window.state = window.state || {}; state = window.state; state.core = (function () { const TABS = ['txt2img', 'img2img']; // settingId, element const ELEMENTS = { 'prompt': 'prompt', 'negative_prompt': 'neg_prompt', 'sampling_steps': 'steps', 'restore_faces': 'restore_faces', 'tiling': 'tiling', 'hires_fix': 'enable_hr', 'hires_steps': 'hires_steps', 'hires_scale': 'hr_scale', 'hires_resize_x': 'hr_resize_x', 'hires_resize_y': 'hr_resize_y', 'hires_denoising_strength': 'denoising_strength', 'width': 'width', 'height': 'height', 'batch_count': 'batch_count', 'batch_size': 'batch_size', 'cfg_scale': 'cfg_scale', 'denoising_strength': 'denoising_strength', 'seed': 'seed', 'sampling': 'sampling', 'switch_at': 'switch_at' }; const ACCORDION = { "hires_fix": "hr", "refiner": "enable" } const ELEMENTS_WITHOUT_PREFIX = { 'resize_mode': 'resize_mode', 'setting_inpainting_mask_weight': 'setting_inpainting_mask_weight', 'setting_CLIP_stop_at_last_layers': 'setting_CLIP_stop_at_last_layers', 'setting_eta_noise_seed_delta': 'setting_eta_noise_seed_delta', 'img2img_mask_blur': 'img2img_mask_blur', 'img2img_mask_mode': 'img2img_mask_mode', 'img2img_inpainting_fill': 'img2img_inpainting_fill', 'img2img_inpaint_full_res_padding': 'img2img_inpaint_full_res_padding', 'img2img_inpaint_full_res': 'img2img_inpaint_full_res', 'img2img_mask_alpha': 'img2img_mask_alpha' //'generation_info_txt2img': 'generation_info_txt2img' // 可能因为是visible=false 所以触发不了onchange事件? }; const SELECTS = { 'sampling': 'sampling', 'hires_upscaler': 'hr_upscaler', 'script': '#script_list', 'checkpoint': 'checkpoint', }; const SELECTS_WITHOUT_PREFIX = { 'setting_sd_model_checkpoint': 'setting_sd_model_checkpoint', 'setting_sd_vae': 'setting_sd_vae' }; const MULTI_SELECTS = { 'styles': 'styles' }; const TOGGLE_BUTTONS = { 'extra_networks': 'extra_networks', }; var IMAGES_WITHOUT_PREFIX = { }; const ELEMENTS_ALWAYS_SAVE = { 'setting_sd_model_checkpoint': 'setting_sd_model_checkpoint', }; const Image_extensions = [".png", ".jpg", ".jpeg"] let store = null; let timer = null; let inited = false let sd_versions = "0.0.0" let waiting_second_apply = false let timeout_id = undefined let img_elem_keys=[]; let ext_list=[]; let flow_save_mode = "Core" function hasSetting(id, tab) { return true // 需要默认保存全部选项 不需要判断 const suffix = tab ? `_${tab}` : ''; return this[`state${suffix}`] && this[`state${suffix}`].indexOf(id) > -1; } function fn_timer(){ // if(inited){ fetch('/lightdiffusionflow/local/need_preload') .then(response => response.json()) .then(data => { console.log(`fn_timer`) if (data != ""){ //state.core.actions.handleLightDiffusionFlow([{"name":data}]); const btn1 = gradioApp().querySelector(`button#set_lightdiffusionflow_file`); state.utils.triggerMouseEvent(btn1); setTimeout(() => { const btn2 = gradioApp().querySelector(`button#preload_button`); state.utils.triggerMouseEvent(btn2); }, 1000); } }).catch(function(e) { clearInterval(timer) console.log("Oops, error"); }); // } // else{ // fetch('/lightdiffusionflow/local/get_imgs_elem_key') //初始化部分图片组件id, 后续设置onchanged事件 // .then(response => response.json()) // .then(data => { // if(data != ""){ // img_elem_keys = data.split(",") // img_elem_keys.forEach(key => { // IMAGES_WITHOUT_PREFIX[key] = key // }); // // 等上面的组件ID同步过来后 再加载其他配置 // fetch('/lightdiffusionflow/local/config.json?_=' + (+new Date())) // .then(response => response.json()) // .then(config => { // try { // store = new state.Store(); // store.clearAll(); // load(config); // inited = true // } catch (error) { // console.error('[state]: Error:', error); // } // }) // .catch(error => console.error('[state]: Error getting JSON file:', error)); // } // }); // } } function get_js_local_data(){ if(state.utils.getCurSeed('txt2img') != undefined){ store.set(`txt2img_seed`,state.utils.getCurSeed('txt2img')) } if(state.utils.getCurSeed('img2img') != undefined){ store.set(`img2img_seed`,state.utils.getCurSeed('img2img')) } stored_config = store.getAll() for (let key in stored_config){ if(key.indexOf("allow-preview") !== -1 && key.indexOf("ext-control-net") !== -1) { console.log("allow-preview改成false") stored_config[key] = "false" } } return stored_config } function get_imgs_elem_key(){ fetch('/lightdiffusionflow/local/get_imgs_elem_key') //初始化部分图片组件id, 后续设置onchanged事件 .then(response => response.json()) .then(data => { console.log(data) if(data == ''){ setTimeout(() => { get_imgs_elem_key() }, 500); } else{ img_elem_keys = data.split(",") img_elem_keys.forEach(key => { IMAGES_WITHOUT_PREFIX[key] = key }); fetch('/lightdiffusionflow/local/get_ext_list') .then(response => response.json()) .then(data => { ext_list = data.split(",") }); // 等上面的组件ID同步过来后 再加载其他配置 fetch('/lightdiffusionflow/local/config.json?_=' + (+new Date())) .then(response => response.json()) .then(config => { try { try{ flow_save_mode = config['lightdiffusionflow-mode'] }catch (error) { flow_save_mode = "Core" } store = new state.Store(); store.clearAll(); load(config); timer = window.setInterval(fn_timer,1000); // 初始化页面完成后再启动timer读取文件 } catch (error) { console.error('[state]: Error:', error); } }) .catch(error => console.error('[state]: Error getting JSON file:', error)); } }); } function init() { //console.log(window.localization) fetch('/lightdiffusionflow/local/refresh_ui') // 刷新页面触发python重置图片数据 .then(response => response.json()) .then(data => { sd_versions = data }); get_imgs_elem_key() } // function forEachImageElement(list, action) { // for (const [settingId, element] of Object.entries(list)) { // TABS.forEach(tab => { // //if (config.hasSetting(settingId, tab)) { // action(element, tab); // //} // }); // } // } function forEachElement_WithoutTabs(list, action) { for (const [settingId, element] of Object.entries(list)) { action(element); } } function forEachElement(list, config, action) { for (const [settingId, element] of Object.entries(list)) { TABS.forEach(tab => { if (config.hasSetting(settingId, tab)) { action(element, tab); } }); } } function load(config, addEvtLsner=true) { config.hasSetting = hasSetting //loadUI(); // 往页面上添加按钮 for (let tab of TABS) { //console.log(`${tab}_script_container start`) let script_container = getElement(`${tab}_script_container`) state.utils.onFrameContentChange(script_container, function (el) { clearTimeout(timeout_id); timeout_id = setTimeout(() => { if(waiting_second_apply) { waiting_second_apply = false actions.applyState(false); setTimeout(() => { actions.preset_output_log("finished") }, 3000); } }, 3000); }); } forEachElement(ACCORDION, config, (element, tab) => { handleSavedAccordion(`${tab}_${element}`, addEvtLsner); }); forEachElement_WithoutTabs(SELECTS_WITHOUT_PREFIX, (element) => { handleSavedSelects(element, addEvtLsner); }); forEachElement(ELEMENTS, config, (element, tab) => { handleSavedInput(`${tab}_${element}`, addEvtLsner); }); forEachElement_WithoutTabs(ELEMENTS_WITHOUT_PREFIX, (element) => { handleSavedInput(element, addEvtLsner); }); forEachElement(SELECTS, config, (element, tab) => { handleSavedSelects(`${tab}_${element}`, addEvtLsner); }); forEachElement(MULTI_SELECTS, config, (element, tab) => { handleSavedMultiSelects(`${tab}_${element}`, addEvtLsner); }); forEachElement(TOGGLE_BUTTONS, config, (element, tab) => { handleToggleButton(`${tab}_${element}`, addEvtLsner); }); forEachElement_WithoutTabs(IMAGES_WITHOUT_PREFIX, (element) => { handleSavedImage(`${element}`, addEvtLsner); }); handleExtensions(config, addEvtLsner); //handleSettingsPage(); restoreTabs(config, addEvtLsner); // 恢复到最后点击的tab页面 forEachElement_WithoutTabs(ELEMENTS_ALWAYS_SAVE, (element) => { state.utils.forceSaveSelect(getElement(element), element, store); //每次无论有没有修改都需要导出的选项 }); } function createHeaderButton(title, text, className, style, action) { const button = state.utils.html.create('button', { title: title, innerHTML: text, className: className, }, style); if (action) { button.addEventListener('click', action); } return button; } // function createHeaderFileInput(title, text, className) { // let inputId = 'state-import-file-inline'; // let importBtn = createHeaderButton(title,text, className, { // display: 'none' // }, () => { // actions.importState(inputId); // }); // let label = state.utils.html.create('label', {}, { cursor: 'pointer' }); // label.appendChild(state.utils.html.create('input', { // type: 'file', // id: inputId, // accept: 'application/json', // }, { // display: 'none' // })); // label.appendChild(document.createTextNode(text)); // label.addEventListener('change', () => { // importBtn.dispatchEvent(new Event('click')); // }); // let button = createHeaderButton(title, '', className, {}); // button.appendChild(label); // return { // hiddenButton: importBtn, // button: button // }; // } // function loadUI() { // let quickSettings = gradioApp().getElementById("quicksettings"); // let className = quickSettings.querySelector('button').className; // quickSettings.appendChild(createHeaderButton('State: Reset', "*️⃣", className, {}, actions.resetAll)); // quickSettings.appendChild(createHeaderButton('State: Export',"📤", className, {}, actions.exportState)); // quickSettings.appendChild(createHeaderButton('State: test',"📤", className, {}, actions.test)); // let fileInput = createHeaderFileInput('State: Import',"📥", className); // quickSettings.appendChild(fileInput.hiddenButton); // quickSettings.appendChild(fileInput.button); // } function restoreTabs(config, addEvtLsner=true) { if (! config.hasSetting('tabs')) { return; } const tabs = gradioApp().querySelectorAll('#tabs > div:first-child button'); const value = store.get('tab'); if (value) { for (var i = 0; i < tabs.length; i++) { if (tabs[i].textContent === state.utils.getTranslation(value)) { state.utils.triggerEvent(tabs[i], 'click'); break; } } } // Use this when onUiTabChange is fixed // onUiTabChange(function () { // store.set('tab', gradioApp().querySelector('#tabs .tab-nav button.selected').textContent); // }); if(addEvtLsner){ bindTabClickEvents(); } } function bindTabClickEvents() { Array.from(gradioApp().querySelectorAll('#tabs .tab-nav button')).forEach(tab => { tab.removeEventListener('click', storeTab); tab.addEventListener('click', storeTab); }); } function storeTab() { let tab_name = gradioApp().querySelector('#tabs .tab-nav button.selected').textContent; store.set('tab', state.utils.reverseTranslation(tab_name)[0]); bindTabClickEvents(); // dirty hack here... } function getElement(id) { for (let i = 0; i < TABS.length; i++) { if (id.startsWith(`${TABS[i]}_#`)) { // handle elements with same ids in different tabs... return gradioApp().querySelector('#tab_' + id.replace(`${TABS[i]}_#`, `${TABS[i]} #`)); } } return gradioApp().getElementById(id); } function handleSavedInput(id, addEvtLsner=true) { const elements = gradioApp().querySelectorAll(`#${id} textarea, #${id} input, #${id} img`); const events = ['change', 'input']; if (! elements || ! elements.length) { return; } let forEach = function (action) { events.forEach(function(event) { elements.forEach(function (element) { action.call(element, event); }); }); }; if(addEvtLsner){ forEach(function (event) { this.addEventListener(event, function () { let value = this.value; if (this.type && this.type === 'checkbox') { value = this.checked; } else if (this.className === 'img') { value = this.checked; } store.set(id, value); }); }); TABS.forEach(tab => { const seedInput = gradioApp().querySelector(`#${tab}_seed input`); ['random_seed', 'reuse_seed'].forEach(id => { const btn = gradioApp().querySelector(`#${tab}_${id}`); btn.addEventListener('click', () => { setTimeout(() => { state.utils.triggerEvent(seedInput, 'change'); }, 100); }); }); }); } let value = store.get(id); if (! value) { return; } forEach(function (event) { state.utils.setValue(this, value, event); }); } function handleSavedSelects(id, addEvtLsner=true) { state.utils.handleSelect(getElement(id), id, store, force=false, addEvtLsner); } function handleSavedAccordion(id, addEvtLsner=true) { state.utils.handleAccordion(getElement(id), id, store, addEvtLsner); } function handleSavedMultiSelects(id, addEvtLsner=true) { const select = gradioApp().getElementById(`${id}`); state.utils.handleMultipleSelect(select, id, store, addEvtLsner); } function handleSavedImage(id, addEvtLsner=true) { state.utils.handleImage(getElement(id), id, store, addEvtLsner); // 图片有修改就发回到python保存 } function handleToggleButton(id, addEvtLsner=true) { const btn = gradioApp().querySelector(`button#${id}`); if (! btn) { return; } // legionfu if (store.get(id) === 'true') { state.utils.triggerMouseEvent(btn); } if(addEvtLsner){ btn.addEventListener('click', function () { store.set(id, Array.from(this.classList).indexOf('secondary-down') === -1); }); } } function handleExtensions(config, addEvtLsner=true) { // if (config['state_extensions']) { // config['state_extensions'].forEach(function (ext) { // if (ext in state.extensions) { // state.extensions[ext].init(); // } // }); // } for (const [name, obj] of Object.entries(state.extensions)) { obj.init(flow_save_mode == "Core", addEvtLsner); } } // function handleSettingsPage() { // settings state 界面 绑定按钮事件等操作 // const page = gradioApp().querySelector('#settings_state'); // state.utils.html.setStyle(page.querySelectorAll('fieldset'), { // 'marginTop': '20px', // 'marginBottom': '10px' // }); // let buttonsContainer = gradioApp().querySelector('#settings_state_buttons'); // if (buttonsContainer) { // buttonsContainer.parentNode.removeChild(buttonsContainer); // } // buttonsContainer = document.createElement('div'); // buttonsContainer.id = 'settings_state_buttons'; // let setCheckboxes = function (value, checkFunc) { // checkFunc = checkFunc || function () { return true; }; // Array.from(page.querySelectorAll('input[type="checkbox"]')).forEach(function (el) { // if (checkFunc(el)) { // if (el.checked !== value) { // el.checked = value; // state.utils.triggerEvent(el, 'change'); // } // } else if (el.checked === value) { // el.checked = !value; // state.utils.triggerEvent(el, 'change'); // } // }); // }; // buttonsContainer.appendChild(state.utils.html.createButton('Select All', function () { // setCheckboxes(true); // })); // buttonsContainer.appendChild(state.utils.html.createButton('Select All Except Seeds', function () { // setCheckboxes(true, function (el) { // return el.nextElementSibling.textContent.indexOf('seed') === -1; // }); // })); // buttonsContainer.appendChild(state.utils.html.createButton('Unselect All', function () { // setCheckboxes(false); // })); // state.utils.html.setStyle(buttonsContainer, { // 'marginTop': '20px', // 'marginBottom': '10px' // }); // buttonsContainer.appendChild(state.utils.html.create('hr')); // buttonsContainer.appendChild(state.utils.html.create('div', // { innerHTML: 'Actions' }, // { marginBottom: '10px' })); // buttonsContainer.appendChild(state.utils.html.createButton('Reset All', actions.resetAll)); // buttonsContainer.appendChild(state.utils.html.createButton('Export State', actions.exportState)); // buttonsContainer.appendChild(state.utils.html.createButton('Import State', actions.importState)); // buttonsContainer.appendChild(state.utils.html.create('input', { // id: 'state-import-file', type: 'file', accept: 'application/json' // })); // page.appendChild(buttonsContainer); // } let actions = { // resetAll: function () { // let confirmed = confirm('Reset all state values?'); // if (confirmed) { // store.clearAll(); // alert('All state values deleted!'); // } // }, applyState: async function (addEvtLsner=true) { console.log("applyState") await fetch('/lightdiffusionflow/local/config.json?_=' + (+new Date())) .then(response => response.json()) .then(config => { try { config.hasSetting = hasSetting try{ flow_save_mode = config['lightdiffusionflow-mode'] }catch (error) { flow_save_mode = "Core" } //console.log(config) //restoreTabs(config); // 恢复到最后点击的tab页面 load(config, addEvtLsner); // forEachElement_WithoutTabs(SELECTS_WITHOUT_PREFIX, (element) => { // handleSavedSelects(element); // }); // forEachElement(ELEMENTS, config, (element, tab) => { // handleSavedInput(`${tab}_${element}`); // }); // forEachElement_WithoutTabs(ELEMENTS_WITHOUT_PREFIX, (element) => { // handleSavedInput(element); // }); // forEachElement(SELECTS, config, (element, tab) => { // handleSavedSelects(`${tab}_${element}`); // }); // forEachElement(MULTI_SELECTS, config, (element, tab) => { // handleSavedMultiSelects(`${tab}_${element}`); // }); // forEachElement(TOGGLE_BUTTONS, config, (element, tab) => { // handleToggleButton(`${tab}_${element}`); // }); // forEachElement_WithoutTabs(IMAGES_WITHOUT_PREFIX, (element) => { // handleSavedImage(element); // }); // handleExtensions(config); //handleSettingsPage(); } catch (error) { console.error('[state]: Error:', error); } }) .catch(error => console.error('[state]: Error getting JSON file:', error)); }, exportState: function () { // if(state.utils.getCurSeed('txt2img') != undefined){ // store.set(`txt2img_seed`,state.utils.getCurSeed('txt2img')) // } // if(state.utils.getCurSeed('img2img') != undefined){ // store.set(`img2img_seed`,state.utils.getCurSeed('img2img')) // } let stored_config = get_js_local_data() fetch('/lightdiffusionflow/local/lightdiffusionflow_config?data2export=true') .then(response => response.json()) .then(config => { config = JSON.parse(config) //stored_config = store.getAll() let data = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ "config_data":stored_config }) } fetch(`/lightdiffusionflow/local/parse_lora_info`, data) .then(response => response.json()) .then(response_lora_info => { for (let key in response_lora_info){ stored_config[key] = response_lora_info[key] } for (let key in config){ if(config[key] != ""){ stored_config[key] = config[key] } } // for (let key in stored_config){ // if(key.indexOf("allow-preview") !== -1 && key.indexOf("ext-control-net") !== -1) // { // console.log("allow-preview改成false") // stored_config[key] = "false" // } // } var checkTime = function (i) { if (i < 10) { i = "0" + i; } return i; } let nowdate = new Date(); let year = String(nowdate.getFullYear()) let month = String(checkTime(nowdate.getMonth() + 1)) let day = String(checkTime(nowdate.getDate())) let h = String(checkTime(nowdate.getHours())) let m = String(checkTime(nowdate.getMinutes())) let s = String(checkTime(nowdate.getSeconds())) let time_str = year+month+day+h+m+s filename = 'flow-'+time_str+'.flow' filename = prompt("Export workflow as:", filename); if (!filename) return; if (!filename.toLowerCase().endsWith(".flow")) { filename += ".flow"; } if(filename != ".flow"){ // const handle = window.showDirectoryPicker(); // console.log(handle) state.utils.saveFile(filename, stored_config); fetch('https://api.lightflow.ai/openapi/access?action=export') .then(response => response.json()) .then(config => { console.log(config) }).catch(function(e) { console.log("Oops, export callback error!"); }); } }).catch(error => console.error('[state]: Error getting Flow file:', error)); }).catch(error => console.error('[state]: Error getting Flow file:', error)); //config = JSON.stringify(store.getAll(), null, 4); //fetch(`/lightdiffusionflow/local/ExportLightDiffusionFlow?config=${config}`) }, saveFlowToLocal: function saveFlowToLocal(){ var checkTime = function (i) { if (i < 10) { i = "0" + i; } return i; } let nowdate = new Date(); let year = String(nowdate.getFullYear()) let month = String(checkTime(nowdate.getMonth() + 1)) let day = String(checkTime(nowdate.getDate())) let h = String(checkTime(nowdate.getHours())) let m = String(checkTime(nowdate.getMinutes())) let s = String(checkTime(nowdate.getSeconds())) let time_str = year+month+day+h+m+s filename = 'flow-'+time_str+'.flow' filename = prompt("Save workflow as:", filename); if (!filename) return; if (!filename.toLowerCase().endsWith(".flow")) { filename += ".flow"; } if(filename != ".flow"){ let data = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ "file_path":filename }) } fetch(`/lightdiffusionflow/local/file_exist`, data) .then(response => response.json()) .then(data => { if(!data || (data && confirm("Overwrite the existing file with the same name?"))) { let stored_config = get_js_local_data() let flow_data = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ "file_name":filename, "file_data":stored_config, "overwrite":true }) } fetch("/lightdiffusionflow/local/save_flow_to_local",flow_data) fetch('https://api.lightflow.ai/openapi/access?action=save') .then(response => response.json()) .then(config => { console.log(config) }).catch(function(e) { console.log("Oops, export callback error!"); }); } }); } }, handleLightDiffusionFlow: function (fileInput){ actions.preset_output_log("start") //actions.output_log("