diff --git a/extensions-builtin/Lora/ui_extra_networks_lora.py b/extensions-builtin/Lora/ui_extra_networks_lora.py index 3cb84170f..66b7cc06a 100644 --- a/extensions-builtin/Lora/ui_extra_networks_lora.py +++ b/extensions-builtin/Lora/ui_extra_networks_lora.py @@ -44,7 +44,7 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): activation_text = item["user_metadata"].get("activation text") preferred_weight = item["user_metadata"].get("preferred weight", 0.0) item["prompt"] = quote_js(f"") - + if activation_text: item["prompt"] += " + " + quote_js(" " + activation_text) diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index ff6130a7d..7015a6a2a 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -11,7 +11,7 @@ var globalPopupInner = null; const storedPopupIds = {}; const extraPageUserMetadataEditors = {}; // A flag used by the `waitForBool` promise to determine when we first load Ui Options. -const initialUiOptionsLoaded = { state: false }; +const initialUiOptionsLoaded = {state: false}; /** Helper functions for checking types and simplifying logging. */ @@ -42,7 +42,7 @@ const isElementLogError = x => { } console.error("expected element type, got:", typeof x); return false; -} +}; const getElementByIdLogError = selector => { let elem = gradioApp().getElementById(selector); @@ -54,17 +54,17 @@ const querySelectorLogError = selector => { let elem = gradioApp().querySelector(selector); isElementLogError(elem); return elem; -} +}; const debounce = (handler, timeout_ms) => { /** Debounces a function call. - * + * * NOTE: This will NOT work if called from within a class. * It will drop `this` from scope. - * + * * Repeated calls to the debounce handler will not call the handler until there are * no new calls to the debounce handler for timeout_ms time. - * + * * Example: * function add(x, y) { return x + y; } * let debounce_handler = debounce(add, 5000); @@ -73,7 +73,7 @@ const debounce = (handler, timeout_ms) => { * res = debounce_handler(i, 100); * } * console.log("Result:", res); - * + * * This example will print "Result: 109". */ let timer = null; @@ -81,7 +81,7 @@ const debounce = (handler, timeout_ms) => { clearTimeout(timer); timer = setTimeout(() => handler(...args), timeout_ms); }; -} +}; const waitForElement = selector => { /** Promise that waits for an element to exist in DOM. */ @@ -102,14 +102,14 @@ const waitForElement = selector => { subtree: true }); }); -} +}; const waitForBool = o => { /** Promise that waits for a boolean to be true. - * + * * `o` must be an Object of the form: * { state: } - * + * * Resolves when (state === true) */ return new Promise(resolve => { @@ -120,17 +120,17 @@ const waitForBool = o => { setTimeout(_waitForBool, 100); })(); }); -} +}; -const waitForKeyInObject = o => { +const waitForKeyInObject = o => { /** Promise that waits for a key to exist in an object. - * + * * `o` must be an Object of the form: * { * obj: , - * k: , + * k: , * } - * + * * Resolves when (k in obj) */ return new Promise(resolve => { @@ -141,22 +141,22 @@ const waitForKeyInObject = o => { setTimeout(_waitForKeyInObject, 100); })(); }); -} +}; const waitForValueInObject = o => { /** Promise that waits for a key value pair in an Object. - * + * * `o` must be an Object of the form: * { * obj: , * k: , * v: * } - * + * * Resolves when obj[k] == v */ return new Promise(resolve => { - waitForKeyInObject({ k: o.k, obj: o.obj }).then(() => { + waitForKeyInObject({k: o.k, obj: o.obj}).then(() => { (function _waitForValueInObject() { if (o.k in o.obj && o.obj[o.k] == o.v) { @@ -166,7 +166,7 @@ const waitForValueInObject = o => { })(); }); }); -} +}; function toggleCss(key, css, enable) { var style = document.getElementById(key); @@ -197,7 +197,7 @@ function extraNetworksRefreshTab(tabname_full) { div_dirs.classList.toggle("hidden", !("selected" in btn_dirs_view.dataset)); div_tree.classList.toggle("hidden", !("selected" in btn_tree_view.dataset)); - waitForKeyInObject({ k: tabname_full, obj: clusterizers }) + waitForKeyInObject({k: tabname_full, obj: clusterizers}) .then(() => extraNetworkClusterizersOnTabLoad(tabname_full)); } @@ -208,7 +208,7 @@ function extraNetworksRegisterPromptForTab(tabname, id) { activePromptTextarea[tabname] = textarea; } - textarea.addEventListener("focus", function () { + textarea.addEventListener("focus", function() { activePromptTextarea[tabname] = textarea; }); } @@ -321,7 +321,7 @@ function extraNetworksTabSelected(tabname, id, showPrompt, showNegativePrompt, t extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePrompt); extraNetworksShowControlsForPage(tabname, tabname_full); - waitForKeyInObject({ k: tabname_full, obj: clusterizers }) + waitForKeyInObject({k: tabname_full, obj: clusterizers}) .then(() => extraNetworkClusterizersOnTabLoad(tabname_full)); } @@ -370,8 +370,8 @@ function extraNetworkClusterizersOnTabLoad(tabname_full) { /** promise */ if (!(tabname_full in clusterizers)) { return resolve(); } - - (async () => { + + (async() => { // Enable then load the selected tab's clusterize lists. extraNetworksClusterizersEnable(tabname_full); for (const v of Object.values(clusterizers[tabname_full])) { @@ -428,7 +428,7 @@ function tryToRemoveExtraNetworkFromPrompt(textarea, text, isNeg) { var extraTextAfterNet = m[2]; var partToSearch = m[1]; var foundAtPosition = -1; - newTextareaText = textarea.value.replaceAll(isNeg ? re_extranet_g_neg : re_extranet_g, function (found, net, pos) { + newTextareaText = textarea.value.replaceAll(isNeg ? re_extranet_g_neg : re_extranet_g, function(found, net, pos) { m = found.match(isNeg ? re_extranet_neg : re_extranet); if (m[1] == partToSearch) { replaced = true; @@ -608,7 +608,7 @@ function extraNetworksControlSearchClearOnClick(event, tabname_full) { txt_search.dispatchEvent( new CustomEvent( "extra-network-control--search-clear", - { detail: { tabname_full: tabname_full } }, + {detail: {tabname_full: tabname_full}}, ) ); } @@ -809,12 +809,12 @@ function extraNetworksShowMetadata(text) { function requestGet(url, data, handler, errorHandler) { var xhr = new XMLHttpRequest(); - var args = Object.keys(data).map(function (k) { + var args = Object.keys(data).map(function(k) { return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]); }).join('&'); xhr.open("GET", url + "?" + args, true); - xhr.onreadystatechange = function () { + xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { try { @@ -839,11 +839,11 @@ function extraNetworksCopyPathToClipboard(event, path) { } function extraNetworksRequestMetadata(event, extraPage, cardName) { - var showError = function () { + var showError = function() { extraNetworksShowMetadata("there was an error getting metadata"); }; - requestGet("./sd_extra_networks/metadata", { page: extraPage, item: cardName }, function (data) { + requestGet("./sd_extra_networks/metadata", {page: extraPage, item: cardName}, function(data) { if (data && data.metadata) { extraNetworksShowMetadata(data.metadata); } else { @@ -877,7 +877,7 @@ function extraNetworksEditUserMetadata(event, tabname, extraPage, cardName) { } function extraNetworksRefreshSingleCard(page, tabname, name) { - requestGet("./sd_extra_networks/get-single-card", { page: page, tabname: tabname, name: name }, function (data) { + requestGet("./sd_extra_networks/get-single-card", {page: page, tabname: tabname, name: name}, function(data) { if (data && data.html) { var card = gradioApp().querySelector(`#${tabname}_${page.replace(" ", "_")}_cards > .card[data-name="${name}"]`); @@ -892,11 +892,11 @@ function extraNetworksRefreshSingleCard(page, tabname, name) { }); } -window.addEventListener("keydown", function (event) { +window.addEventListener("keydown", function(event) { if (event.key == "Escape") { closePopup(); } }); onUiLoaded(setupExtraNetworks); -onOptionsChanged(() => initialUiOptionsLoaded.state = true); \ No newline at end of file +onOptionsChanged(() => initialUiOptionsLoaded.state = true); diff --git a/javascript/extraNetworksClusterizeList.js b/javascript/extraNetworksClusterizeList.js index c00f037db..9cc6f372e 100644 --- a/javascript/extraNetworksClusterizeList.js +++ b/javascript/extraNetworksClusterizeList.js @@ -1,8 +1,8 @@ const JSON_UPDATE_DEBOUNCE_TIME_MS = 250; const RESIZE_DEBOUNCE_TIME_MS = 250; // Collators used for sorting. -const INT_COLLATOR = new Intl.Collator([], { numeric: true }); -const STR_COLLATOR = new Intl.Collator("en", { numeric: true, sensitivity: "base" }); +const INT_COLLATOR = new Intl.Collator([], {numeric: true}); +const STR_COLLATOR = new Intl.Collator("en", {numeric: true, sensitivity: "base"}); class InvalidCompressedJsonDataError extends Error { constructor(message, options) { @@ -19,7 +19,7 @@ const getComputedPropertyDims = (elem, prop) => { bottom: parseFloat(style.getPropertyValue(`${prop}-bottom`)), right: parseFloat(style.getPropertyValue(`${prop}-right`)), }; -} +}; const getComputedMarginDims = elem => { /** Returns the width/height of the computed margin of an element. */ @@ -28,7 +28,7 @@ const getComputedMarginDims = elem => { width: dims.left + dims.right, height: dims.top + dims.bottom, }; -} +}; const getComputedPaddingDims = elem => { /** Returns the width/height of the computed padding of an element. */ @@ -37,7 +37,7 @@ const getComputedPaddingDims = elem => { width: dims.left + dims.right, height: dims.top + dims.bottom, }; -} +}; const getComputedBorderDims = elem => { /** Returns the width/height of the computed border of an element. */ @@ -49,7 +49,7 @@ const getComputedBorderDims = elem => { width: dims.left + dims.right, height: dims.top + dims.bottom, }; -} +}; const getComputedDims = elem => { /** Returns the full width and height of an element including its margin, padding, and border. */ @@ -61,8 +61,8 @@ const getComputedDims = elem => { return { width: width + margin.width + padding.width + border.width, height: height + margin.height + padding.height + border.height, - } -} + }; +}; async function decompress(base64string) { /** Decompresses a base64 encoded ZLIB compressed string. */ @@ -82,14 +82,14 @@ async function decompress(base64string) { } } -const htmlStringToElement = function (str) { +const htmlStringToElement = function(str) { /** Converts an HTML string into an Element type. */ let parser = new DOMParser(); let tmp = parser.parseFromString(str, "text/html"); return tmp.body.firstElementChild; -} +}; -const getComputedValue = function (container, css_property) { +const getComputedValue = function(container, css_property) { /** Gets a property value for the computed style of an element. */ return parseInt( window.getComputedStyle(container, null) @@ -98,18 +98,18 @@ const getComputedValue = function (container, css_property) { ); }; -const calcColsPerRow = function (parent, child) { +const calcColsPerRow = function(parent, child) { /** Calculates the number of columns of children that can fit in a parent's visible width. */ const parent_inner_width = parent.offsetWidth - getComputedPaddingDims(parent).width; return parseInt(parent_inner_width / getComputedDims(child).width); -} +}; -const calcRowsPerCol = function (parent, child) { +const calcRowsPerCol = function(parent, child) { /** Calculates the number of rows of children that can fit in a parent's visible height. */ const parent_inner_height = parent.offsetHeight - getComputedPaddingDims(parent).height; return parseInt(parent_inner_height / getComputedDims(child).height); -} +}; class ExtraNetworksClusterize { /** Base class for a clusterize list. Cannot be used directly. */ @@ -124,17 +124,25 @@ class ExtraNetworksClusterize { show_no_data_row = true, callbacks = {}, } = { - rows_in_block: 10, - blocks_in_cluster: 4, - show_no_data_row: true, - callbacks: {}, - } + rows_in_block: 10, + blocks_in_cluster: 4, + show_no_data_row: true, + callbacks: {}, + } ) { // Do not continue if any of the required parameters are invalid. - if (!isStringLogError(data_id)) { return; } - if (!isStringLogError(scroll_id)) { return; } - if (!isStringLogError(content_id)) { return; } - if (!isElementLogError(txt_search_elem)) { return; } + if (!isStringLogError(data_id)) { + return; + } + if (!isStringLogError(scroll_id)) { + return; + } + if (!isStringLogError(content_id)) { + return; + } + if (!isElementLogError(txt_search_elem)) { + return; + } this.data_id = data_id; this.scroll_id = scroll_id; @@ -154,7 +162,7 @@ class ExtraNetworksClusterize { this.resize_observer = null; this.resize_observer_timer = null; this.element_observer = null; - this.data_update_timer = null + this.data_update_timer = null; // Used to control logic. Many functions immediately return when disabled. this.enabled = false; @@ -193,7 +201,7 @@ class ExtraNetworksClusterize { load() { /** promise */ /** Loads this instance into the view. - * + * * Calling this function should be all that is needed in order to fully update * and display the clusterize list. */ @@ -201,7 +209,9 @@ class ExtraNetworksClusterize { waitForElement(`#${this.data_id}`) .then((elem) => this.data_elem = elem) .then(() => this.parseJson(this.data_elem.dataset.json)) - .then(() => { return resolve(); }); + .then(() => { + return resolve(); + }); }); } @@ -239,7 +249,9 @@ class ExtraNetworksClusterize { updateJson(json) { /** promise */ console.error("Base class method called. Must be overridden by subclass."); - return new Promise(resolve => { return resolve(); }); + return new Promise(resolve => { + return resolve(); + }); } sortByDivId() { @@ -249,11 +261,11 @@ class ExtraNetworksClusterize { applySort() { /** Sorts the rows using the instance's `sort_fn`. - * + * * It is expected that a subclass will override this function to update the * instance's `sort_fn` then call `super.applySort()` to apply the sorting. */ - this.sort_fn() + this.sort_fn(); if (this.sort_reverse) { this.data_obj_keys_sorted = this.data_obj_keys_sorted.reverse(); } @@ -261,7 +273,7 @@ class ExtraNetworksClusterize { applyFilter() { /** Sorts then updates the rows. - * + * * Should be overridden by subclass. Base class doesn't apply any filters. */ this.applySort(); @@ -304,7 +316,7 @@ class ExtraNetworksClusterize { updateRows() { /** Updates the instance using the stored rows in our data object. - * + * * Should be called whenever we change order or number of rows. */ // If we don't have any entries in the dataset, then just return. @@ -325,7 +337,7 @@ class ExtraNetworksClusterize { recalculateDims() { /** Recalculates the number of rows and columns that can fit within the scroll view. - * + * * Returns whether the rows/columns have changed indicating that we need to rebuild. */ let rebuild_required = false; @@ -342,7 +354,7 @@ class ExtraNetworksClusterize { // If no rows exist, we need to add one so we can calculate rows/cols. // We remove this row before returning. - if (this.rowCount() === 0) {// || this.content_elem.innerHTML === "") { + if (this.rowCount() === 0) { // || this.content_elem.innerHTML === "") { this.clear(); this.update([this.data_obj[this.data_obj_keys_sorted[0]].html]); clear_before_return = true; @@ -402,9 +414,9 @@ class ExtraNetworksClusterize { rebuild(force) { /** Rebuilds, updates, or initializes a clusterize instance. - * + * * TODO: Possibly rename this function to make its purpose more clear. - * + * * Performs one of the following: * 1. Initializes a new instance if we haven't already. * 2. Destroys and reinitializes an instance if we pass `force=true` or if @@ -412,7 +424,7 @@ class ExtraNetworksClusterize { * that we can show on screen to be updated. * 3. Simply updates the clusterize instance's rows with our current data * if none of the other conditions are met. - * + * */ // Only accept boolean values for `force` parameter. Default to false. if (force !== true) { @@ -474,17 +486,17 @@ class ExtraNetworksClusterize { onElementDetached(elem_id) { /** Callback whenever one of our elements has become detached from the DOM. */ switch (elem_id) { - case this.data_id: - waitForElement(`#${this.data_id}`).then((elem) => this.data_elem = elem); - break; - case this.scroll_id: - this.repair(); - break; - case this.content_id: - this.repair(); - break; - default: - break; + case this.data_id: + waitForElement(`#${this.data_id}`).then((elem) => this.data_elem = elem); + break; + case this.scroll_id: + this.repair(); + break; + case this.content_id: + this.repair(); + break; + default: + break; } } @@ -512,13 +524,13 @@ class ExtraNetworksClusterize { setupElementObservers() { /** Listens for changes to the data, scroll, and content elements. - * + * * During testing, the scroll/content elements would frequently get removed from * the DOM. Our clusterize instance stores a reference to these elements * which breaks whenever these elements are removed from the DOM. To fix this, * we need to check for these changes and re-attach our stores elements by * replacing the ones in the DOM with the ones in our clusterize instance. - * + * * We also use an observer to detect whenever the data element gets a new set * of JSON data so that we can update our dataset. */ @@ -550,7 +562,7 @@ class ExtraNetworksClusterize { this.onElementDetached(content_elem.id); } }); - this.element_observer.observe(gradioApp(), { subtree: true, childList: true, attributes: true }); + this.element_observer.observe(gradioApp(), {subtree: true, childList: true, attributes: true}); } setupResizeHandlers() { @@ -735,11 +747,11 @@ class ExtraNetworksClusterizeTreeList extends ExtraNetworksClusterize { if ("expanded" in elem.dataset) { this.data_obj[div_id].expanded = false; delete elem.dataset.expanded; - this.removeChildRows(div_id) + this.removeChildRows(div_id); } else { this.data_obj[div_id].expanded = true; elem.dataset.expanded = ""; - this.addChildRows(div_id) + this.addChildRows(div_id); } this.updateDivContent(div_id, elem); this.updateRows(); @@ -852,7 +864,9 @@ class ExtraNetworksClusterizeCardsList extends ExtraNetworksClusterize { if (isElement(search_terms_elem)) { search_terms = Array.prototype.map.call( parsed_html.querySelectorAll(".search_terms"), - (elem) => { return elem.textContent.toLowerCase(); } + (elem) => { + return elem.textContent.toLowerCase(); + } ).join(" "); } @@ -937,21 +951,21 @@ class ExtraNetworksClusterizeCardsList extends ExtraNetworksClusterize { this.sort_reverse = this.sort_dir_str === "descending"; switch (this.sort_mode_str) { - case "name": - this.sort_fn = this.sortByName; - break; - case "path": - this.sort_fn = this.sortByPath; - break; - case "created": - this.sort_fn = this.sortByCreated; - break; - case "modified": - this.sort_fn = this.sortByModified; - break; - default: - this.sort_fn = this.sortByDivId; - break; + case "name": + this.sort_fn = this.sortByName; + break; + case "path": + this.sort_fn = this.sortByPath; + break; + case "created": + this.sort_fn = this.sortByCreated; + break; + case "modified": + this.sort_fn = this.sortByModified; + break; + default: + this.sort_fn = this.sortByDivId; + break; } super.applySort(); } diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 16bec158f..7d4eb150b 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -35,6 +35,7 @@ class ExtraNetworksItem: """Wrapper for dictionaries representing ExtraNetworks items.""" item: dict + def get_tree(paths: Union[str, list[str]], items: dict[str, ExtraNetworksItem]) -> dict: """Recursively builds a directory tree. @@ -85,8 +86,12 @@ def get_tree(paths: Union[str, list[str]], items: dict[str, ExtraNetworksItem]) return res + 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], [])))