reorganize js callbacks and startup sequence

This commit is contained in:
Vladimir Mandic
2024-04-04 18:26:51 -04:00
parent 77db12765d
commit 9d04255b54
22 changed files with 98 additions and 80 deletions
+1
View File
@@ -50,6 +50,7 @@
"optionsChangedCallbacks": "readonly",
"onUiLoaded": "readonly",
"onUiUpdate": "readonly",
"onUiTabChange": "readonly",
"uiCurrentTab": "writable",
"uiElementIsVisible": "readonly",
"uiElementInSight": "readonly",
+1
View File
@@ -40,6 +40,7 @@
- Styles apply wildcards to params
- Make metadata in full screen viewer optional
- Add VAE civitai scan metadata/preview
- More efficient in-browser callbacks
- **IPEX**
- update to *IPEX 2.1.20* on Linux
requires removing the venv folder to update properly
+1 -3
View File
@@ -113,7 +113,5 @@ async function initContextMenu() {
appendContextMenuOption(id, 'nVidia overlay', initNVML);
}
}
addContextMenuEventListener();
}
onUiLoaded(initContextMenu);
onAfterUiUpdate(() => addContextMenuEventListener());
-2
View File
@@ -42,5 +42,3 @@ async function setupControlUI() {
log('initControlUI');
}
onUiLoaded(setupControlUI);
-2
View File
@@ -481,5 +481,3 @@ async function setupExtraNetworks() {
registerPrompt('control', 'control_neg_prompt');
log('initExtraNetworks');
}
onUiLoaded(setupExtraNetworks);
+2 -3
View File
@@ -383,8 +383,8 @@ async function galleryHidden() {
if (pruneImagesTimer) clearInterval(pruneImagesTimer);
}
async function galleryObserve() { // triggered on gradio change to monitor when ui gets sufficiently constructed
log('initBrowser');
async function initGallery() { // triggered on gradio change to monitor when ui gets sufficiently constructed
log('initGallery');
el.folders = gradioApp().getElementById('tab-gallery-folders');
el.files = gradioApp().getElementById('tab-gallery-files');
el.status = gradioApp().getElementById('tab-gallery-status');
@@ -403,4 +403,3 @@ async function galleryObserve() { // triggered on gradio change to monitor when
customElements.define('gallery-folder', GalleryFolder);
customElements.define('gallery-file', GalleryFile);
onUiLoaded(galleryObserve);
-6
View File
@@ -16,10 +16,8 @@ function attachGalleryListeners(tab_name) {
let txt2img_gallery;
let img2img_gallery;
let modal;
let generationParamsInitialized = false;
async function initiGenerationParams() {
if (generationParamsInitialized) return;
if (!modal) modal = gradioApp().getElementById('lightboxModal');
if (!modal) return;
@@ -33,10 +31,6 @@ async function initiGenerationParams() {
if (!txt2img_gallery) txt2img_gallery = attachGalleryListeners('txt2img');
if (!img2img_gallery) img2img_gallery = attachGalleryListeners('img2img');
if (txt2img_gallery && img2img_gallery) generationParamsInitialized = true;
else return;
modalObserver.observe(modal, { attributes: true, attributeFilter: ['style'] });
log('initGenerationParams');
}
onAfterUiUpdate(initiGenerationParams);
-6
View File
@@ -1,8 +1,4 @@
let dragDropInitialized = false;
async function initDragDrop() {
if (dragDropInitialized) return;
dragDropInitialized = true;
log('initDragDrop');
window.addEventListener('drop', (e) => {
const target = e.composedPath()[0];
@@ -26,5 +22,3 @@ async function initDragDrop() {
}
});
}
onAfterUiUpdate(initDragDrop);
-7
View File
@@ -159,8 +159,6 @@ function modalResetInstance(event) {
previewInstance = panzoom(modalImage, { zoomSpeed: 0.05, minZoom: 0.1, maxZoom: 5.0, filterKey: (/* e, dx, dy, dz */) => true });
}
let imageViewerInitialized = false;
function galleryClickEventHandler(event) {
if (event.button !== 0) return;
if (event.target.nodeName === 'IMG' && !event.target.parentNode.classList.contains('thumbnail-item')) {
@@ -183,9 +181,6 @@ async function initImageViewer() {
}
}
}
if (imageViewerInitialized) return;
imageViewerInitialized = true;
// main elements
const modal = document.createElement('div');
modal.id = 'lightboxModal';
@@ -286,5 +281,3 @@ async function initImageViewer() {
gradioApp().appendChild(modal);
log('initImageViewer');
}
onAfterUiUpdate(initImageViewer);
-7
View File
@@ -74,10 +74,3 @@ async function put(record) {
request.onerror = (evt) => reject(evt);
});
}
window.idbAdd = add;
window.idbDel = del;
window.idbGet = get;
window.idbPut = put;
onUiLoaded(initIndexDB);
-6
View File
@@ -59,13 +59,9 @@ async function logMonitor() {
}
}
let logMonitorInitialized = false;
async function initLogMonitor() {
if (logMonitorInitialized) return;
const el = document.getElementsByTagName('footer')[0];
if (!el) return;
logMonitorInitialized = true;
el.classList.add('log-monitor');
el.innerHTML = `
<table id="logMonitor" style="width: 100%;">
@@ -89,5 +85,3 @@ async function initLogMonitor() {
logMonitor();
log('initLogMonitor');
}
onAfterUiUpdate(initLogMonitor);
+1 -3
View File
@@ -3,7 +3,7 @@
let lastHeadImg = null;
let notificationButton = null;
function initNotifications() {
async function initNotifications() {
if (!notificationButton) {
notificationButton = gradioApp().getElementById('request_notifications');
if (notificationButton) notificationButton.addEventListener('click', (evt) => Notification.requestPermission(), true);
@@ -28,5 +28,3 @@ function initNotifications() {
};
log('sendNotification');
}
onAfterUiUpdate(initNotifications);
+3 -7
View File
@@ -3,8 +3,6 @@
// Counts open and closed brackets (round, square, curly) in the prompt and negative prompt text boxes in the txt2img and img2img tabs.
// If there's a mismatch, the keyword counter turns red and if you hover on it, a tooltip tells you what's wrong.
let promptCheckerInitialized = false;
function checkBrackets(textArea, counterElt) {
const counts = {};
const errors = [];
@@ -25,17 +23,15 @@ function setupBracketChecking(idPrompt, idCounter) {
const textarea = gradioApp().querySelector(`#${idPrompt} > label > textarea`);
const counter = gradioApp().getElementById(idCounter);
if (!textarea || !counter) return;
if (!promptCheckerInitialized) log('initPromptChecker');
promptCheckerInitialized = true;
textarea.addEventListener('input', () => checkBrackets(textarea, counter));
}
onAfterUiUpdate(() => {
if (promptCheckerInitialized) return;
async function initPromptChecker() {
log('initPromptChecker');
setupBracketChecking('txt2img_prompt', 'txt2img_token_counter');
setupBracketChecking('txt2img_neg_prompt', 'txt2img_negative_token_counter');
setupBracketChecking('img2img_prompt', 'img2img_token_counter');
setupBracketChecking('img2img_neg_prompt', 'img2img_negative_token_counter');
setupBracketChecking('control_prompt', 'control_token_counter');
setupBracketChecking('control_neg_prompt', 'control_negative_token_counter');
});
}
+35 -15
View File
@@ -10,6 +10,10 @@ const debug = (...msg) => {
console.debug(ts, ...msg); // eslint-disable-line no-console
};
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms)); // eslint-disable-line no-promise-executor-return
}
function gradioApp() {
const elems = document.getElementsByTagName('gradio-app');
const elem = elems.length === 0 ? document : elems[0];
@@ -30,6 +34,7 @@ const get_uiCurrentTab = getUICurrentTab;
const uiAfterUpdateCallbacks = [];
const uiUpdateCallbacks = [];
const uiLoadedCallbacks = [];
const uiReadyCallbacks = [];
const uiTabChangeCallbacks = [];
const optionsChangedCallbacks = [];
let uiCurrentTab = null;
@@ -47,6 +52,10 @@ function onUiLoaded(callback) {
uiLoadedCallbacks.push(callback);
}
function onUiReady(callback) {
uiReadyCallbacks.push(callback);
}
function onUiTabChange(callback) {
uiTabChangeCallbacks.push(callback);
}
@@ -72,23 +81,34 @@ function scheduleAfterUiUpdateCallbacks() {
}
let executedOnLoaded = false;
const ignoreElements = ['logMonitorData', 'logWarnings', 'logErrors', 'tooltip-container'];
const ignoreClasses = ['wrap'];
async function mutationCallback(mutations) {
let validMutations = mutations;
validMutations = validMutations.filter((m) => m.target.nodeName !== 'LABEL');
validMutations = validMutations.filter((m) => ignoreElements.indexOf(m.target.id) === -1);
validMutations = validMutations.filter((m) => m.target.id !== 'logWarnings' && m.target.id !== 'logErrors');
validMutations = validMutations.filter((m) => !m.target.classList?.contains('wrap'));
if (validMutations.length < 1) return;
if (!executedOnLoaded && gradioApp().getElementById('txt2img_prompt')) { // execute once
executedOnLoaded = true;
executeCallbacks(uiLoadedCallbacks);
}
if (executedOnLoaded) { // execute on each mutation
executeCallbacks(uiUpdateCallbacks, mutations);
scheduleAfterUiUpdateCallbacks();
}
const newTab = getUICurrentTab();
if (newTab && (newTab !== uiCurrentTab)) {
uiCurrentTab = newTab;
executeCallbacks(uiTabChangeCallbacks);
}
}
document.addEventListener('DOMContentLoaded', () => {
const mutationObserver = new MutationObserver((m) => {
if (!executedOnLoaded && gradioApp().getElementById('txt2img_prompt')) {
executedOnLoaded = true;
executeCallbacks(uiLoadedCallbacks);
}
if (executedOnLoaded) {
executeCallbacks(uiUpdateCallbacks, m);
scheduleAfterUiUpdateCallbacks();
}
const newTab = getUICurrentTab();
if (newTab && (newTab !== uiCurrentTab)) {
uiCurrentTab = newTab;
executeCallbacks(uiTabChangeCallbacks);
}
});
const mutationObserver = new MutationObserver(mutationCallback);
mutationObserver.observe(gradioApp(), { childList: true, subtree: true });
});
+2 -1
View File
@@ -107,11 +107,12 @@ async function setHints() {
const t1 = performance.now();
log('setHints', { type: localeData.type, elements: elements.length, localized, hints, data: localeData.data.length, time: t1 - t0 });
// sortUIElements();
removeSplash();
// validateHints(elements, localeData.data);
}
/*
onAfterUiUpdate(async () => {
if (localeData.timeout) clearTimeout(localeData.timeout);
localeData.timeout = setTimeout(setHints, 250);
});
*/
-3
View File
@@ -195,6 +195,3 @@ async function initSettings() {
});
log('initSettings');
}
onUiLoaded(initSettings);
onUiLoaded(initModels);
+44
View File
@@ -0,0 +1,44 @@
/* eslint-disable no-undef */
async function initStartup() {
log('initStartup');
// all items here are non-blocking async calls
initModels();
getUIDefaults();
initiGenerationParams();
initNotifications();
initPromptChecker();
initLogMonitor();
initContextMenu();
initDragDrop();
initSettings();
initImageViewer();
initGallery();
setupControlUI();
setupExtraNetworks();
// reconnect server session
await reconnectUI();
// make sure all of the ui is ready and options are loaded
while (Object.keys(window.opts).length === 0) await sleep(50);
executeCallbacks(uiReadyCallbacks);
// optinally wait for modern ui
if (window.waitForUiUxReady) await window.waitForUiUxReady();
removeSplash();
// post startup tasks that may take longer but are not critical
setHints();
initIndexDB();
}
onUiLoaded(initStartup);
onUiReady(() => log('uiReady'));
// onAfterUiUpdate(() => log('evt onAfterUiUpdate'));
// onUiLoaded(() => log('evt onUiLoaded'));
// onOptionsChanged(() => log('evt onOptionsChanged'));
// onUiTabChange(() => log('evt onUiTabChange'));
// onUiUpdate(() => log('evt onUiUpdate'));
-4
View File
@@ -492,11 +492,9 @@ async function browseFolder() {
async function reconnectUI() {
const gallery = gradioApp().getElementById('txt2img_gallery');
if (!gallery) return;
const task_id = localStorage.getItem('task');
const api_logo = Array.from(gradioApp().querySelectorAll('img')).filter((el) => el?.src?.endsWith('api-logo.svg'));
if (api_logo.length > 0) api_logo[0].remove();
clearInterval(start_check); // eslint-disable-line no-use-before-define
if (task_id) {
debug('task check:', task_id);
requestProgress(task_id, null, gallery, null, null, true);
@@ -524,5 +522,3 @@ async function reconnectUI() {
sd_model_observer.observe(sd_model, { attributes: true, childList: true, subtree: true });
log('reconnectUI');
}
const start_check = setInterval(reconnectUI, 100);
+1 -3
View File
@@ -10,7 +10,7 @@ function uiOpenSubmenus() {
return states;
}
function getUIDefaults() {
async function getUIDefaults() {
const btn = gradioApp().getElementById('ui_defaults_view');
if (!btn) return;
const intersectionObserver = new IntersectionObserver((entries) => {
@@ -19,5 +19,3 @@ function getUIDefaults() {
});
intersectionObserver.observe(btn); // monitor visibility of tab
}
onUiLoaded(getUIDefaults);
+4 -1
View File
@@ -530,6 +530,7 @@ def control_run(units: List[unit.Unit] = [], inputs: List[Image.Image] = [], ini
# pipeline
output = None
script_run = False
if pipe is not None: # run new pipeline
pipe.restore_pipeline = restore_pipeline
debug(f'Control exec pipeline: task={sd_models.get_diffusers_task(pipe)} class={pipe.__class__}')
@@ -549,6 +550,8 @@ def control_run(units: List[unit.Unit] = [], inputs: List[Image.Image] = [], ini
processed = p.scripts.run(p, *p.script_args)
if processed is None:
processed: processing.Processed = processing.process_images(p) # run actual pipeline
else:
script_run = True
output = processed.images if processed is not None else None
# output = pipe(**vars(p)).images # alternative direct pipe exec call
else: # blend all processed images and return
@@ -570,7 +573,7 @@ def control_run(units: List[unit.Unit] = [], inputs: List[Image.Image] = [], ini
output_image = images.resize_image(resize_mode_after, output_image, width_after, height_after, resize_name_after)
output_images.append(output_image)
if shared.opts.include_mask:
if shared.opts.include_mask and not script_run:
if processed_image is not None and isinstance(processed_image, Image.Image):
output_images.append(processed_image)
+2 -1
View File
@@ -280,7 +280,8 @@ def create_resize_inputs(tab, images, accordion=True, latent=False):
res_switch_btn = ToolButton(value=ui_symbols.switch, elem_id=f"{tab}_res_switch_btn")
res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress=False)
detect_image_size_btn = ToolButton(value=ui_symbols.detect, elem_id=f"{tab}_detect_image_size_btn")
detect_image_size_btn.click(fn=lambda w, h, _: (w or gr.update(), h or gr.update()), _js=f'currentImageResolution{tab}', inputs=[dummy_component, dummy_component, dummy_component], outputs=[width, height], show_progress=False)
el = tab.split('_')[0]
detect_image_size_btn.click(fn=lambda w, h, _: (w or gr.update(), h or gr.update()), _js=f'currentImageResolution{el}', inputs=[dummy_component, dummy_component, dummy_component], outputs=[width, height], show_progress=False)
with gr.Tab(label="Scale") as tab_scale_by:
scale_by = gr.Slider(minimum=0.05, maximum=8.0, step=0.05, label="Scale", value=1.0, elem_id=f"{tab}_scale")
for component in images:
+1
View File
@@ -1981,6 +1981,7 @@ class Script(scripts.Script):
# run pipeline
processed: processing.Processed = processing.process_images(p) # runs processing using main loop
if shared.opts.include_mask:
p.image_mask = image_mask
if image_mask is not None and isinstance(image_mask, Image.Image):
processed.images.append(image_mask)