Spaces:
Runtime error
Runtime error
window.opts = {}; | |
window.localization = {}; | |
window.titles = {}; | |
let tabSelected = ''; | |
let txt2img_textarea; | |
let img2img_textarea; | |
const wait_time = 800; | |
const token_timeouts = {}; | |
let uiLoaded = false; | |
window.args_to_array = Array.from; // Compatibility with e.g. extensions that may expect this to be around | |
function rememberGallerySelection(name) { | |
// dummy | |
} | |
function set_theme(theme) { | |
const gradioURL = window.location.href; | |
if (!gradioURL.includes('?__theme=')) window.location.replace(`${gradioURL}?__theme=${theme}`); | |
} | |
function update_token_counter(button_id) { | |
if (token_timeouts[button_id]) clearTimeout(token_timeouts[button_id]); | |
token_timeouts[button_id] = setTimeout(() => gradioApp().getElementById(button_id)?.click(), wait_time); | |
} | |
function clip_gallery_urls(gallery) { | |
const files = gallery.map((v) => v.data); | |
navigator.clipboard.writeText(JSON.stringify(files)).then( | |
() => log('clipboard:', files), | |
(err) => console.error('clipboard:', files, err), | |
); | |
} | |
function all_gallery_buttons() { | |
const allGalleryButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnails > .thumbnail-item.thumbnail-small'); | |
const visibleGalleryButtons = []; | |
allGalleryButtons.forEach((elem) => { | |
if (elem.parentElement.offsetParent) visibleGalleryButtons.push(elem); | |
}); | |
return visibleGalleryButtons; | |
} | |
function selected_gallery_button() { | |
const allCurrentButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnail-item.thumbnail-small.selected'); | |
let visibleCurrentButton = null; | |
allCurrentButtons.forEach((elem) => { | |
if (elem.parentElement.offsetParent) visibleCurrentButton = elem; | |
}); | |
return visibleCurrentButton; | |
} | |
function selected_gallery_index() { | |
const buttons = all_gallery_buttons(); | |
const button = selected_gallery_button(); | |
let result = -1; | |
buttons.forEach((v, i) => { if (v === button) { result = i; } }); | |
return result; | |
} | |
function extract_image_from_gallery(gallery) { | |
if (gallery.length === 0) return [null]; | |
if (gallery.length === 1) return [gallery[0]]; | |
let index = selected_gallery_index(); | |
if (index < 0 || index >= gallery.length) index = 0; | |
return [gallery[index]]; | |
} | |
async function setTheme(val, old) { | |
if (!old || val === old) return; | |
old = old.replace('modern/', ''); | |
val = val.replace('modern/', ''); | |
const links = Array.from(document.getElementsByTagName('link')).filter((l) => l.href.includes(old)); | |
if (links.length === 0) { | |
log('setTheme: current theme not matched', old); | |
return; | |
} | |
for (const link of links) { | |
const href = link.href.replace(old, val); | |
const res = await fetch(href); | |
if (res.ok) { | |
log('setTheme:', old, val); | |
link.href = link.href.replace(old, val); | |
} else { | |
log('setTheme: CSS not found', val); | |
} | |
} | |
} | |
function setFontSize(val, old) { | |
const size = val || opts.font_size; | |
if (size === old) return; | |
document.documentElement.style.setProperty('--font-size', `${size}px`); | |
gradioApp().style.setProperty('--font-size', `${size}px`); | |
gradioApp().style.setProperty('--text-xxs', `${size - 3}px`); | |
gradioApp().style.setProperty('--text-xs', `${size - 2}px`); | |
gradioApp().style.setProperty('--text-sm', `${size - 1}px`); | |
gradioApp().style.setProperty('--text-md', `${size}px`); | |
gradioApp().style.setProperty('--text-lg', `${size + 1}px`); | |
gradioApp().style.setProperty('--text-xl', `${size + 2}px`); | |
gradioApp().style.setProperty('--text-xxl', `${size + 3}px`); | |
log('setFontSize', size); | |
} | |
function switchToTab(tab) { | |
const tabs = Array.from(gradioApp().querySelectorAll('#tabs > .tab-nav > button')); | |
const btn = tabs?.find((t) => t.innerText === tab); | |
log('switchToTab', tab); | |
if (btn) btn.click(); | |
} | |
function switch_to_txt2img(...args) { | |
switchToTab('Text'); | |
return Array.from(arguments); | |
} | |
function switch_to_img2img_tab(no) { | |
switchToTab('Image'); | |
gradioApp().getElementById('mode_img2img').querySelectorAll('button')[no].click(); | |
} | |
function switch_to_img2img(...args) { | |
switchToTab('Image'); | |
switch_to_img2img_tab(0); | |
return Array.from(arguments); | |
} | |
function switch_to_sketch(...args) { | |
switchToTab('Image'); | |
switch_to_img2img_tab(1); | |
return Array.from(arguments); | |
} | |
function switch_to_inpaint(...args) { | |
switchToTab('Image'); | |
switch_to_img2img_tab(2); | |
return Array.from(arguments); | |
} | |
function switch_to_inpaint_sketch(...args) { | |
switchToTab('Image'); | |
switch_to_img2img_tab(3); | |
return Array.from(arguments); | |
} | |
function switch_to_extras(...args) { | |
switchToTab('Process'); | |
return Array.from(arguments); | |
} | |
function switch_to_control(...args) { | |
switchToTab('Control'); | |
return Array.from(arguments); | |
} | |
function get_tab_index(tabId) { | |
let res = 0; | |
gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button') | |
.forEach((button, i) => { | |
if (button.className.indexOf('selected') !== -1) res = i; | |
}); | |
return res; | |
} | |
function create_tab_index_args(tabId, args) { | |
const res = Array.from(args); | |
res[0] = get_tab_index(tabId); | |
return res; | |
} | |
function get_img2img_tab_index(...args) { | |
const res = Array.from(arguments); | |
res.splice(-2); | |
res[0] = get_tab_index('mode_img2img'); | |
return res; | |
} | |
function create_submit_args(args) { | |
const res = Array.from(args); | |
// As it is currently, txt2img and img2img send back the previous output args (txt2img_gallery, generation_info, html_info) whenever you generate a new image. | |
// This can lead to uploading a huge gallery of previously generated images, which leads to an unnecessary delay between submitting and beginning to generate. | |
// I don't know why gradio is sending outputs along with inputs, but we can prevent sending the image gallery here, which seems to be an issue for some. | |
// If gradio at some point stops sending outputs, this may break something | |
if (Array.isArray(res[res.length - 3])) res[res.length - 3] = null; | |
return res; | |
} | |
function showSubmitButtons(tabname, show) {} | |
function clearGallery(tabname) { | |
const gallery = gradioApp().getElementById(`${tabname}_gallery`); | |
gallery.classList.remove('logo'); | |
// gallery.style.height = window.innerHeight - gallery.getBoundingClientRect().top - 200 + 'px' | |
const footer = gradioApp().getElementById(`${tabname}_footer`); | |
footer.style.display = 'flex'; | |
} | |
function submit_txt2img(...args) { | |
log('submitTxt'); | |
clearGallery('txt2img'); | |
const id = randomId(); | |
requestProgress(id, null, gradioApp().getElementById('txt2img_gallery')); | |
const res = create_submit_args(args); | |
res[0] = id; | |
return res; | |
} | |
function submit_img2img(...args) { | |
log('submitImg'); | |
clearGallery('img2img'); | |
const id = randomId(); | |
requestProgress(id, null, gradioApp().getElementById('img2img_gallery')); | |
const res = create_submit_args(args); | |
res[0] = id; | |
res[1] = get_tab_index('mode_img2img'); | |
return res; | |
} | |
function submit_control(...args) { | |
log('submitControl'); | |
clearGallery('control'); | |
const id = randomId(); | |
requestProgress(id, null, gradioApp().getElementById('control_gallery')); | |
const res = create_submit_args(args); | |
res[0] = id; | |
res[1] = gradioApp().querySelector('#control-tabs > .tab-nav > .selected')?.innerText.toLowerCase() || ''; // selected tab name | |
return res; | |
} | |
function submit_postprocessing(...args) { | |
log('SubmitExtras'); | |
clearGallery('extras'); | |
return args; | |
} | |
window.submit = submit_txt2img; | |
function modelmerger(...args) { | |
const id = randomId(); | |
const res = create_submit_args(args); | |
res[0] = id; | |
return res; | |
} | |
function clearPrompts(prompt, negative_prompt) { | |
prompt = ''; | |
negative_prompt = ''; | |
return [prompt, negative_prompt]; | |
} | |
const promptTokenCountUpdateFuncs = {}; | |
function recalculatePromptTokens(name) { | |
if (promptTokenCountUpdateFuncs[name]) { | |
promptTokenCountUpdateFuncs[name](); | |
} | |
} | |
function recalculate_prompts_txt2img(...args) { | |
recalculatePromptTokens('txt2img_prompt'); | |
recalculatePromptTokens('txt2img_neg_prompt'); | |
return Array.from(arguments); | |
} | |
function recalculate_prompts_img2img(...args) { | |
recalculatePromptTokens('img2img_prompt'); | |
recalculatePromptTokens('img2img_neg_prompt'); | |
return Array.from(arguments); | |
} | |
function recalculate_prompts_inpaint(...args) { | |
recalculatePromptTokens('img2img_prompt'); | |
recalculatePromptTokens('img2img_neg_prompt'); | |
return Array.from(arguments); | |
} | |
function recalculate_prompts_control(...args) { | |
recalculatePromptTokens('control_prompt'); | |
recalculatePromptTokens('control_neg_prompt'); | |
return Array.from(arguments); | |
} | |
function registerDragDrop() { | |
const qs = gradioApp().getElementById('quicksettings'); | |
if (!qs) return; | |
qs.addEventListener('dragover', (evt) => { | |
evt.preventDefault(); | |
evt.dataTransfer.dropEffect = 'copy'; | |
}); | |
qs.addEventListener('drop', (evt) => { | |
evt.preventDefault(); | |
evt.dataTransfer.dropEffect = 'copy'; | |
for (const f of evt.dataTransfer.files) { | |
log('QuickSettingsDrop', f); | |
} | |
}); | |
} | |
function sortUIElements() { | |
// sort top-level tabs | |
const currSelected = gradioApp()?.querySelector('.tab-nav > .selected')?.innerText; | |
if (currSelected === tabSelected || !opts.ui_tab_reorder) return; | |
tabSelected = currSelected; | |
const tabs = gradioApp().getElementById('tabs')?.children[0]; | |
if (!tabs) return; | |
let tabsOrder = opts.ui_tab_reorder?.split(',').map((el) => el.trim().toLowerCase()) || []; | |
for (const el of Array.from(tabs.children)) { | |
const elIndex = tabsOrder.indexOf(el.innerText.toLowerCase()); | |
if (elIndex > -1) el.style.order = elIndex - 50; // default is 0 so setting to negative values | |
} | |
// sort always-on scripts | |
const find = (el, ordered) => { | |
for (const i in ordered) { | |
if (el.innerText.toLowerCase().startsWith(ordered[i])) return i; | |
} | |
return 99; | |
}; | |
tabsOrder = opts.ui_scripts_reorder?.split(',').map((el) => el.trim().toLowerCase()) || []; | |
const scriptsTxt = gradioApp().getElementById('scripts_alwayson_txt2img').children; | |
for (const el of Array.from(scriptsTxt)) el.style.order = find(el, tabsOrder); | |
const scriptsImg = gradioApp().getElementById('scripts_alwayson_img2img').children; | |
for (const el of Array.from(scriptsImg)) el.style.order = find(el, tabsOrder); | |
log('sortUIElements'); | |
} | |
onAfterUiUpdate(async () => { | |
let promptsInitialized = false; | |
async function registerTextarea(id, id_counter, id_button) { | |
const prompt = gradioApp().getElementById(id); | |
if (!prompt) return; | |
const counter = gradioApp().getElementById(id_counter); | |
const localTextarea = gradioApp().querySelector(`#${id} > label > textarea`); | |
if (counter.parentElement === prompt.parentElement) return; | |
prompt.parentElement.insertBefore(counter, prompt); | |
prompt.parentElement.style.position = 'relative'; | |
promptTokenCountUpdateFuncs[id] = () => { update_token_counter(id_button); }; | |
localTextarea.addEventListener('input', promptTokenCountUpdateFuncs[id]); | |
if (!promptsInitialized) log('initPrompts'); | |
promptsInitialized = true; | |
} | |
// sortUIElements(); | |
registerTextarea('txt2img_prompt', 'txt2img_token_counter', 'txt2img_token_button'); | |
registerTextarea('txt2img_neg_prompt', 'txt2img_negative_token_counter', 'txt2img_negative_token_button'); | |
registerTextarea('img2img_prompt', 'img2img_token_counter', 'img2img_token_button'); | |
registerTextarea('img2img_neg_prompt', 'img2img_negative_token_counter', 'img2img_negative_token_button'); | |
registerTextarea('control_prompt', 'control_token_counter', 'control_token_button'); | |
registerTextarea('control_neg_prompt', 'control_negative_token_counter', 'control_negative_token_button'); | |
}); | |
function update_txt2img_tokens(...args) { | |
update_token_counter('txt2img_token_button'); | |
if (args.length === 2) return args[0]; | |
return args; | |
} | |
function update_img2img_tokens(...args) { | |
update_token_counter('img2img_token_button'); | |
if (args.length === 2) return args[0]; | |
return args; | |
} | |
function getTranslation(...args) { | |
return null; | |
} | |
function monitorServerStatus() { | |
document.open(); | |
document.write(` | |
<html> | |
<head><title>SD.Next</title></head> | |
<body style="background: #222222; font-size: 1rem; font-family:monospace; margin-top:20%; color:lightgray; text-align:center"> | |
<h1>Waiting for server...</h1> | |
<script> | |
function monitorServerStatus() { | |
fetch('/sdapi/v1/progress?skip_current_image=true') | |
.then((res) => { !res?.ok ? setTimeout(monitorServerStatus, 1000) : location.reload(); }) | |
.catch((e) => setTimeout(monitorServerStatus, 1000)) | |
} | |
window.onload = () => monitorServerStatus(); | |
</script> | |
</body> | |
</html> | |
`); | |
document.close(); | |
} | |
function restartReload() { | |
document.body.style = 'background: #222222; font-size: 1rem; font-family:monospace; margin-top:20%; color:lightgray; text-align:center'; | |
document.body.innerHTML = '<h1>Server shutdown in progress...</h1>'; | |
fetch('/sdapi/v1/progress?skip_current_image=true') | |
.then((res) => setTimeout(restartReload, 1000)) | |
.catch((e) => setTimeout(monitorServerStatus, 500)); | |
return []; | |
} | |
function updateInput(target) { | |
const e = new Event('input', { bubbles: true }); | |
Object.defineProperty(e, 'target', { value: target }); | |
target.dispatchEvent(e); | |
} | |
let desiredCheckpointName = null; | |
function selectCheckpoint(name) { | |
desiredCheckpointName = name; | |
const tabname = getENActiveTab(); | |
const btnModel = gradioApp().getElementById(`${tabname}_extra_model`); | |
const isRefiner = btnModel && btnModel.classList.contains('toolbutton-selected'); | |
if (isRefiner) gradioApp().getElementById('change_refiner').click(); | |
else gradioApp().getElementById('change_checkpoint').click(); | |
log(`Change ${isRefiner ? 'refiner' : 'model'}: ${desiredCheckpointName}`); | |
} | |
let desiredVAEName = null; | |
function selectVAE(name) { | |
desiredVAEName = name; | |
gradioApp().getElementById('change_vae').click(); | |
log(`Change VAE: ${desiredVAEName}`); | |
} | |
function selectReference(name) { | |
desiredCheckpointName = name; | |
gradioApp().getElementById('change_reference').click(); | |
} | |
function currentImageResolutionimg2img(_a, _b, scaleBy) { | |
const img = gradioApp().querySelector('#mode_img2img > div[style="display: block;"] img'); | |
return img ? [img.naturalWidth, img.naturalHeight, scaleBy] : [0, 0, scaleBy]; | |
} | |
function currentImageResolutioncontrol(_a, _b, scaleBy) { | |
const img = gradioApp().querySelector('#control-tab-input > div[style="display: block;"] img'); | |
return img ? [img.naturalWidth, img.naturalHeight, scaleBy] : [0, 0, scaleBy]; | |
} | |
function updateImg2imgResizeToTextAfterChangingImage() { | |
setTimeout(() => gradioApp().getElementById('img2img_update_resize_to').click(), 500); | |
return []; | |
} | |
function createThemeElement() { | |
const el = document.createElement('img'); | |
el.id = 'theme-preview'; | |
el.className = 'theme-preview'; | |
el.onclick = () => { el.style.display = 'none'; }; | |
document.body.appendChild(el); | |
return el; | |
} | |
function toggleCompact(val, old) { | |
if (val === old) return; | |
log('toggleCompact', val, old); | |
if (val) { | |
gradioApp().style.setProperty('--layout-gap', 'var(--spacing-md)'); | |
gradioApp().querySelectorAll('input[type=range]').forEach((el) => el.classList.add('hidden')); | |
gradioApp().querySelectorAll('div .form').forEach((el) => el.classList.add('form-compact')); | |
gradioApp().querySelectorAll('.small-accordion .label-wrap').forEach((el) => el.classList.add('accordion-compact')); | |
} else { | |
gradioApp().style.setProperty('--layout-gap', 'var(--spacing-xxl)'); | |
gradioApp().querySelectorAll('input[type=range]').forEach((el) => el.classList.remove('hidden')); | |
gradioApp().querySelectorAll('div .form').forEach((el) => el.classList.remove('form-compact')); | |
gradioApp().querySelectorAll('.small-accordion .label-wrap').forEach((el) => el.classList.remove('accordion-compact')); | |
} | |
} | |
function previewTheme() { | |
let name = gradioApp().getElementById('setting_gradio_theme').querySelectorAll('input')?.[0].value || ''; | |
fetch('/file=html/themes.json').then((res) => { | |
res.json().then((themes) => { | |
const theme = themes.find((t) => t.id === name); | |
if (theme) { | |
window.open(theme.subdomain, '_blank'); | |
} else { | |
const el = document.getElementById('theme-preview') || createThemeElement(); | |
el.style.display = el.style.display === 'block' ? 'none' : 'block'; | |
name = name.replace('/', '-'); | |
el.src = `/file=html/${name}.jpg`; | |
} | |
}); | |
}); | |
} | |
async function browseFolder() { | |
const f = await window.showDirectoryPicker(); | |
if (f && f.kind === 'directory') return f.name; | |
return null; | |
} | |
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); | |
} | |
uiLoaded = true; | |
const sd_model = gradioApp().getElementById('setting_sd_model_checkpoint'); | |
let loadingStarted = 0; | |
let loadingMonitor = 0; | |
const sd_model_callback = () => { | |
const loading = sd_model.querySelector('.eta-bar'); | |
if (!loading) { | |
loadingStarted = 0; | |
clearInterval(loadingMonitor); | |
} else if (loadingStarted === 0) { | |
loadingStarted = Date.now(); | |
loadingMonitor = setInterval(() => { | |
const elapsed = Date.now() - loadingStarted; | |
if (elapsed > 3000 && loading) loading.style.display = 'none'; | |
}, 5000); | |
} | |
}; | |
const sd_model_observer = new MutationObserver(sd_model_callback); | |
sd_model_observer.observe(sd_model, { attributes: true, childList: true, subtree: true }); | |
log('reconnectUI'); | |
} | |
const start_check = setInterval(reconnectUI, 100); | |