diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d7babf93..de6e87827 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,12 @@ # Change Log for SD.Next -## Update for 2023-08-31 +## Update for 2023-09-01 +- extra networks: + - support for **tags** + search by tag, list tags, add to prompt, etc. + - simplified handling of **descriptions** + now shows on-mouse-over without the need for user interaction - diffusers: - ability to interrupt (stop/skip) model generate - add `diffusers_force_zeros` setting diff --git a/extensions-builtin/Lora/scripts/lora_script.py b/extensions-builtin/Lora/scripts/lora_script.py index cef764c52..c69367620 100644 --- a/extensions-builtin/Lora/scripts/lora_script.py +++ b/extensions-builtin/Lora/scripts/lora_script.py @@ -55,8 +55,8 @@ script_callbacks.on_infotext_pasted(lora.infotext_pasted) shared.options_templates.update(shared.options_section(('extra_networks', "Extra Networks"), { - "sd_lora": shared.OptionInfo("None", "Add Lora to prompt", gr.Dropdown, lambda: {"choices": ["None", *lora.available_loras]}, refresh=lora.list_available_loras), - "lora_preferred_name": shared.OptionInfo("Alias from file", "When adding to prompt, refer to Lora by", gr.Radio, {"choices": ["Alias from file", "Filename"]}), + "sd_lora": shared.OptionInfo("None", "Add Lora to prompt", gr.Dropdown, lambda: { "choices": ["None", *lora.available_loras], "visible": False }, refresh=lora.list_available_loras), + "lora_preferred_name": shared.OptionInfo("Filename", "When adding to prompt, refer to Lora by", gr.Radio, {"choices": ["Alias from file", "Filename"]}), "lora_add_hashes_to_infotext": shared.OptionInfo(True, "Add Lora hashes to infotext", gr.Checkbox, { "visible": False }), })) diff --git a/extensions-builtin/Lora/ui_extra_networks_lora.py b/extensions-builtin/Lora/ui_extra_networks_lora.py index 064d77d15..54b703bcb 100644 --- a/extensions-builtin/Lora/ui_extra_networks_lora.py +++ b/extensions-builtin/Lora/ui_extra_networks_lora.py @@ -16,7 +16,8 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): for name, lora_on_disk in lora.available_loras.items(): path, _ext = os.path.splitext(lora_on_disk.filename) alias = lora_on_disk.get_alias() - prompt = (json.dumps(f"")) + prompt = f" " + prompt = json.dumps(prompt) metadata = json.dumps(lora_on_disk.metadata, indent=4) if lora_on_disk.metadata else None possible_tags = lora_on_disk.metadata.get('ss_tag_frequency', {}) if lora_on_disk.metadata is not None else {} if isinstance(possible_tags, str): @@ -36,7 +37,7 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): "hash": lora_on_disk.shorthash, "preview": self.find_preview(path), "description": self.find_description(path), - "search_term": self.search_terms_from_path(lora_on_disk.filename), + "search_term": self.search_terms_from_path(lora_on_disk.filename) + ' '.join(tags.keys()), "prompt": prompt, "local_preview": f"{path}.{shared.opts.samples_format}", "metadata": metadata, diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index ce982881b..9f09fef35 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -1,6 +1,9 @@ let globalPopup = null; let globalPopupInner = null; +let previousCard = null; const activePromptTextarea = {}; +const re_extranet = /<([^:]+:[^:]+):[\d\.]+>/; +const re_extranet_g = /\s+<([^:]+:[^:]+):[\d\.]+>/g; const getENActiveTab = () => gradioApp().getElementById('tab_txt2img').style.display === 'block' ? 'txt2img' : 'img2img'; @@ -27,6 +30,112 @@ function requestGet(url, data, handler, errorHandler) { xhr.send(js); } +function popup(contents) { + if (!globalPopup) { + globalPopup = document.createElement('div'); + globalPopup.onclick = () => { globalPopup.style.display = 'none'; }; + globalPopup.classList.add('global-popup'); + const close = document.createElement('div'); + close.classList.add('global-popup-close'); + close.onclick = () => { globalPopup.style.display = 'none'; }; + close.title = 'Close'; + globalPopup.appendChild(close); + globalPopupInner = document.createElement('div'); + globalPopupInner.onclick = (event) => { event.stopPropagation(); return false; }; + globalPopupInner.classList.add('global-popup-inner'); + globalPopup.appendChild(globalPopupInner); + gradioApp().appendChild(globalPopup); + } + globalPopupInner.innerHTML = ''; + globalPopupInner.appendChild(contents); + globalPopup.style.display = 'flex'; +} + +function readCardMetadata(event, extraPage, cardName) { + requestGet('./sd_extra_networks/metadata', { page: extraPage, item: cardName }, (data) => { + if (data?.metadata) { + if (typeof (data?.metadata) !== 'string') data.metadata = JSON.stringify(data.metadata, null, 2); + const elem = document.createElement('pre'); + elem.classList.add('popup-metadata'); + elem.textContent = data.metadata; + popup(elem); + } + }, () => { }); + event.stopPropagation(); + event.preventDefault(); +} + +function readCardTags(el, tags) { + const clickTag = (e, tag) => { + e.preventDefault(); + e.stopPropagation(); + const textarea = activePromptTextarea[getENActiveTab()]; + if (textarea.value.indexOf(tag) !== -1) textarea.value = textarea.value.replace(tag, ''); + else textarea.value += ` ${tag}`; + updateInput(textarea); + }; + if (tags.length === 0) return; + const cardTags = tags.split('|'); + if (cardTags.length === 0) return; + const tagsEl = el.getElementsByClassName('tags')[0]; + if (tagsEl.children.length > 0) return; + for (const tag of cardTags) { + const span = document.createElement('span'); + span.classList.add('tag'); + span.textContent = tag; + span.onclick = (e) => clickTag(e, tag); + tagsEl.appendChild(span); + } +} + +function readCardInformation(event, extraPage, cardName) { + requestGet('./sd_extra_networks/info', { page: extraPage, item: cardName }, (data) => { + if (data?.info && (typeof (data?.info) === 'string')) { + const elem = document.createElement('pre'); + elem.classList.add('popup-metadata'); + elem.textContent = data.info; + popup(elem); + } + }, () => { }); + event.stopPropagation(); + event.preventDefault(); +} + +function readCardDescription(filename, descript) { + const tabname = getENActiveTab(); + const fn = gradioApp().querySelector(`#${tabname}_description_filename > label > textarea`); + const description = gradioApp().querySelector(`#${tabname}_description > label > textarea`); + fn.value = filename; + description.value = descript?.trim() || ''; + description.focus(); + updateInput(fn); + updateInput(description); +} + +function saveCardPreview(event) { + const tabname = getENActiveTab(); + const textarea = gradioApp().querySelector(`#${tabname}_preview_filename > label > textarea`); + const button = gradioApp().getElementById(`${tabname}_save_preview`); + const el = event?.target?.parentElement?.parentElement?.parentElement; + if (el?.classList?.contains('card')) { + textarea.value = el.dataset.filename; + updateInput(textarea); + button.click(); + } + event.stopPropagation(); + event.preventDefault(); +} + +function saveCardDescription(event) { + const tabname = getENActiveTab(); + const el = event?.target?.parentElement?.parentElement?.parentElement; + if (el?.classList?.contains('card')) el.dataset.description = gradioApp().getElementById(`${tabname}_description`)?.children[0].children[1].value; + const button = gradioApp().getElementById(`${tabname}_save_description`); + button.click(); + event.stopPropagation(); + event.preventDefault(); +} + function setupExtraNetworksForTab(tabname) { gradioApp().querySelector(`#${tabname}_extra_tabs`).classList.add('extra-networks'); const tabs = gradioApp().querySelector(`#${tabname}_extra_tabs > div`); @@ -53,6 +162,17 @@ function setupExtraNetworksForTab(tabname) { }); }); + gradioApp().getElementById(`${tabname}_extra_tabs`).onmouseover = (e) => { + const el = e?.target?.parentElement; + if (!el?.classList?.contains('card')) return; + if (el.title === previousCard) return; + readCardDescription(el.dataset.filename, el.dataset.description); + readCardTags(el, el.dataset.tags); + e.stopPropagation(); + e.preventDefault(); + previousCard = el.title; + }; + const intersectionObserver = new IntersectionObserver((entries) => { if (!en) return; for (const el of Array.from(gradioApp().querySelectorAll('.extra-networks-page'))) el.style.height = `${window.opts.extra_networks_height}vh`; @@ -107,10 +227,6 @@ function setupExtraNetworks() { log('initExtraNetworks'); } -onUiLoaded(setupExtraNetworks); -const re_extranet = /<([^:]+:[^:]+):[\d\.]+>/; -const re_extranet_g = /\s+<([^:]+:[^:]+):[\d\.]+>/g; - function tryToRemoveExtraNetworkFromPrompt(textarea, text) { let m = text.match(re_extranet); let replaced = false; @@ -148,48 +264,11 @@ function refreshExtraNetworks(tabname) { function cardClicked(textToAdd, allowNegativePrompt) { const tabname = getENActiveTab(); const textarea = allowNegativePrompt ? activePromptTextarea[tabname] : gradioApp().querySelector(`#${tabname}_prompt > label > textarea`); - if (!tryToRemoveExtraNetworkFromPrompt(textarea, textToAdd)) textarea.value = textarea.value + opts.extra_networks_add_text_separator + textToAdd; + if (textarea.value.indexOf(textToAdd) !== -1) textarea.value = textarea.value.replace(textToAdd, ''); + else textarea.value += textToAdd; updateInput(textarea); } -function saveCardPreview(event, filename) { - const tabname = getENActiveTab(); - const textarea = gradioApp().querySelector(`#${tabname}_preview_filename > label > textarea`); - const button = gradioApp().getElementById(`${tabname}_save_preview`); - textarea.value = filename; - updateInput(textarea); - button.click(); - event.stopPropagation(); - event.preventDefault(); -} - -function saveCardDescription(event, filename, descript) { - const tabname = getENActiveTab(); - const textarea = gradioApp().querySelector(`#${tabname}_description_filename > label > textarea`); - const button = gradioApp().getElementById(`${tabname}_save_description`); - const description = gradioApp().getElementById(`${tabname}_description`); - textarea.value = filename; - description.value = descript; - updateInput(textarea); - button.click(); - event.stopPropagation(); - event.preventDefault(); -} - -function readCardDescription(event, filename, descript, extraPage, cardName) { - const tabname = getENActiveTab(); - const textarea = gradioApp().querySelector(`#${tabname}_description_filename > label > textarea`); - const description = gradioApp().querySelector(`#${tabname}_description > label > textarea`); - const button = gradioApp().getElementById(`${tabname}_read_description`); - textarea.value = filename; - description.value = descript?.trim() || ''; - updateInput(textarea); - updateInput(description); - button.click(); - event.stopPropagation(); - event.preventDefault(); -} - function extraNetworksSearchButton(event) { const tabname = getENActiveTab(); const searchTextarea = gradioApp().querySelector(`#${tabname}_extra_tabs > div > div > textarea`); @@ -199,60 +278,4 @@ function extraNetworksSearchButton(event) { updateInput(searchTextarea); } -function popup(contents) { - if (!globalPopup) { - globalPopup = document.createElement('div'); - globalPopup.onclick = () => { globalPopup.style.display = 'none'; }; - globalPopup.classList.add('global-popup'); - const close = document.createElement('div'); - close.classList.add('global-popup-close'); - close.onclick = () => { globalPopup.style.display = 'none'; }; - close.title = 'Close'; - globalPopup.appendChild(close); - globalPopupInner = document.createElement('div'); - globalPopupInner.onclick = (event) => { event.stopPropagation(); return false; }; - globalPopupInner.classList.add('global-popup-inner'); - globalPopup.appendChild(globalPopupInner); - gradioApp().appendChild(globalPopup); - } - globalPopupInner.innerHTML = ''; - globalPopupInner.appendChild(contents); - globalPopup.style.display = 'flex'; -} - -function readCardMetadata(event, extraPage, cardName) { - requestGet('./sd_extra_networks/metadata', { page: extraPage, item: cardName }, (data) => { - if (data?.metadata) { - if (typeof (data?.metadata) !== 'string') data.metadata = JSON.stringify(data.metadata, null, 2); - const elem = document.createElement('pre'); - elem.classList.add('popup-metadata'); - elem.textContent = data.metadata; - popup(elem); - } - }, () => {}); - event.stopPropagation(); - event.preventDefault(); -} - -function readCardTags(event, extraPage, cardTags) { - if ((cardTags || []).length === 0) return; - const textarea = activePromptTextarea[getENActiveTab()]; - const textToAdd = cardTags.join(' '); - if (!tryToRemoveExtraNetworkFromPrompt(textarea, textToAdd)) textarea.value = textarea.value + opts.extra_networks_add_text_separator + textToAdd; - updateInput(textarea); - event.stopPropagation(); - event.preventDefault(); -} - -function readCardInformation(event, extraPage, cardName) { - requestGet('./sd_extra_networks/info', { page: extraPage, item: cardName }, (data) => { - if (data?.info && (typeof (data?.info) === 'string')) { - const elem = document.createElement('pre'); - elem.classList.add('popup-metadata'); - elem.textContent = data.info; - popup(elem); - } - }, () => {}); - event.stopPropagation(); - event.preventDefault(); -} +onUiLoaded(setupExtraNetworks); diff --git a/javascript/style.css b/javascript/style.css index 491d21d7e..a42aea0e0 100644 --- a/javascript/style.css +++ b/javascript/style.css @@ -120,7 +120,7 @@ div#extras_scale_to_tab div.form{ flex-direction: row; } #quicksettings > button { margin-left: -0.5em; } #settings { display: flex; gap: var(--layout-gap); } -#settings div { border: none; display: inline-flex; justify-content: normal; gap: 0.5em; } +#settings div { border: none; justify-content: normal; gap: 0.5em; } #settings > div.tab-content { flex: 10 0 75%; display: grid; } #settings > div.tab-content > div { border: none; padding: 0; } @@ -129,7 +129,7 @@ div#extras_scale_to_tab div.form{ flex-direction: row; } #settings > div.tab-nav button { display: block; border: none; text-align: left; white-space: initial; padding: 0; } #settings > div.tab-nav > #settings_show_all_pages { padding: var(--size-2) var(--size-4); } #settings .block.gradio-checkbox { margin: 0; width: auto; } -#settings .dirtyable { display: grid; gap: .5em; } +#settings .dirtyable { gap: .5em; } #settings .dirtyable.hidden { display: none; } #settings .modification-indicator { height: 1.2em; border-radius: 1em !important; padding: 0; width: 0; margin-right: 0.5em; } #settings .modification-indicator:disabled { visibility: hidden; } @@ -240,11 +240,15 @@ table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-widt .extra-network-cards .card .overlay { position: absolute; bottom: 0; padding: 0.2em; z-index: 10; width: 100%; background: none; } .extra-network-cards .card:hover .overlay { background: rgba(0, 0, 0, 0.40); } .extra-network-cards .card .overlay .name { font-size: 1.2em; font-weight: bold; line-break: anywhere; text-shadow: 1px 1px black; color: white; } -.extra-network-cards .card .overlay .actions { font-size: 2.2em; display: none; text-align-last: justify; cursor: pointer; word-spacing: -6px; font-variant: unicase; letter-spacing: 4px; } -.extra-network-cards .card:hover .overlay .actions { display: block; } +.extra-network-cards .card .overlay .tags { margin: 4px; display: none; overflow-wrap: break-word; } +.extra-network-cards .card .overlay .tag { padding: 2px; margin: 2px; background: var(--neutral-700); cursor: pointer; display: inline-block; } +.extra-network-cards .card .overlay .actions { font-size: 2.2em; display: none; text-align-last: center; cursor: pointer; font-variant: unicase; height: 0.8em } +.extra-network-cards .card .overlay .actions > span { padding: 4px; } .extra-network-cards .card .overlay .description { line-break: anywhere; display: none; color: white; } -.extra-network-cards .card:hover .overlay .description { display: block; } .extra-network-cards .card .preview { box-shadow: var(--button-shadow); min-height: 30px; } +.extra-network-cards .card:hover .overlay .actions { display: block; } +.extra-network-cards .card:hover .overlay .tags { display: block; } +.extra-network-cards .card:hover .overlay .description { display: block; } .extra-network-cards .card:hover .preview { box-shadow: none; } /* controlnet */ diff --git a/modules/lora b/modules/lora index cf8021020..59c9a8e7a 160000 --- a/modules/lora +++ b/modules/lora @@ -1 +1 @@ -Subproject commit cf8021020f82398b3338019b72e15fe293863be6 +Subproject commit 59c9a8e7aec9dfc910d4ee2a11cebc01786b5eda diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index 87c142cb5..a2f3e00df 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -1,3 +1,4 @@ +import time import inspect import typing import torch @@ -54,6 +55,12 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro shared.state.current_latent = latents if shared.state.interrupted or shared.state.skipped: raise AssertionError('Interrupted...') + if shared.state.paused: + shared.log.debug('Sampling paused') + while shared.state.paused: + if shared.state.interrupted or shared.state.skipped: + raise AssertionError('Interrupted...') + time.sleep(0.1) def full_vae_decode(latents, model): shared.log.debug(f'VAE decode: name={sd_vae.loaded_vae_file if sd_vae.loaded_vae_file is not None else "baked"} dtype={model.vae.dtype} upcast={model.vae.config.get("force_upcast", None)} images={latents.shape[0]}') diff --git a/modules/shared.py b/modules/shared.py index 26f6efce7..b990ed348 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -8,7 +8,6 @@ from urllib.parse import urlparse from enum import Enum import gradio as gr import tqdm -import requests import fasteners from modules import errors, ui_components, shared_items, cmd_args from modules.paths_internal import models_path, script_path, data_path, sd_configs_path, sd_default_config, sd_model_file, default_sd_model_file, extensions_dir, extensions_builtin_dir # pylint: disable=W0611 @@ -288,6 +287,7 @@ def disable_extensions(): def refresh_themes(): + import requests try: req = requests.get('https://huggingface.co/datasets/freddyaboulton/gradio-theme-subdomains/resolve/main/subdomains.json', timeout=5) if req.status_code == 200: @@ -392,9 +392,9 @@ options_templates.update(options_section(('cuda', "Compute Settings"), { "cudnn_benchmark": OptionInfo(False, "Enable full-depth cuDNN benchmark feature"), # "cuda_allow_tf32": OptionInfo(True, "Allow TF32 math ops"), # "cuda_allow_tf16_reduced": OptionInfo(True, "Allow TF16 reduced precision math ops"), - "cuda_compile": OptionInfo(True if cmd_opts.use_openvino else False, "Enable model compile (experimental)"), - "cuda_compile_backend": OptionInfo("openvino_fx" if cmd_opts.use_openvino else "none", "Model compile backend (experimental)", gr.Radio, lambda: {"choices": ['none', 'inductor', 'cudagraphs', 'aot_ts_nvfuser', 'hidet', 'ipex', 'openvino_fx']}), - "cuda_compile_mode": OptionInfo("default", "Model compile mode (experimental)", gr.Radio, lambda: {"choices": ['default', 'reduce-overhead', 'max-autotune']}), + "cuda_compile": OptionInfo(True if cmd_opts.use_openvino else False, "Enable model compile"), + "cuda_compile_backend": OptionInfo("openvino_fx" if cmd_opts.use_openvino else "none", "Model compile backend", gr.Radio, lambda: {"choices": ['none', 'inductor', 'cudagraphs', 'aot_ts_nvfuser', 'hidet', 'ipex', 'openvino_fx']}), + "cuda_compile_mode": OptionInfo("default", "Model compile mode", gr.Radio, lambda: {"choices": ['default', 'reduce-overhead', 'max-autotune']}), "cuda_compile_fullgraph": OptionInfo(False, "Model compile fullgraph"), "cuda_compile_precompile": OptionInfo(False, "Model compile precompile"), "cuda_compile_verbose": OptionInfo(False, "Model compile verbose mode"), @@ -521,8 +521,6 @@ options_templates.update(options_section(('ui', "User Interface"), { "keyedit_precision_extra": OptionInfo(0.05, "Ctrl+up/down precision when editing ", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}), "keyedit_delimiters": OptionInfo(".,\/!?%^*;:{}=`~()", "Ctrl+up/down word delimiters"), # pylint: disable=anomalous-backslash-in-string "quicksettings_list": OptionInfo(["sd_model_checkpoint"], "Quicksettings list", ui_components.DropdownMulti, lambda: {"choices": list(opts.data_labels.keys())}), - # "hidden_tabs": OptionInfo([], "Hidden UI tabs", ui_components.DropdownMulti, lambda: {"choices": list(tab_names)}), - # "ui_tab_reorder": OptionInfo("From Text, From Image, Process Image", "UI tabs order"), "ui_scripts_reorder": OptionInfo("", "UI scripts order"), })) @@ -542,8 +540,6 @@ options_templates.update(options_section(('live-preview', "Live Previews"), { options_templates.update(options_section(('sampler-params', "Sampler Settings"), { "show_samplers": OptionInfo(["Default", "Euler a", "UniPC", "DEIS", "DDIM", "DPM 1S", "DPM 2M", "DPM++ 2M SDE", "DPM++ 2M SDE Karras", "DPM2 Karras", "DPM++ 2M Karras"], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers() if x.name != "PLMS"]}), - # "fallback_sampler": OptionInfo("Euler a", "Secondary sampler", gr.Dropdown, lambda: {"choices": ["None"] + [x.name for x in list_samplers()]}), - # "force_latent_sampler": OptionInfo("None", "Force latent upscaler sampler", gr.Dropdown, lambda: {"choices": ["None"] + [x.name for x in list_samplers()]}), 'uni_pc_variant': OptionInfo("bh1", "UniPC variant", gr.Radio, {"choices": ["bh1", "bh2", "vary_coeff"]}), 'uni_pc_skip_type': OptionInfo("time_uniform", "UniPC skip type", gr.Radio, {"choices": ["time_uniform", "time_quadratic", "logSNR"]}), 'eta_noise_seed_delta': OptionInfo(0, "Noise seed delta (eta)", gr.Number, {"precision": 0}), @@ -645,11 +641,9 @@ options_templates.update(options_section(('extra_networks', "Extra Networks"), { "extra_networks_card_fit": OptionInfo("cover", "UI image contain method", gr.Radio, lambda: {"choices": ["contain", "cover", "fill"]}), "extra_network_skip_indexing": OptionInfo(False, "Do not automatically build extra network pages", gr.Checkbox), "lyco_patch_lora": OptionInfo(False, "Use LyCoris handler for all LoRA types", gr.Checkbox), - # "lora_disable": OptionInfo(False, "Disable built-in Lora handler", gr.Checkbox, { "visible": True }, onchange=disable_extensions), "lora_functional": OptionInfo(False, "Use Kohya method for handling multiple LoRA", gr.Checkbox), - "extra_networks_add_text_separator": OptionInfo(" ", "Extra text to add before <...> when adding extra network to prompt", gr.Text, { "visible": False }), "extra_networks_default_multiplier": OptionInfo(1.0, "Multiplier for extra networks", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), - "sd_hypernetwork": OptionInfo("None", "Add hypernetwork to prompt", gr.Dropdown, lambda: {"choices": ["None"] + list(hypernetworks.keys())}, refresh=reload_hypernetworks), + "sd_hypernetwork": OptionInfo("None", "Add hypernetwork to prompt", gr.Dropdown, lambda: { "choices": ["None"] + list(hypernetworks.keys()), "visible": False }, refresh=reload_hypernetworks), })) options_templates.update(options_section((None, "Hidden options"), { diff --git a/modules/ui.py b/modules/ui.py index 612cc406e..7f5159835 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -911,7 +911,7 @@ def create_ui(startup_timer = None): info = opts.data_labels[key] t = type(info.default) - args = info.component_args() if callable(info.component_args) else info.component_args + args = (info.component_args() if callable(info.component_args) else info.component_args) or {} if info.component is not None: comp = info.component elif t == str: @@ -925,21 +925,21 @@ def create_ui(startup_timer = None): elem_id = f"setting_{key}" if not is_quicksettings: - dirtyable_setting = gr.Group(elem_classes="dirtyable", visible=(args or {}).get("visible", True)) + dirtyable_setting = gr.Group(elem_classes="dirtyable", visible=args.get("visible", True)) dirtyable_setting.__enter__() dirty_indicator = gr.Button("", elem_classes="modification-indicator", elem_id="modification_indicator_" + key) if info.refresh is not None: if is_quicksettings: - res = comp(label=info.label, value=fun(), elem_id=elem_id, **(args or {})) - create_refresh_button(res, info.refresh, info.component_args, f"refresh_{key}") + res = comp(label=info.label, value=fun(), elem_id=elem_id, **args) + create_refresh_button(res, info.refresh, args, f"refresh_{key}") else: with FormRow(): - res = comp(label=info.label, value=fun(), elem_id=elem_id, **(args or {})) - create_refresh_button(res, info.refresh, info.component_args, f"refresh_{key}") + res = comp(label=info.label, value=fun(), elem_id=elem_id, **args) + create_refresh_button(res, info.refresh, args, f"refresh_{key}") else: try: - res = comp(label=info.label, value=fun(), elem_id=elem_id, **(args or {})) + res = comp(label=info.label, value=fun(), elem_id=elem_id, **args) except Exception as e: log.error(f'Error creating setting: {key} {e}') res = None diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index ef64a9812..9834309f0 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -37,7 +37,7 @@ def listdir(path): def register_page(page): - """registers extra networks page for the UI; recommend doing it in on_before_ui() callback for extensions""" + # registers extra networks page for the UI; recommend doing it in on_before_ui() callback for extensions extra_pages.append(page) allowed_dirs.clear() allowed_dirs.update(set(sum([x.allowed_directories_for_previews() for x in extra_pages], []))) @@ -93,19 +93,17 @@ class ExtraNetworksPage: self.missing_thumbs = [] # class additional is to keep old extensions happy self.card = ''' -
+
{name}
-
{description}
+
    - πŸ’™ - πŸ“– + ⏺️ πŸ›… πŸ“˜ ℹ️ - #️
    @@ -237,32 +235,28 @@ class ExtraNetworksPage: def create_html_for_item(self, item, tabname): try: - tags = [item.get("tags")] if isinstance(item.get("tags", {}), str) else list(item.get("tags", {}).keys()) args = { + "tabname": json.dumps(tabname), + "name": item["name"], + "title": item["name"], + "tags": '|'.join([item.get("tags")] if isinstance(item.get("tags", {}), str) else list(item.get("tags", {}).keys())), "preview": html.escape(item.get("preview", None)), "width": shared.opts.extra_networks_card_size, "height": shared.opts.extra_networks_card_size if shared.opts.extra_networks_card_square else 'auto', "fit": shared.opts.extra_networks_card_fit, - "prompt": item.get("prompt", None), - "tabname": json.dumps(tabname), - "local_preview": json.dumps(item["local_preview"]), - "name": item["name"], - "description": (item.get("description") or ""), - "search_term": item.get("search_term", ""), "loading": "lazy" if shared.opts.extra_networks_card_lazy else "eager", - "card_click": item.get("onclick", '"' + html.escape(f"""return cardClicked({item.get("prompt", None)}, {"true" if self.allow_negative_prompt else "false"})""") + '"'), - "card_read_desc": '"' + html.escape(f"""return readCardDescription(event, {json.dumps(item["local_preview"])}, {json.dumps(item.get("description", ""))})""") + '"', - "card_save_desc": '"' + html.escape(f"""return saveCardDescription(event, {json.dumps(item["local_preview"])})""") + '"', - "card_read_meta": '"' + html.escape(f"""return readCardMetadata(event, {json.dumps(self.name)}, {json.dumps(item["name"])})""") + '"', - "card_read_info": '"' + html.escape(f"""return readCardInformation(event, {json.dumps(self.name)}, {json.dumps(item["name"])})""") + '"', - "card_read_tags": '"' + html.escape(f"""return readCardTags(event, {json.dumps(self.name)}, {json.dumps(tags)})""") + '"', - "card_save_preview": '"' + html.escape(f"""return saveCardPreview(event, {json.dumps(item["local_preview"])})""") + '"', - "title": f'Name: {item["name"]}', + "prompt": item.get("prompt", None), + "search_term": item.get("search_term", ""), + "description": item.get("description") or "", + "local_preview": item["local_preview"], + "card_click": item.get("onclick", '"' + html.escape(f'return cardClicked({item.get("prompt", None)}, {"true" if self.allow_negative_prompt else "false"})') + '"'), + "card_save_preview": '"' + html.escape('return saveCardPreview(event)') + '"', + "card_save_desc": '"' + html.escape('return saveCardDescription(event)') + '"', + "card_read_meta": '"' + html.escape(f'return readCardMetadata(event, {json.dumps(self.name)}, {json.dumps(item["name"])})') + '"', + "card_read_info": '"' + html.escape(f'return readCardInformation(event, {json.dumps(self.name)}, {json.dumps(item["name"])})') + '"', } if item.get("alias", None) is not None: args['title'] += f'\nAlias: {item["alias"]}' - if item.get("tags", None) is not None: - args['title'] += f'\nTags: {", ".join(tags)}' return self.card.format(**args) except Exception as e: shared.log.error(f'Extra networks item error: page={tabname} item={item["name"]} {e}') @@ -329,6 +323,7 @@ class ExtraNetworksUi: self.button_read_description = None self.description_target_filename = None self.description = None + self.tags = None self.tabname = None self.search = None @@ -357,12 +352,10 @@ def create_ui(container, button, tabname, skip_indexing = False): button_close = ToolButton(close_symbol, elem_id=tabname+"_extra_close") ui.search = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", elem_classes="textbox", lines=1) ui.description = gr.TextArea('', show_label=False, elem_id=tabname+"_description", placeholder="Save/Replace Extra Network Description...", elem_classes="textbox", lines=1) - - ui.button_save_preview = gr.Button('Save preview', elem_id=tabname+"_save_preview", visible=False) ui.preview_target_filename = gr.Textbox('Preview save filename', elem_id=tabname+"_preview_filename", visible=False) - ui.button_save_description = gr.Button('Save description', elem_id=tabname+"_save_description", visible=False) - ui.button_read_description = gr.Button('Read description', elem_id=tabname+"_read_description", visible=False) + ui.button_save_preview = gr.Button('Save preview', elem_id=tabname+"_save_preview", visible=False) ui.description_target_filename = gr.Textbox('Description save filename', elem_id=tabname+"_description_filename", visible=False) + ui.button_save_description = gr.Button('Save description', elem_id=tabname+"_save_description", visible=False) for page in ui.stored_extra_pages: shared.log.debug(f"Extra network page: {page.title} tab={tabname}") @@ -432,21 +425,21 @@ def setup_ui(ui, gallery): ) # write description to a file - def save_description(filename,descrip): + def save_description(filename, desc): lastDotIndex = filename.rindex('.') - filename = filename[0:lastDotIndex]+".description.txt" - if descrip != "": + filename = filename[0:lastDotIndex]+".txt" + if desc != "": try: with open(filename,'w', encoding='utf-8') as f: - f.write(descrip) - shared.log.info(f'Extra network save description: {filename}') + f.write(desc) + shared.log.info(f'Extra network save description: {filename} {desc}') except Exception as e: - shared.log.error(f'Extra network save preview: {filename} {e}') + shared.log.error(f'Extra network save description: {filename} {e}') return [page.create_html(ui.tabname) for page in ui.stored_extra_pages] ui.button_save_description.click( fn=save_description, - _js="function(x,y){return [x,y]}", + _js="function(x,y) {return [x,y]}", inputs=[ui.description_target_filename, ui.description], outputs=[*ui.pages] ) diff --git a/wiki b/wiki index e61edfe21..3f1cf21d7 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit e61edfe21d5b0b607cb20d9782cf16df6b77eb4a +Subproject commit 3f1cf21d77444887139e6a80bf7273e437ee4f50