mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 17:24:32 +02:00
reorganize js callbacks and startup sequence
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
"optionsChangedCallbacks": "readonly",
|
||||
"onUiLoaded": "readonly",
|
||||
"onUiUpdate": "readonly",
|
||||
"onUiTabChange": "readonly",
|
||||
"uiCurrentTab": "writable",
|
||||
"uiElementIsVisible": "readonly",
|
||||
"uiElementInSight": "readonly",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -113,7 +113,5 @@ async function initContextMenu() {
|
||||
appendContextMenuOption(id, 'nVidia overlay', initNVML);
|
||||
}
|
||||
}
|
||||
addContextMenuEventListener();
|
||||
}
|
||||
|
||||
onUiLoaded(initContextMenu);
|
||||
onAfterUiUpdate(() => addContextMenuEventListener());
|
||||
|
||||
@@ -42,5 +42,3 @@ async function setupControlUI() {
|
||||
|
||||
log('initControlUI');
|
||||
}
|
||||
|
||||
onUiLoaded(setupControlUI);
|
||||
|
||||
@@ -481,5 +481,3 @@ async function setupExtraNetworks() {
|
||||
registerPrompt('control', 'control_neg_prompt');
|
||||
log('initExtraNetworks');
|
||||
}
|
||||
|
||||
onUiLoaded(setupExtraNetworks);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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
@@ -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 });
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
*/
|
||||
|
||||
@@ -195,6 +195,3 @@ async function initSettings() {
|
||||
});
|
||||
log('initSettings');
|
||||
}
|
||||
|
||||
onUiLoaded(initSettings);
|
||||
onUiLoaded(initModels);
|
||||
|
||||
@@ -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'));
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user