stable-diffusion-webui

Форк
0
199 строк · 6.0 Кб
1
function gradioApp() {
2
    const elems = document.getElementsByTagName('gradio-app');
3
    const elem = elems.length == 0 ? document : elems[0];
4

5
    if (elem !== document) {
6
        elem.getElementById = function(id) {
7
            return document.getElementById(id);
8
        };
9
    }
10
    return elem.shadowRoot ? elem.shadowRoot : elem;
11
}
12

13
/**
14
 * Get the currently selected top-level UI tab button (e.g. the button that says "Extras").
15
 */
16
function get_uiCurrentTab() {
17
    return gradioApp().querySelector('#tabs > .tab-nav > button.selected');
18
}
19

20
/**
21
 * Get the first currently visible top-level UI tab content (e.g. the div hosting the "txt2img" UI).
22
 */
23
function get_uiCurrentTabContent() {
24
    return gradioApp().querySelector('#tabs > .tabitem[id^=tab_]:not([style*="display: none"])');
25
}
26

27
var uiUpdateCallbacks = [];
28
var uiAfterUpdateCallbacks = [];
29
var uiLoadedCallbacks = [];
30
var uiTabChangeCallbacks = [];
31
var optionsChangedCallbacks = [];
32
var uiAfterUpdateTimeout = null;
33
var uiCurrentTab = null;
34

35
/**
36
 * Register callback to be called at each UI update.
37
 * The callback receives an array of MutationRecords as an argument.
38
 */
39
function onUiUpdate(callback) {
40
    uiUpdateCallbacks.push(callback);
41
}
42

43
/**
44
 * Register callback to be called soon after UI updates.
45
 * The callback receives no arguments.
46
 *
47
 * This is preferred over `onUiUpdate` if you don't need
48
 * access to the MutationRecords, as your function will
49
 * not be called quite as often.
50
 */
51
function onAfterUiUpdate(callback) {
52
    uiAfterUpdateCallbacks.push(callback);
53
}
54

55
/**
56
 * Register callback to be called when the UI is loaded.
57
 * The callback receives no arguments.
58
 */
59
function onUiLoaded(callback) {
60
    uiLoadedCallbacks.push(callback);
61
}
62

63
/**
64
 * Register callback to be called when the UI tab is changed.
65
 * The callback receives no arguments.
66
 */
67
function onUiTabChange(callback) {
68
    uiTabChangeCallbacks.push(callback);
69
}
70

71
/**
72
 * Register callback to be called when the options are changed.
73
 * The callback receives no arguments.
74
 * @param callback
75
 */
76
function onOptionsChanged(callback) {
77
    optionsChangedCallbacks.push(callback);
78
}
79

80
function executeCallbacks(queue, arg) {
81
    for (const callback of queue) {
82
        try {
83
            callback(arg);
84
        } catch (e) {
85
            console.error("error running callback", callback, ":", e);
86
        }
87
    }
88
}
89

90
/**
91
 * Schedule the execution of the callbacks registered with onAfterUiUpdate.
92
 * The callbacks are executed after a short while, unless another call to this function
93
 * is made before that time. IOW, the callbacks are executed only once, even
94
 * when there are multiple mutations observed.
95
 */
96
function scheduleAfterUiUpdateCallbacks() {
97
    clearTimeout(uiAfterUpdateTimeout);
98
    uiAfterUpdateTimeout = setTimeout(function() {
99
        executeCallbacks(uiAfterUpdateCallbacks);
100
    }, 200);
101
}
102

103
var executedOnLoaded = false;
104

105
document.addEventListener("DOMContentLoaded", function() {
106
    var mutationObserver = new MutationObserver(function(m) {
107
        if (!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')) {
108
            executedOnLoaded = true;
109
            executeCallbacks(uiLoadedCallbacks);
110
        }
111

112
        executeCallbacks(uiUpdateCallbacks, m);
113
        scheduleAfterUiUpdateCallbacks();
114
        const newTab = get_uiCurrentTab();
115
        if (newTab && (newTab !== uiCurrentTab)) {
116
            uiCurrentTab = newTab;
117
            executeCallbacks(uiTabChangeCallbacks);
118
        }
119
    });
120
    mutationObserver.observe(gradioApp(), {childList: true, subtree: true});
121
});
122

123
/**
124
 * Add keyboard shortcuts:
125
 * Ctrl+Enter to start/restart a generation
126
 * Alt/Option+Enter to skip a generation
127
 * Esc to interrupt a generation
128
 */
129
document.addEventListener('keydown', function(e) {
130
    const isEnter = e.key === 'Enter' || e.keyCode === 13;
131
    const isCtrlKey = e.metaKey || e.ctrlKey;
132
    const isAltKey = e.altKey;
133
    const isEsc = e.key === 'Escape';
134

135
    const generateButton = get_uiCurrentTabContent().querySelector('button[id$=_generate]');
136
    const interruptButton = get_uiCurrentTabContent().querySelector('button[id$=_interrupt]');
137
    const skipButton = get_uiCurrentTabContent().querySelector('button[id$=_skip]');
138

139
    if (isCtrlKey && isEnter) {
140
        if (interruptButton.style.display === 'block') {
141
            interruptButton.click();
142
            const callback = (mutationList) => {
143
                for (const mutation of mutationList) {
144
                    if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
145
                        if (interruptButton.style.display === 'none') {
146
                            generateButton.click();
147
                            observer.disconnect();
148
                        }
149
                    }
150
                }
151
            };
152
            const observer = new MutationObserver(callback);
153
            observer.observe(interruptButton, {attributes: true});
154
        } else {
155
            generateButton.click();
156
        }
157
        e.preventDefault();
158
    }
159

160
    if (isAltKey && isEnter) {
161
        skipButton.click();
162
        e.preventDefault();
163
    }
164

165
    if (isEsc) {
166
        const globalPopup = document.querySelector('.global-popup');
167
        const lightboxModal = document.querySelector('#lightboxModal');
168
        if (!globalPopup || globalPopup.style.display === 'none') {
169
            if (document.activeElement === lightboxModal) return;
170
            if (interruptButton.style.display === 'block') {
171
                interruptButton.click();
172
                e.preventDefault();
173
            }
174
        }
175
    }
176
});
177

178
/**
179
 * checks that a UI element is not in another hidden element or tab content
180
 */
181
function uiElementIsVisible(el) {
182
    if (el === document) {
183
        return true;
184
    }
185

186
    const computedStyle = getComputedStyle(el);
187
    const isVisible = computedStyle.display !== 'none';
188

189
    if (!isVisible) return false;
190
    return uiElementIsVisible(el.parentNode);
191
}
192

193
function uiElementInSight(el) {
194
    const clRect = el.getBoundingClientRect();
195
    const windowHeight = window.innerHeight;
196
    const isOnScreen = clRect.bottom > 0 && clRect.top < windowHeight;
197

198
    return isOnScreen;
199
}
200

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.