window.state = window.state || {}; state = window.state; let selectingQueue = 0; // 默认都延时一下再开始触发 state.utils = { testFunction: function testFunction() { //console.log(state.extensions) // const button = gradioApp().getElementById("lightdiffusionflow_set_elements"); // button.click(); value = "新建文件夹\\anything-v5-PrtRE.safetensors" value = value.replace("/","\\") parts = value.split("\\") console.log(parts[parts.length - 1]) }, target_is_newer_version: function(cur_version, target_version){ let cur = cur_version.replace("v","") cur = cur.split(".") let target = target_version.replace("v","") target = target.split(".") let version_len = Math.min(cur.length, target.length) // 逐个版本号比较 v1.2.3 和 v1.2比较时,只比较前面两个数字 for (let i=0; i < version_len; i++){ if(Number(cur[i]) > Number(target[i])){ return false } else if(Number(cur[i]) < Number(target[i])){ return true } } // 前面的版本号一样,再看谁的版本号更长 if(cur.length >= target.length){ return false } return true }, searchCheckPointByHash: async function searchCheckPointByHash(hash){ let downloadUrl = undefined hash_str = hash.replace("[","").replace("]","").replace(/^\s+|\s+$/g,"") await fetch("https://civitai.com/api/v1/model-versions/by-hash/"+hash_str) .then(response => response.json()) .then(data => { //try{ //console.log(data["files"]) for (file of data["files"]){ for (key of Object.keys(file["hashes"])){ if(file["hashes"][key].toLowerCase() === hash_str.toLowerCase()) { downloadUrl = file["downloadUrl"] console.log(downloadUrl) break } } } if(downloadUrl == undefined){downloadUrl = data["files"][0]["downloadUrl"]} //} catch (error) {} }).catch(function(e) { console.log("search model error!"); }); return downloadUrl }, getTranslation: function getTranslation(key){ new_key = key try{ if(window.localization[new_key.replace(/^\s+|\s+$/g,"")] != undefined){ new_key = window.localization[new_key] } } catch (error) { console.warn('getTranslation error:', error); } return new_key }, reverseTranslation: function reverseTranslation(key){ new_key = [] try{ //key=key.replace(/^\s+|\s+$/g,""); for (localize_key of Object.keys(window.localization)) { if(key.replace(/^\s+|\s+$/g,"") === window.localization[localize_key].replace(/^\s+|\s+$/g,"")){ tmp_key = localize_key new_key.push(tmp_key) //break } } } catch (error) { console.warn('reverseTranslation error:', error); } if(new_key.length == 0){new_key.push(key)} //console.log(`---------reverseTranslation---------${key}---------`) //console.log(new_key) return new_key }, sleep: function sleep(time) { return new Promise((resolve) => setTimeout(resolve, time)); }, switch_to_img_inpaint: function switch_to_img_inpaint() { switch_to_img2img_tab(4); return Array.from(arguments); }, switch_to_txt2img_ControlNet: function switch_to_txt2img_ControlNet(unit) { switch_to_txt2img() let elem = undefined elem = gradioApp().getElementById('txt2img_controlnet') elem = elem.querySelector("#controlnet") try{ if(elem.className.split(' ').pop() != "open"){ state.utils.triggerMouseEvent(elem, 'click') } for(e of elem.children){ if(e.className.split(' ').pop() != "open"){ state.utils.triggerMouseEvent(e, 'click') } } } catch(error){console.log(error)} try{ gradioApp().getElementById('txt2img_controlnet_tabs').querySelectorAll('button')[Number(unit)].click() } catch (error) { console.warn('[switch_to_txt2img_ControlNet]: Error:', error); } }, switch_to_img2img_ControlNet: function switch_to_img2img_ControlNet(unit) { switch_to_img2img() let elem = undefined //gradioApp().getElementById('txt2img_controlnet').children[0].children[1] elem = gradioApp().getElementById('img2img_controlnet') elem = elem.querySelector("#controlnet") try{ if(elem.className.split(' ').pop() != "open"){ state.utils.triggerMouseEvent(elem, 'click') } for(e of elem.children){ if(e.className.split(' ').pop() != "open"){ state.utils.triggerMouseEvent(e, 'click') } } } catch(error){console.log(error)} try{ gradioApp().getElementById('img2img_controlnet_tabs').querySelectorAll('button')[Number(unit)].click() } catch (error) { console.warn('[switch_to_img2img_ControlNet]: Error:', error); } }, triggerEvent: function triggerEvent(element, event) { if (! element) { return; } element.dispatchEvent(new Event(event.trim())); return element; }, triggerMouseEvent: function triggerMouseEvent(element, event) { if (! element) { return; } event = event || 'click'; element.dispatchEvent(new MouseEvent(event, { view: window, bubbles: true, cancelable: true, })); return element; }, setValue: function setValue(element, value, event) { switch (element.type) { case 'checkbox': element.checked = value === 'true'; this.triggerEvent(element, event); break; case 'radio': if (element.value === value) { element.checked = true; this.triggerEvent(element, event); } else if(element.value == "Scribble/Sketch" && value == "Scribble"){ element.checked = true; this.triggerEvent(element, event); } else { element.checked = false; } break; default: element.value = value; this.triggerEvent(element, event); } }, onFrameContentChange: function onFrameContentChange(targetNode, func) { if(targetNode) { const observer = new MutationObserver((mutationsList, observer) => { for (const mutation of mutationsList) { if (mutation.type === 'childList' || (mutation.type === 'attributes' && mutation.attributeName == 'src') // 图片被更改 ) { //console.log(`onFrameContentChange ${mutation.type} `) func(targetNode); } } }); observer.observe(targetNode, { //attributes: true, childList: true, //characterData: true, subtree: true }); } }, onContentChange: function onContentChange(targetNode, func) { if(targetNode) { const observer = new MutationObserver((mutationsList, observer) => { for (const mutation of mutationsList) { if (mutation.type === 'childList' || (mutation.type === 'attributes' && mutation.attributeName == 'src') // 图片被更改 ) { func(targetNode); } } }); observer.observe(targetNode, { attributes: true, childList: true, characterData: true, subtree: true }); } }, onAccordionChange: function onAccordionChange(targetNode, func) { if(targetNode) { const observer = new MutationObserver((mutationsList, observer) => { for (const mutation of mutationsList) { if (mutation.type === 'attributes' ) { func(targetNode); } } }); observer.observe(targetNode, { attributes: true, }); } }, getCurSeed: function getCurSeed(tab) { const elements = gradioApp().getElementById(`html_info_${tab}`).querySelectorAll(`#html_info_${tab}`); if (! elements || ! elements.length || !elements[0].innerText) { return undefined; } seed = undefined values = elements[0].innerText.split(',') for (value of values){ pair = value.split(':') if(pair[0].replace(/^\s+|\s+$/g,"") == 'Seed'){ seed = pair[1].replace(/^\s+|\s+$/g,"") } } return seed }, handleImage: function handleImage(select, id, store, addEvtLsner=true) { if(addEvtLsner){ setTimeout(() => { state.utils.onContentChange(select, function (el) { let data = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ "id":id, "img":"" }) } try { // new gradio version... let img = el.querySelector('img'); if (img) { data.body = JSON.stringify({ "id":id, "img":img.src }) } } catch (error) { console.warn('[state]: Error:', error); } //console.log(`image changed ${id}`) fetch(`/lightdiffusionflow/local/imgs_callback`, data) }); }, 150); } }, clearImage: function clearImage(select) { try { if(select){ let buttons = select.querySelectorAll('button'); buttons.forEach(button => { if(button.getAttribute("aria-label") == "Clear"){ button.click(); //state.utils.triggerMouseEvent(button, 'mousedown'); } }); } } catch (error) { console.warn('[state]: Error:', error); } }, // handleSelect: function handleSelect(select, id, store) { // try { // let value = store.get(id); // if (value) { // let input = select.querySelector('input'); // state.utils.triggerMouseEvent(input, 'focus'); // setTimeout(() => { // let items = Array.from(select.querySelectorAll('ul li')); // for (li of items){ // if (li.lastChild.wholeText.trim() === value) { // state.utils.triggerMouseEvent(li, 'mousedown'); // //return false; // break // } // } // state.utils.triggerMouseEvent(input, 'blur'); // }, 100); // } // setTimeout(() => { // state.utils.onContentChange(select, function (el) { // let selected = el.querySelector('span.single-select'); // if (selected) { // store.set(id, selected.textContent); // } else { // // new gradio version... // let input = select.querySelector('input'); // if (input) { // store.set(id, input.value); // } // } // }); // }, 150); // } catch (error) { // console.warn('[state]: Error:', error); // } // }, forceSaveSelect: function forceSaveSelect(select, id, store) { let selected = select.querySelector('span.single-select'); if (selected) { store.set(id, selected.textContent); } else { // new gradio version... let input = select.querySelector('input'); if (input) { store.set(id, input.value); } } }, handleAccordion: function handleAccordion(accordion, id, store, addEvtLsner=true){ try{ let value = store.get(id); let child = accordion.querySelector('div.cursor-pointer, .label-wrap'); if (value) { //for(child of children){ //let span = child.querySelector('.transition, .icon'); //if(span.style.transform !== 'rotate(90deg)'){ if(child.className.split(' ').pop() != "open"){ state.utils.triggerMouseEvent(child, 'click') } //} } if(addEvtLsner){ setTimeout(() => { state.utils.onAccordionChange(child, function (el) { store.set(id, el.className.split(' ').pop() == "open"); //console.log(`accordion on change ${id}`) //let span = el.querySelector('.transition, .icon'); //store.set(id, span.style.transform !== 'rotate(90deg)'); }); }, 150); } } catch (error) { console.warn(`accordion:${accordion}, id:${id}`) console.warn('[state]: Error:', error); } }, handleSelect: function handleSelect(select, id, store, force=false, addEvtLsner=true) { try { let value = store.get(id); if ( value ) { //&& value != 'None' value = value.replace("/","\\") let parts = value.split("\\") value = parts[parts.length - 1] selectingQueue += 1; setTimeout(() => { let input = select.querySelector('input'); state.utils.triggerMouseEvent(input, 'focus'); setTimeout(() => { let items = Array.from(select.querySelectorAll('ul li')); let localized_value = this.getTranslation(value) let successed = false for (li of items){ // li.lastChild.wholeText.trim() === value let option = li.lastChild.wholeText.trim().replace(/^\s+|\s+$/g,"") option = option.replace("/","\\") let parts = option.split("\\") option = parts[parts.length - 1] if (localized_value.replace(/^\s+|\s+$/g,"") === option) { state.utils.triggerMouseEvent(li, 'mousedown'); successed = true break } } let hash_res = localized_value.match(/\[[0-9A-Fa-f]{8,10}\]/) if(!successed){ // && hash_pos != -1 找不到对应选项 并且选项里有10位哈希值 for (li of items){ // 去掉Hash比较 let text = li.lastChild.wholeText.trim() text = text.replace("/","\\") let parts = text.split("\\") text = parts[parts.length - 1] let localized_value_no_hash = localized_value.replace(/\[[0-9A-Fa-f]{8,10}\]/,"").replace(/^\s+|\s+$/g,"") let text_no_hash = text.replace(/\[[0-9A-Fa-f]{8,10}\]/, "").replace(/^\s+|\s+$/g,"") if (localized_value_no_hash === text_no_hash) { successed = true } // 只比较Hash if(!successed && hash_res != null){ let hash_str = hash_res[0].replace(/^\s+|\s+$/g,"") let text_hash_res = text.match(/\[[0-9A-Fa-f]{8,10}\]/) if(text_hash_res != null){ let text_hash = text_hash_res[0].replace(/^\s+|\s+$/g,"") if (hash_str === text_hash) { successed = true } } } if(successed){ state.utils.triggerMouseEvent(li, 'mousedown'); // state.core.actions.output_log( // `Note: \'${value}\' not found. An approximate match \'${li.lastChild.wholeText.trim()}\' has been automatically selected as replacement.` // ) state.core.actions.preset_output_log("alt_option", value, li.lastChild.wholeText.trim()) break } } } if(!successed && items.length > 0) // 下拉框一个选项都没找到说明就没有这个下拉框,可能是界面设置把下拉框替换成了radio button { let option_name = store.prefix + id if(option_name === "state-setting_sd_model_checkpoint"){ // 大模型找不到就只用warning提示,因为不影响运行 // state.core.actions.output_log(`Note: \'${value}\' not found.`) state.core.actions.preset_output_log("no_option", "stable diffusion checkpoint", value) } else{ //state.core.actions.output_log(`Error: \'${option_name}\' import failed! The option \'${value}\' was not found!`) state.core.actions.preset_output_log("no_option", option_name, value) } if(hash_res != null){ let model_name = value let hash_str = hash_res[0] state.utils.searchCheckPointByHash(hash_str).then( downloadUrl => { if(downloadUrl != undefined){ // let warning_str = encodeURIComponent(`Click to download \ // ${model_name} `) // state.core.actions.output_warning(warning_str) state.core.actions.preset_output_log("download_url", model_name, downloadUrl) } }); } } state.utils.triggerMouseEvent(input, 'blur'); selectingQueue -= 1; //console.log(`selectingQueue = ${selectingQueue}`) }, 100); }, selectingQueue * 200) } if(addEvtLsner) { setTimeout(() => { state.utils.onContentChange(select, function (el) { let selected = el.querySelector('span.single-select'); if(force){ let localized_id = state.utils.getTranslation(id) let id_translations = state.utils.reverseTranslation(localized_id) //宁可错存一千,也不漏存一个 for (trans_id of id_translations){ if (selected) { store.set(trans_id, selected.textContent); } else { // new gradio version... let input = el.querySelector('input'); if (input) { store.set(trans_id, input.value); } } } } else{ if (selected) { store.set(id, selected.textContent); } else { // new gradio version... let input = el.querySelector('input'); if (input) { store.set(id, input.value); } } } }); }, 150); } } catch (error) { console.warn('[state]: Error:', error); } }, handleMultipleSelect: function handleMultipleSelect(select, id, store, addEvtLsner=true) { try { let value = store.get(id); if (value) { value = value.split(',').reverse(); if (value.length) { let input = select.querySelector('input'); let selectOption = function () { if (! value.length) { state.utils.triggerMouseEvent(input, 'blur'); return; } let option = value.pop(); state.utils.triggerMouseEvent(input, 'focus'); setTimeout(() => { let successed = false let items = Array.from(select.querySelectorAll('ul li')); items.forEach(li => { if (li.lastChild.wholeText.trim() === option) { state.utils.triggerMouseEvent(li, 'mousedown'); successed = true return false; } }); if(!successed){ state.core.actions.preset_output_log("no_option", store.prefix + id, value) //state.core.actions.output_log(`Error: \'${store.prefix + id}\' import failed! The option \'${value}\' was not found!`) } setTimeout(selectOption, 100); }, 100); } selectOption(); } } if(addEvtLsner){ state.utils.onContentChange(select, function (el) { const selected = Array.from(el.querySelectorAll('.token > span')).map(item => item.textContent); store.set(id, selected); }); } } catch (error) { console.warn('[state]: Error:', error); } }, txtToId: function txtToId(txt) { return txt.split(' ').join('-').toLowerCase(); }, callXTimes: function callXTimes(func, times) { let called = 0; return function() { if (called < times) { called++; return func.apply(this); } } }, saveFile: function saveJSON(fileName ,data) { const json = JSON.stringify(data, null, 4); const blob = new Blob([json], {type: 'application/json'}); const url = URL.createObjectURL(blob); console.log(url) const link = document.createElement('a'); link.href = url; link.download = fileName; document.body.appendChild(link); link.click(); link.parentNode.removeChild(link); }, debounce: function debounce(func, delay) { let lastCallTime = 0; return function() { const currentCallTime = new Date().getTime(); if (currentCallTime - lastCallTime > delay) { lastCallTime = currentCallTime; func.apply(this, arguments); } } }, onNextUiUpdates: function (func) { // brute force this to to ensure that the method is called after next few updates onUiUpdate(this.callXTimes(function () { setTimeout(func, 5); }, 150)); } }; state.utils.html = { setStyle: function setStyle(elements, style) { if (elements instanceof NodeList) { elements = Array.from(elements); } else if (elements instanceof Node){ elements = [elements]; } else { return; } elements.forEach(element => { for (let key in style) { if (style.hasOwnProperty(key)) { element.style[key] = style[key]; } } }); }, create: function create(type, props, style) { const element = document.createElement(type); if (props) { for (let key in props) { if (props.hasOwnProperty(key)) { element[key] = props[key]; } } } if (style) { this.setStyle(element, style); } return element; }, createButton: function createButton(text, onclick) { const btn = document.createElement('button'); btn.innerHTML = text; btn.onclick = onclick || function () {}; btn.className = 'gr-button gr-button-lg gr-button-primary'; return btn; } };