diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index 3856df0bf..699a823e8 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -2,6 +2,17 @@ /*global ExtraNetworksClusterizeTreeList, ExtraNetworksClusterizeCardsList, + waitForElement, + isElement, + isElementThrowError, + requestGetPromise, + isElementLogError, + isNumber, + waitForKeyInObject, + isNullOrUndefined, + debounce, + waitForBool, + copyToClipboard, */ /*eslint no-undef: "error"*/ @@ -173,7 +184,7 @@ class ExtraNetworksTab { this.cards_list.setFilterStr(this.filter_str); } - movePrompt(show_prompt=true, show_neg_prompt=true) { + movePrompt(show_prompt = true, show_neg_prompt = true) { // This function only applies when compact prompt mode is enabled. if (!this.compact_prompt_en) { return; @@ -239,7 +250,7 @@ class ExtraNetworksTab { } async load(show_prompt, show_neg_prompt) { - this.movePrompt(show_prompt=show_prompt, show_neg_prompt=show_neg_prompt); + this.movePrompt(show_prompt, show_neg_prompt); this.showControls(); this.tree_list.enable(true); this.cards_list.enable(true); @@ -256,11 +267,11 @@ class ExtraNetworksTab { applyFilter() { // We only want to filter/sort the cards list. this.setFilterStr(this.txt_search_elem.value.toLowerCase()); - + // If the search input has changed since selecting a button to populate it // then we want to disable the button that previously populated the search input. - // tree view buttons + // tree view buttons let btn = this.container_elem.querySelector(".tree-list-item[data-selected='']"); if (isElement(btn) && btn.dataset.path !== this.txt_search_elem.value && "selected" in btn.dataset) { this.tree_list.onRowSelected(btn.dataset.divId, btn, false); @@ -278,13 +289,14 @@ class ExtraNetworksTab { // immediately clicks a tab, then we will try to load the card data before // the server has even generated it. // We use status 503 to indicate that the page isnt ready yet. - while (true) { + let ready = false; + while (!ready) { try { await requestGetPromise( "./sd_extra_networks/page-is-ready", {extra_networks_tabname: this.extra_networks_tabname}, ); - break; + ready = true; } catch (error) { if (error.status === 503) { await new Promise(resolve => setTimeout(resolve, 250)); @@ -364,7 +376,7 @@ class ExtraNetworksTab { if (!isElementLogError(left_col)) { return; } - + // If the left column is hidden then we don't want to do anything. if (left_col.classList.contains("hidden")) { return; @@ -385,7 +397,7 @@ class ExtraNetworksTab { } } -// +// function popup(contents) { if (!globalPopup) { @@ -576,7 +588,9 @@ async function extraNetworksRefreshTab(tabname_full) { // ==== EVENT HANDLING ==== function extraNetworksFetchMetadata(extra_networks_tabname, card_name) { - const _showError = () => { extraNetworksShowMetadata("there was an error getting metadata"); }; + const _showError = () => { + extraNetworksShowMetadata("there was an error getting metadata"); + }; requestGet( "./sd_extra_networks/metadata", @@ -604,7 +618,7 @@ async function extraNetworksTabSelected(tabname_full, show_prompt, show_neg_prom await waitForKeyInObject({obj: extra_networks_tabs, k: tabname_full}); for (const [k, v] of Object.entries(extra_networks_tabs)) { if (k === tabname_full) { - await v.load(show_prompt=show_prompt, show_neg_prompt=show_neg_prompt); + await v.load(show_prompt, show_neg_prompt); } else { v.unload(); } @@ -749,7 +763,7 @@ function extraNetworksControlRefreshOnClick(event, tabname_full) { */ // We want to reset all tabs lists on refresh click so that the viewing area // shows that it is loading new data. - for (tab of Object.values(extra_networks_tabs)) { + for (const tab of Object.values(extra_networks_tabs)) { tab.tree_list.destroy(); tab.cards_list.destroy(); } @@ -802,7 +816,7 @@ function extraNetworksTreeDirectoryOnClick(event, btn, tabname_full) { delete elem.dataset.selected; } }); - + } tab.updateSearch("selected" in btn.dataset ? btn.dataset.path : ""); } @@ -908,7 +922,7 @@ async function extraNetworksSetupTab(tabname) { controls_div.classList.add("extra-network-controls-div"); tab_nav.appendChild(controls_div); tab_nav.insertBefore(controls_div, null); - + const panes = this_tab.querySelectorAll(`:scope > .tabitem[id^="${tabname}_"]`); for (const pane of panes) { const tabname_full = pane.id; diff --git a/javascript/extraNetworksClusterize.js b/javascript/extraNetworksClusterize.js index ec3546c7e..96feeee2e 100644 --- a/javascript/extraNetworksClusterize.js +++ b/javascript/extraNetworksClusterize.js @@ -1,7 +1,24 @@ +// Prevent eslint errors on functions defined in other files. +/*global + Clusterize, + getValueThrowError, + INT_COLLATOR, + STR_COLLATOR, + LRUCache, + isString, + isNullOrUndefined, + isNullOrUndefinedLogError, + isElement, + isElementLogError, + keyExistsLogError, + htmlStringToElement, +*/ +/*eslint no-undef: "error"*/ + class NotImplementedError extends Error { constructor(...params) { super(...params); - + if (Error.captureStackTrace) { Error.captureStackTrace(this, NotImplementedError); } @@ -16,7 +33,7 @@ class ExtraNetworksClusterize extends Clusterize { lru = null; sort_reverse = false; default_sort_fn = this.sortByDivId; - sort_fn = this.default_sort_fn; + sort_fn = this.default_sort_fn; tabname = ""; extra_networks_tabname = ""; @@ -298,7 +315,7 @@ class ExtraNetworksClusterizeTreeList extends ExtraNetworksClusterize { async onRowExpandClick(div_id, elem) { /** Expands or collapses a row to show/hide children. */ - if (!keyExistsLogError(this.data_obj, div_id)){ + if (!keyExistsLogError(this.data_obj, div_id)) { return; } @@ -359,7 +376,7 @@ class ExtraNetworksClusterizeTreeList extends ExtraNetworksClusterize { res.push(parsed_html.outerHTML); this.lru.set(String(div_id), parsed_html); } - + return res; } @@ -428,7 +445,7 @@ class ExtraNetworksClusterizeCardsList extends ExtraNetworksClusterize { // replace the element in DOM with our new element old_card.replaceWith(parsed_html); - + // update the internal cache with the new html this.lru.set(String(div_id), new_html); } @@ -454,23 +471,23 @@ class ExtraNetworksClusterizeCardsList extends ExtraNetworksClusterize { async sortData() { switch (this.sort_mode_str) { - case "name": - this.sort_fn = this.sortByName; - break; - case "path": - this.sort_fn = this.sortByPath; - break; - case "date_created": - this.sort_fn = this.sortByDateCreated; - break; - case "date_modified": - this.sort_fn = this.sortByDateModified; - break; - default: - this.sort_fn = this.default_sort_fn; - break; + case "name": + this.sort_fn = this.sortByName; + break; + case "path": + this.sort_fn = this.sortByPath; + break; + case "date_created": + this.sort_fn = this.sortByDateCreated; + break; + case "date_modified": + this.sort_fn = this.sortByDateModified; + break; + default: + this.sort_fn = this.default_sort_fn; + break; } - await super.sortData() + await super.sortData(); } async filterDataDefaultCallback() { @@ -489,4 +506,4 @@ class ExtraNetworksClusterizeCardsList extends ExtraNetworksClusterize { return n_visible; } -} \ No newline at end of file +} diff --git a/javascript/lru_cache.js b/javascript/lru_cache.js index efe0c58b0..ba234d07c 100644 --- a/javascript/lru_cache.js +++ b/javascript/lru_cache.js @@ -1,7 +1,14 @@ +// Prevent eslint errors on functions defined in other files. +/*global + isNumberThrowError, + isNullOrUndefined, +*/ +/*eslint no-undef: "error"*/ + const LRU_CACHE_MAX_ITEMS_DEFAULT = 250; class LRUCache { /** Least Recently Used cache implementation. - * + * * Source: https://stackoverflow.com/a/46432113 */ constructor(max = LRU_CACHE_MAX_ITEMS_DEFAULT) { @@ -49,4 +56,4 @@ class LRUCache { first() { return this.cache.keys().next().value; } -} \ No newline at end of file +} diff --git a/javascript/utils.js b/javascript/utils.js index 94b9e1343..7a649a81d 100644 --- a/javascript/utils.js +++ b/javascript/utils.js @@ -3,7 +3,9 @@ const INT_COLLATOR = new Intl.Collator([], {numeric: true}); const STR_COLLATOR = new Intl.Collator("en", {numeric: true, sensitivity: "base"}); /** Helper functions for checking types and simplifying logging/error handling. */ -function isNumber(x) { return typeof x === "number" && isFinite(x); } +function isNumber(x) { + return typeof x === "number" && isFinite(x); +} function isNumberLogError(x) { if (isNumber(x)) { return true; @@ -18,7 +20,9 @@ function isNumberThrowError(x) { throw new Error(`expected number, got: ${typeof x}`); } -function isString(x) { return typeof x === "string" || x instanceof String; } +function isString(x) { + return typeof x === "string" || x instanceof String; +} function isStringLogError(x) { if (isString(x)) { return true; @@ -33,10 +37,16 @@ function isStringThrowError(x) { throw new Error(`expected string, got: ${typeof x}`); } -function isNull(x) { return x === null; } -function isUndefined(x) { return typeof x === "undefined" || x === undefined; } +function isNull(x) { + return x === null; +} +function isUndefined(x) { + return typeof x === "undefined" || x === undefined; +} // checks both null and undefined for simplicity sake. -function isNullOrUndefined(x) { return isNull(x) || isUndefined(x); } +function isNullOrUndefined(x) { + return isNull(x) || isUndefined(x); +} function isNullOrUndefinedLogError(x) { if (isNullOrUndefined(x)) { console.error("Variable is null/undefined."); @@ -51,7 +61,9 @@ function isNullOrUndefinedThrowError(x) { throw new Error("Variable is null/undefined."); } -function isElement(x) { return x instanceof Element; } +function isElement(x) { + return x instanceof Element; +} function isElementLogError(x) { if (isElement(x)) { return true; @@ -66,7 +78,9 @@ function isElementThrowError(x) { throw new Error(`expected element type, got: ${typeof x}`); } -function isFunction(x) { return typeof x === "function"; } +function isFunction(x) { + return typeof x === "function"; +} function isFunctionLogError(x) { if (isFunction(x)) { return true; @@ -81,7 +95,9 @@ function isFunctionThrowError(x) { throw new Error(`expected function type, got: ${typeof x}`); } -function isObject(x) { return typeof x === "object" && !Array.isArray(x); } +function isObject(x) { + return typeof x === "object" && !Array.isArray(x); +} function isObjectLogError(x) { if (isObject(x)) { return true; @@ -110,7 +126,7 @@ function keyExistsThrowError(obj, k) { if (keyExists(obj, k)) { return; } - throw new Error(`key does not exist in object: ${k}`) + throw new Error(`key does not exist in object: ${k}`); } function getValue(obj, k) { @@ -318,7 +334,7 @@ function waitForValueInObject(o) { * 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) { @@ -334,12 +350,12 @@ function waitForValueInObject(o) { 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 { diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index b6ed6f29f..41fe91495 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -4,12 +4,10 @@ import urllib.parse from base64 import b64decode from io import BytesIO from pathlib import Path -from typing import Optional, Union, Any, Callable +from typing import Optional, Callable from dataclasses import dataclass -import zlib -import base64 import re -from starlette.responses import Response, FileResponse, JSONResponse, PlainTextResponse +from starlette.responses import Response, FileResponse, JSONResponse from modules import shared, ui_extra_networks_user_metadata, errors, extra_networks, util from modules.images import read_info_from_image, save_image_with_geninfo @@ -121,7 +119,7 @@ class DirectoryTreeNode: DirectoryTreeNode(self.root_dir, child_path, self).build(items) else: self.item = items.get(self.abspath, None) - + def flatten(self, res: dict, dirs_only: bool = False) -> None: """Flattens the keys/values of the tree nodes into a dictionary. @@ -248,7 +246,7 @@ def page_is_ready(extra_networks_tabname: str = "") -> JSONResponse: page = get_page_by_name(extra_networks_tabname) try: - items_list = [x for x in page.list_items()] + items_list = list(page.list_items()) if len(page.items) == len(items_list): return JSONResponse({}, status_code=200) @@ -706,10 +704,10 @@ class ExtraNetworksPage: tree.update(subtree) # Sort the tree nodes by relative paths - dir_nodes = list(sorted( + dir_nodes = sorted( tree.values(), key=lambda x: shared.natural_sort_key(x.relpath), - )) + ) dirs_html = "".join([ self.btn_dirs_view_item_tpl.format(**{ "extra_class": "search-all" if node.relpath == "" else "",