From ecdc4cc23c82429106c5f794295d1c55a7ac8cf9 Mon Sep 17 00:00:00 2001 From: haohaocreates Date: Wed, 22 May 2024 16:53:45 -0400 Subject: [PATCH 01/59] chore(publish): Add Github Action for Publishing to Comfy Registry --- .github/workflows/publish.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..828f300 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,21 @@ +name: Publish to Comfy registry +on: + workflow_dispatch: + push: + branches: + - main + paths: + - "pyproject.toml" + +jobs: + publish-node: + name: Publish Custom Node to registry + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Publish Custom Node + uses: Comfy-Org/publish-node-action@main + with: + ## Add your own personal access token to your Github Repository secrets and reference it here. + personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} \ No newline at end of file From 3d2b07904827767391f6b2ef4b002084b08c5aba Mon Sep 17 00:00:00 2001 From: haohaocreates Date: Wed, 22 May 2024 16:53:49 -0400 Subject: [PATCH 02/59] chore(pyproject): Add pyproject.toml for Custom Node Registry --- pyproject.toml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b0b3b02 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,14 @@ +[project] +name = "comfyui-model-manager" +description = "Manage models: browsing, download and delete." +version = "1.0.0" +license = "LICENSE" + +[project.urls] +Repository = "https://github.com/hayden-fr/ComfyUI-Model-Manager" +# Used by Comfy Registry https://comfyregistry.org + +[tool.comfy] +PublisherId = "" +DisplayName = "ComfyUI-Model-Manager" +Icon = "" From 92f8c632df9465bdbfcae22188f6897173b8f1aa Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Thu, 5 Sep 2024 23:15:26 -0400 Subject: [PATCH 03/59] Fix issue with Civitai `Content-Type` in API header. - https://github.com/hayden-fr/ComfyUI-Model-Manager/issues/18 --- __init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/__init__.py b/__init__.py index 6aadb9b..704aadd 100644 --- a/__init__.py +++ b/__init__.py @@ -228,6 +228,7 @@ def get_def_headers(url=""): if url.startswith("https://civitai.com/"): api_key = server_settings["civitai_api_key"] if (api_key != ""): + def_headers["Content-Type"] = f"application/json" def_headers["Authorization"] = f"Bearer {api_key}" url += "&" if "?" in url else "?" # not the most robust solution url += f"token={api_key}" # TODO: Authorization didn't work in the header From eeb63912f6c44ce4c41517f9d4f7d3a94b062210 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:03:33 -0400 Subject: [PATCH 04/59] Fix model type select sorting. - Remove duplicate logic in url search. --- web/model-manager.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index a9246a3..a6cedd1 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2036,10 +2036,11 @@ class ModelGrid { } let modelTypeOptions = []; - for (const [key, value] of Object.entries(models)) { + for (const key of Object.keys(models)) { const el = $el("option", [key]); modelTypeOptions.push(el); } + modelTypeOptions.sort((a, b) => a.innerText.localeCompare(b.innerText, undefined, {sensitivity: 'base'})); modelSelect.innerHTML = ""; modelTypeOptions.forEach(option => modelSelect.add(option)); modelSelect.value = modelType; @@ -3280,9 +3281,6 @@ class DownloadView { /** @type {HTMLButtonElement} */ clearSearchButton: null, }; - /** @type {DOMParser} */ - #domParser = null; - /** @type {Object.} */ #settings = null; @@ -3295,7 +3293,6 @@ class DownloadView { * @param {() => Promise} updateModels */ constructor(modelData, settings, updateModels) { - this.#domParser = new DOMParser(); this.#updateModels = updateModels; const update = async() => { await this.#update(modelData, settings); }; const reset = () => { @@ -3360,12 +3357,7 @@ class DownloadView { onkeydown: async (e) => { if (e.key === "Enter") { e.stopPropagation(); - if (this.elements.url.value === "") { - reset(); - } - else { - await update(); - } + searchButton.click(); e.target.blur(); } }, From 25d52dda6de035b210e95a9984dd9399eb6a4b9e Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 03:28:53 -0400 Subject: [PATCH 05/59] Added buttons to search the web for notes and open url in new tab. - See here for discussion: https://github.com/hayden-fr/ComfyUI-Model-Manager/issues/18 - Added python requirement. --- __init__.py | 147 ++++++++++++++++++++++++++++++++++++++++++- requirements.txt | 1 + web/model-manager.js | 113 +++++++++++++++++++++++++++++---- 3 files changed, 249 insertions(+), 12 deletions(-) create mode 100644 requirements.txt diff --git a/__init__.py b/__init__.py index 704aadd..b791144 100644 --- a/__init__.py +++ b/__init__.py @@ -8,6 +8,8 @@ import copy import importlib import re import base64 +import hashlib +import markdownify from aiohttp import web import server @@ -187,6 +189,7 @@ def ui_rules(): Rule("model-show-add-button", True, bool), Rule("model-show-copy-button", True, bool), Rule("model-show-load-workflow-button", True, bool), + Rule("model-show-open-model-url-button", False, bool), Rule("model-info-button-on-left", False, bool), Rule("model-add-embedding-extension", False, bool), @@ -240,6 +243,93 @@ def get_def_headers(url=""): return def_headers +def civitai_get_model_info(sha256_hash: str): + url_api_hash = r"https://civitai.com/api/v1/model-versions/by-hash/" + sha256_hash + hash_response = requests.get(url_api_hash) + if hash_response.status_code != 200: + return {} + hash_info = hash_response.json() + if len(hash_info) == 0: + return {} + model_id = hash_info["modelId"] + + url_api_model = r"https://civitai.com/api/v1/models/" + str(model_id) + model_response = requests.get(url_api_model) + if model_response.status_code != 200: + return {} + return model_response.json() + + +def search_web_for_model_url(sha256_hash): + model_info = civitai_get_model_info(sha256_hash) + if len(model_info) > 0: + model_id = model_info["id"] + version_id = None + for model_version in model_info["modelVersions"]: + for files in model_version["files"]: + if files["hashes"]["SHA256"].lower() == sha256_hash.lower(): + version_id = model_version["id"] + break + if version_id is not None: break + return f"https://civitai.com/models/{model_id}?modelVersionId={version_id}" + + # TODO: search other websites + + return "" + + +def search_web_for_model_notes(sha256_hash): + model_info = civitai_get_model_info(sha256_hash) + if len(model_info) > 0: + model_description = model_info.get("description", "") + model_version_description = "" + model_trigger_words = [] + for model_version in model_info["modelVersions"]: + for files in model_version["files"]: + if files["hashes"]["SHA256"].lower() == sha256_hash.lower(): + model_version_description = model_version.get("description", "") + model_trigger_words = model_version.get("trainedWords", "") + break + if model_version_description != "": break + + notes = "" + if len(model_trigger_words) > 0: + notes += "# Trigger Words\n\n" + model_trigger_words = [re.sub(",$", "", s.strip()) for s in model_trigger_words] + join_separator = ', ' + for s in model_trigger_words: + if ',' in s: + join_separator = '\n' + break + if join_separator == '\n' and len(model_trigger_words) > 1: + model_trigger_words = ["* " + s for s in model_trigger_words] + notes += join_separator.join(model_trigger_words) + if model_version_description != "": + if len(notes) > 0: notes += "\n\n" + notes += "# About this version\n\n" + notes += markdownify.markdownify(model_version_description) + if model_description != "": + if len(notes) > 0: notes += "\n\n" + notes += "# " + model_info.get("name", str(model_info["id"])) + "\n\n" + notes += markdownify.markdownify(model_description) + notes = notes.strip() + return notes + + # TODO: search other websites + + return "" + + +def hash_file(path, buffer_size=1024*1024): + sha256 = hashlib.sha256() + with open(path, 'rb') as f: + while True: + data = f.read(buffer_size) + if not data: break + sha256.update(data) + return sha256.hexdigest() + + @server.PromptServer.instance.routes.get("/model-manager/timestamp") async def get_timestamp(request): return web.json_response({ "timestamp": datetime.now().timestamp() }) @@ -1004,6 +1094,23 @@ async def get_model_info(request): return web.json_response(result) +@server.PromptServer.instance.routes.get("/model-manager/model/info/web-url") +async def get_model_web_url(request): + model_path = request.query.get("path", None) + if model_path is None: + web.json_response({ "url": "" }) + model_path = urllib.parse.unquote(model_path) + + abs_path, model_type = search_path_to_system_path(model_path) + if abs_path is None: + web.json_response({ "url": "" }) + + sha256_hash = hash_file(abs_path) + url = search_web_for_model_url(sha256_hash) + + return web.json_response({ "url": url }) + + @server.PromptServer.instance.routes.get("/model-manager/system-separator") async def get_system_separator(request): return web.json_response(os.path.sep) @@ -1218,12 +1325,50 @@ async def set_notes(request): except ValueError as e: print(e, file=sys.stderr, flush=True) result["alert"] = "Failed to save notes!\n\n" + str(e) - web.json_response(result) + return web.json_response(result) result["success"] = True return web.json_response(result) +@server.PromptServer.instance.routes.post("/model-manager/notes/download") +async def try_download_notes(request): + result = { "success": False } + + model_path = request.query.get("path", None) + if model_path is None: + result["alert"] = "Missing model path!" + return web.json_response(result) + model_path = urllib.parse.unquote(model_path) + + abs_path, model_type = search_path_to_system_path(model_path) + if abs_path is None: + result["alert"] = "Invalid model path!" + return web.json_response(result) + + overwrite = request.query.get("overwrite", None) + overwrite = not (overwrite == "False" or overwrite == "false" or overwrite == None) + notes_path = os.path.splitext(abs_path)[0] + ".txt" + if not overwrite and os.path.isfile(notes_path): + result["alert"] = "Notes already exist!" + return web.json_response(result) + + sha256_hash = hash_file(abs_path) + notes = search_web_for_model_notes(sha256_hash) + if not notes.isspace() and notes != "": + try: + with open(notes_path, "w", encoding="utf-8") as f: + f.write(notes) + result["success"] = True + except ValueError as e: + print(e, file=sys.stderr, flush=True) + result["alert"] = "Failed to save notes!\n\n" + str(e) + return web.json_response(result) + + result["notes"] = notes + return web.json_response(result) + + WEB_DIRECTORY = "web" NODE_CLASS_MAPPINGS = {} __all__ = ["NODE_CLASS_MAPPINGS"] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..06a83f1 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +markdownify \ No newline at end of file diff --git a/web/model-manager.js b/web/model-manager.js index a6cedd1..ef310d2 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -139,6 +139,22 @@ async function loadWorkflow(url) { app.handleFile(file); } +/** + * @param {string} modelPath + * @returns {Promise} + */ +async function tryOpenModelUrl(modelPath) { + const webUrlResponse = await comfyRequest(`/model-manager/model/info/web-url?path=${modelPath}`); + try { + const modelUrl = new URL(webUrlResponse["url"]); + window.open(modelUrl, '_blank').focus(); + } + catch (exception) { + return false; + } + return true; +} + const modelNodeType = { "checkpoints": "CheckpointLoaderSimple", "clip": "CLIPLoader", @@ -1885,6 +1901,7 @@ class ModelGrid { const showAddButton = canShowButtons && settingsElements["model-show-add-button"].checked; const showCopyButton = canShowButtons && settingsElements["model-show-copy-button"].checked; const showLoadWorkflowButton = canShowButtons && settingsElements["model-show-load-workflow-button"].checked; + const shouldShowTryOpenModelUrl = canShowButtons && settingsElements["model-show-open-model-url-button"].checked; const strictDragToAdd = settingsElements["model-add-drag-strict-on-field"].checked; const addOffset = parseInt(settingsElements["model-add-offset"].value); const showModelExtension = settingsElements["model-show-label-extensions"].checked; @@ -1957,6 +1974,22 @@ class ModelGrid { }).element, ); } + if (shouldShowTryOpenModelUrl) { + actionButtons.push( + new ComfyButton({ + icon: "open-in-new", + tooltip: "Attempt to open model url page in a new tab.", + classList: "comfyui-button icon-button model-button", + action: async (e) => { + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const success = await tryOpenModelUrl(searchPath); + comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); + button.disabled = false; + }, + }).element + ); + } const infoButtons = [ new ComfyButton({ icon: "information-outline", @@ -2494,17 +2527,30 @@ class ModelInfo { innerHtml.push($el("div", [ previewSelect.elements.previews, + $el("div.row.tab-header", { style: { "flex-direction": "row" } }, [ + new ComfyButton({ + icon: "arrow-bottom-left-bold-box-outline", + tooltip: "Attempt to load preview image workflow", + classList: "comfyui-button icon-button", + action: async () => { + const urlString = previewSelect.elements.defaultPreviews.children[0].src; + await loadWorkflow(urlString); + }, + }).element, + new ComfyButton({ + icon: "open-in-new", + tooltip: "Attempt to open model url page in a new tab.", + classList: "comfyui-button icon-button", + action: async (e) => { + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const success = await tryOpenModelUrl(path); + comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); + button.disabled = false; + }, + }).element, + ]), $el("div.row.tab-header", [ - $el("div", [ - new ComfyButton({ - content: "Load Workflow", - tooltip: "Attempt to load preview image workflow", - action: async () => { - const urlString = previewSelect.elements.defaultPreviews.children[0].src; - await loadWorkflow(urlString); - }, - }).element, - ]), $el("div.row.tab-header-flex-block", [ previewSelect.elements.radioGroup, ]), @@ -2691,6 +2737,46 @@ class ModelInfo { }, }).element; + const downloadNotesButton = new ComfyButton({ + icon: "earth-arrow-down", + tooltip: "Attempt to download model info from the internet.", + classList: "comfyui-button icon-button", + action: async (e) => { + if (this.#savedNotesValue !== "") { + const overwriteNoteConfirmation = window.confirm("Overwrite note?"); + if (!overwriteNoteConfirmation) { + comfyButtonAlert(e.target, false, "mdi-check-bold", "mdi-close-thick"); + return; + } + } + + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const [success, downloadedNotesValue] = await comfyRequest( + `/model-manager/notes/download?path=${path}&overwrite=True`, + { + method: "POST", + body: {}, + } + ).then((data) => { + const success = data["success"]; + const message = data["alert"]; + if (message !== undefined) { + window.alert(message); + } + return [success, data["notes"]]; + }).catch((err) => { + return [false, ""]; + }); + if (success) { + this.#savedNotesValue = downloadedNotesValue; + this.elements.notes.value = downloadedNotesValue; + } + comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); + button.disabled = false; + }, + }).element; + const saveDebounce = debounce(async() => { const saveIconClass = "mdi-" + saveIcon; const savingIconClass = "mdi-" + savingIcon; @@ -2750,6 +2836,7 @@ class ModelInfo { }, [ $el("h1", ["Notes"]), saveNotesButton, + downloadNotesButton, ]), $el("div", { style: { "display": "flex", "height": "100%", "min-height": "60px" }, @@ -3162,7 +3249,7 @@ async function getModelInfos(urlText) { const description = [ tags !== undefined ? "# Trigger Words" : undefined, tags?.join(tags.some((tag) => { return tag.includes(","); }) ? "\n" : ", "), - version["description"] !== undefined ? "# About this version " : undefined, + version["description"] !== undefined ? "# About this version" : undefined, version["description"], civitaiInfo["description"] !== undefined ? "# " + name : undefined, civitaiInfo["description"], @@ -3882,6 +3969,7 @@ class SettingsView { /** @type {HTMLInputElement} */ "model-show-add-button": null, /** @type {HTMLInputElement} */ "model-show-copy-button": null, /** @type {HTMLInputElement} */ "model-show-load-workflow-button": null, + /** @type {HTMLInputElement} */ "model-show-open-model-url-button": null, /** @type {HTMLInputElement} */ "model-info-button-on-left": null, /** @type {HTMLInputElement} */ "model-add-embedding-extension": null, @@ -4111,6 +4199,9 @@ class SettingsView { $checkbox({ $: (el) => (settings["model-show-load-workflow-button"] = el), textContent: "Show \"Load Workflow\" button", + }),$checkbox({ + $: (el) => (settings["model-show-open-model-url-button"] = el), + textContent: "Show \"Open Model Url\" button", }), $checkbox({ $: (el) => (settings["model-info-button-on-left"] = el), From e3f6a7b6f69fd6109e2030efcd801e5b60794756 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 03:34:47 -0400 Subject: [PATCH 06/59] Updated README. --- README.md | 2 ++ ...odel-preview-thumbnail-buttons-example.png | Bin 73525 -> 77929 bytes 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 41626f7..2e3f391 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Designed to support desktop, mobile and multi-screen devices. - Press the "copy" button to copy a model to ComfyUI's clipboard or copy the embedding to the system clipboard. (Copying the embedding to the system clipboard requires a secure http connection.) - Press the "add" button to add the model to the ComfyUI graph or append the embedding to one or more selected nodes. - Press the "load workflow" button to try and load a workflow embedded in a model's preview image. +- Press the "open model url" button to try and search the web and open a model's webpage. ### Download Tab @@ -55,6 +56,7 @@ Designed to support desktop, mobile and multi-screen devices. - Read, edit and save notes. (Saved as a `.txt` file beside the model). - `Ctrl+s` or `⌘+S` to save a note when the textarea is in focus. - Autosave can be enabled in settings. (Note: Once the model info view is closed, the undo history is lost.) + - Automatically search the web for model info and save as notes with a single button. - Change or remove a model's preview image. - View training tags and use the random tag generator to generate prompt ideas. (Inspired by the one in A1111.) diff --git a/demo/tab-model-preview-thumbnail-buttons-example.png b/demo/tab-model-preview-thumbnail-buttons-example.png index 8f96ba6e6adff439521ac091795ae5641a6ed0cf..fc64ea1527a0569855848382c6258b8b735b7e04 100644 GIT binary patch literal 77929 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 literal 73525 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 fkMBJ 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 m{8tYC&m_fv7NbRoZYl9kR^A|g9X|W>O|p_o5*1 Date: Sat, 7 Sep 2024 03:37:23 -0400 Subject: [PATCH 07/59] Minor change to trigger word formatting. --- __init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index b791144..b8e1da4 100644 --- a/__init__.py +++ b/__init__.py @@ -301,7 +301,7 @@ def search_web_for_model_notes(sha256_hash): if ',' in s: join_separator = '\n' break - if join_separator == '\n' and len(model_trigger_words) > 1: + if join_separator == '\n': model_trigger_words = ["* " + s for s in model_trigger_words] notes += join_separator.join(model_trigger_words) if model_version_description != "": From ee9489b75864549bdc0086951927915073270b45 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 16:57:40 -0400 Subject: [PATCH 08/59] Rearranged model preview thumbnail buttons. (Ordered by action impact.) - Fixed bug with boolean to show Add and Copy buttons. --- ...odel-preview-thumbnail-buttons-example.png | Bin 77929 -> 78388 bytes web/model-manager.js | 81 +++++++++--------- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/demo/tab-model-preview-thumbnail-buttons-example.png b/demo/tab-model-preview-thumbnail-buttons-example.png index fc64ea1527a0569855848382c6258b8b735b7e04..0eef0db5916f0b65987e543b0fda26c1b5fb81d9 100644 GIT binary patch literal 78388 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 z

AtIE2)4fE#CYl()I;{OX#~ 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�R7#^rL) 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�{q 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

Bb__(()L_a)uhPO5wTr`3M^Wn1wZB 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 z zzA;zyI!6x`Jtw#e7Z?V}a5NpS=ko64opfSAr6Gl(n?^SAghAT8)u(Lc=g-9(bQTX` zcp>pnc7(sYyqG;NGV(AO8Ag|H=6Pe@9}88?pF0=d{Nh~X2d95W~!yDT~zvP{S` zKphY^d5kox3~GL3h^YP;=EhR!h&&8_%9H0~d4=y&v6Q>&M_asNbaX!TmX{OvrS1kkb5YLsi^v1?e z&qx#L+w35>q(7EwR~Uqgz(Qz;z*4(LT-Unf8jDl#9MR557j1#(h_d9KA(b~}j$rEu zLQmG&H#8NV$`H(Op>7-LK?7G1`eEy2LzEj7d5Sfqfr#273XJs4sbOw8TDC}lp) z)SeU^^!D&3m<1#-un`RyD!6>(eU*`I!#pbtGvdH#%S9P5dgOEtV;o_GASBJoTI50h z#g=pZ{WuJ38JOCJxI%Q%Qzn5$*oZl8!XU*k1&n&;D9xXni}E3l^lTvpvfM@@O_V3b z9^W|%aUcVad+F(7K>?OK=cBLOPdb{|3LREt+g^rc^p7jPex;paRkFje ze>s;1^pzcDF{toIMkvPt9g}Z{2kIZyCFP7z!thTqvlWyQE+PH&PE-RLkvzF;XSwmF z17**iJyBNUDysp-OZ>IhBeuVR)GRI+1&(6-2xw*4BpHFqp&{FCNVa&5Z8$cXzZ`{|krEvTaASg*S zZTxY9x@H~}<;p(s;hQ0NJX5qM<}}fsq9;@3xOKhvmRXiz$EjSla-@~vu>+)C^*~+d zG>MFKkVjrHEG5s6#l?9E zO0|)u&GRfG$PhZDPuaO7=B>^^El=w7^z^9+kGWmdH$BVsIi-Em)=3NgqU@Ts)@h4! zlnefM?V3~`Q=C$El#~8z+_PzK#+biq=$FD6W41ts14awR7H{$Cg{ZwBF$YQpc)tuO z#1}>xJq*hop^&SbaU8?=WVnR!#5{_v?W4aq3J)WZa53(qcS><%XmLz$2t(PJTf%%0 z(nHS|1`~#|WMiHqov~Grau`|s$)m#Q8d2;LN4&|_e=#RX<-icbsolHE&WRmim|-ZU zQMndE01<_eSBFDkJX2QOcV>DzRzln<12ua&5PtnlPl}9Rm0$MeF^4GM(vv@o*gn<8 zHhN<&amv?M=+cP1m_0W1NXbB^4te{Zy#{G`hB#H8F{&>QWtR@2fl$C`MmUjnh8beK za*ks}C}kBZ!G#FP^hCPinDXXav(+(Tg!|*=z>cw4+MaN;Y}Vp>?OD7sN~eOQzNt&{ zNI4*qmzEc!Jwp{zBcsFl@NQOsWW=QM>z*De%E5T_a3Kn+19!)d*l$n!;u!A;aZQ8 z8fB!n?u;>}V$o%c*%FM1Is}K|HoW~0qd1HZEG||F<0phUCn>lP85lGeFELj_MifRW zHVEh1cms@i!|)z@p~Co)p@=YvVP@K5sL^AC5r=39dr0Z(8d5Tr8nM+muW)jn4z4kx zbcyuG&>`}Hk)_kI5P)`A#gGrMvVtB%k1(w1-J$#tdEAG83|M*-c*BmdN3Y4_M;|K> zKk`td6C*whQG}|}jMySgA;0vuDqQ0X#W5q1zN^v@MKX!f4XiNozgU zwK&H%#XO=bdRVocRaq{^oUZKoR3SwB!}xwyP@l9DrIEaaU{*M^Zv-xN8ZQtK1M-8T z&SF6ZrM*g5v80LkVlG-fw8j{-0sk@>W3~o^MVsLm zRyZ1SSYlqwKn`(Bqg&>PjHp<2LIx2AC_PFHg~B*vNFr~j5eLlM!APmY@~$ozt{9JL z9MW4v8Zo@jpFgL#7s|}pnTVfshYc=+FN`FPbt2E}Tw`2ico)c9| zH-ZZRo5QhE(5^{jAqEg-Ln>#=dT@|l0@5!dx#Mb{5ISLFX3|b_`EwkL zZLsCpqW7*p%B8p7yKZ~qNO!s{pUb%{O5>V0;22|d!2pKOaSg+b zYqN7R<<#kuDHddCg+V9d6+HpXK( zrLQ`!F{}hMm|iJ0UqJs)CDr+jtx zdz=K@B`*9nPH{w;)cd1+7&gT!kcjD=kF&Uh=va#O5WPY1e~@ZiZr(z-uF36PXH-+$ zv%mLRKt)4QsS*(t3(^DuDN#Ye1}aFA5;P*BAP_(ZB@sl5G?5aJCS65Aii8ppr9*&# zh=@QUge0JlkOT;Ul>fo|-g$NE-QcK^!J7&N zSN57vH%MS$R{J$~90Ku2(Bif8k}zpWmb0F_pS%4pgiScNUOYx8BcDorV#Pc$BKfSh z=7s?TEPR=|+;!nH5GPBSDry-W3KWhTZfWy&ccz+wMjlQOh9VESGZdE~r5@>sDC5d| z3huFVd%SEf2UgG6G0d4+c;7-W3{+Xo+r;uZqW;`m(ZRJ)A9)~3*IVk4eUzc5UdwBx z;L;Py`fEqjK3{S7l#qr+T^U}vj;^|X=mdXB!di4!n*SK?|O`1LQ z$ry0PWS>Q{Kgkjb#Y>n(8|uWwwQuZ4cX#j68JLl3lI);YxX8Faq+NQuF>VlIplh44 zlb)2D+S8fYHd38nV)wi_W(y43QQu>irwTba>eV!zPQ#w?8)uQ0$e~XQoMRK_hEGkq zBqX0sCajdaEiJPyld8y;OlPUwVv!}D}>25>wpPNejoX_!!mB_v)Szl6BcBkFtbtxa+sEx4z9q_0( ztOz)hDEOut?gws#W!IKhSbT}Td-1VZE48XK`LINYfo2b}@#p2h{V-EIZqXh~$&^r6 zow=+RN7nX#1Zu)NWTEetS`=&0tw#6lJ9OOi?4xJmtuAY_Uy_2DdDj-l2o0QV?jd*V znj}Jd5dndDU+d(S?YfO^8xN$98ROCnG=0*JE%mmjE2(NZZhUN*vM8yFlWfaT0~H&Y zRW2n{ZoXMNsfmXfb@Y(JLn($QLl*tgwKd&>Sud~IA&N6?Rtq20cqHFvsoeR*={g=& zPvhQk^n4kViQX@Nk<@8QJnd!F(AQYfS2YpTDy(+#o~tVAv?cToni=@Shs4pf7zD{i z?;A4#%IP|VwH#@Wk?DT+Oi^;$FtvRp{Kwh9sGa^YPK+x8mp*c1-O3<1#HYq1!BYl^ ziOdtL5F7k(`JC%k@r_&T#L6-6(34Ub&N#VS_XE7t`OyU`s+LCD8@D%Y*M9%;S$RXv z%_s>=`K61#UARHk@NsjkGOe934fN;0$-m++YjJPYCnU~`S4Fah)F{VrF~zk{W`H1| zKaXy^R^V&BUtQwt?nkb95a^u)1|wg;wk)*8wyeP7Sr=0zL51;#2CE=sNu>4hbg0_3_)5!39$K$u!$J}$OEjau^^LyKipI(;k9i~$-??8Xz&ey$Z zBgZ@)?F@G$N_0xr@fsR*P!CQlYd@NGQR$OoO{>H_8iwypBS}(<*;YuNc+H9LE;gsR z+>76SmR9YNk;WTQs2emvQ_3bX>iIZqeerSzXDdwnepK|;d_r%&;qg86S%KRFMa~~) z0VxMJ4J8j;LkwhC4t@UobR(}qGW4WlhTYc-__jSJuCdiQ^xECqUU}{343_98D|)_p zD+W(%y(#s|nA~F}?(kW;9Q9La*8ZKvr4P8{uS)wVqy6Q4{o)f=mEftkMxg5Vt$5h? ze(d*a;*{uDni0^?2@uoQr+f}}0!Poz1fOT0sPe6QeL9b9z>v02@9=)p*`3?e^RmUT za#XIh;%y}kVnpQUtFB=x*&Kwf*yuqZtGZS{>K5Jivl-FY%0UlF6`$#U~LK2zw! z6CaWQM=EhUu(mb^IfDwf6`a*1eB4V`y|pFSj^Y$Y60gHfbl!dK6RaJ4>kz0z`mb}e z&1P|uvT|@N51e+j8QZ&W`*1>o!tJoO^wvLYly2oz9{?|glmz#ZwkT~r;PX++agj8Q z&98mGIRGgMvyY5PvwIAr?Rjv?%=wN&D<}{Zh7nJ0^l@~5tQ~jdR`70aNyI1^0e&u5 z+^f}?HP+&56t$yeSHT64%9T=qPPKeq-R0<+0ZGq~AJ6`9H`QX>9Cu}S9p5OV)_Xvc_}*i<3chBCw#m71E7P5B zX^C&tqW`*v%VnO@yZucsU0yS=?g%VPC0hL#D$l3n{7T!?C+epPeRs?D$3TBR4uC3L zd!WMAY;)G5RePhgt!~_1qwoKCUbFDU$%DBc(5WYO6C-=#>JcZ-JUVO)Y~AjgVBnyL2aM5?z3eb-XaB_$~k-J%>IB^h*{d}&)LKs zC(j0_2XD2-vjn=-?0{6#E7y`l?3JYHl46m;kJJsUbpR_BTd84bPpNckd{}D?XP?(is2X_M5w(-lm`SbLiZG3smg zCDt{RqIzQjLb+bqT(;OCg%|6t(lYSXRB>55>^WcFGprqdbK~sB&59VA%_zBj!}Q^Z zKgvCATIZvQyM#a@)e)1y)CA*fQAblq!Z~@=Kp)D>Kq~u&aD0{Qu4SjSmHZ%OP+{%TXVtuU|B=yu`_Bx zHY;8@{k$g!8C~WRYAy&le5HQ-rrNHH)ni0`%W@tmHo#;yQ}rUWLbu0TwzdykTH!}G`u(w>tNBmBe97RM>~zAZZYc_`Pon}X<>MlDwkMk|$) zHBMgJ*qp>J3M!8?7#eH4I*~q_S>Zvqj1$)D>5!B9 zSA9>9%LhK2zjqW(9r>kG8k_s@{DfYI){K_38qRmAB0!#VCqN_WdZ~5}J0CIf!BTC0 zV_B`9#vO+F$rrVr*~Cj78DkF;nj^OvyxCExugy@Eh?b`LwkTaYG?LcZVT5^z&X}M& z>%Y^RNO6sna%@bCIMLT|A@2=JcGy<26X)C+!+yLiMf&vNq&o!YM7fZXsdKl^nNU5O z;f@ZeqZQNkx{ykm5BgjsY)w^p(U5F28bhEYs+1I2-Fp$R&$)DGOmeB`^DZ!i5TXV}?L^+{#h1(xUGaiM>HIHIn_foRE#2p%aXla-KR~)g4@B@$?L|>}mp%@|AM?T2BxJ}?hk!hLJuxqa=Gh(WR*1-(+JCVck^YOwFPY{t z8_GtHchts(HUiu>)_+@(F-%nssxl<+D<^DIoZ=JW*mVPaMNdcNV7+?L>#!!19!*}c zr{?n)LX8;7)+gvr)2X5n>*Y2eJIiD{tp$3-^g41@t%GAzHIXxk#}>G|IUV)~3GH|dC@v4qOOG{J}@=_g~n<(SHvog}aS_y{<<6}_tt$q&?BWtD(uAPkv$25woQW%jk z#5*d9k1G+Oh@p{Y?0BH>n@b70SvymR5PTUQk6(Tbe``2$bLfmhepqW0fs5ras__}j zpSKKIWq2FpdG3RX&f?dp_GHK9WPLwZ=VRN{lGBKyNuP93IQzMrW=ZO1&ElJR^1!Xv z-;9HI0Qf^ZDu!>u3epc(xJ|WJYBKprLFk|d2HZM!g-@^G_8aVEDC!NrCa4)V-i$x` z!p-e=;hgA&eg>ESO=O4rRnphJecXk#B*Q$)?wy-r%Pk#&aTsBBz_FmqQhaBge=t!pSDm4cG8a;r7UF`|_dOTxxzZv+4R%w8x?g z^QdUf$o2Y;clj&kz2(C9>QxxY$eaP|+Gwy>cxHe2j@2 zNx!8F1c|=;%)vXZcMYUU?XPUAN$3Y_fCZzV3}QZY+_qsY5QC1`PCwW4Wj?4{W{$Vp zeAM=|^xM2f{5YoobshOb4E3J>kthslphwI~$A3#yQukR&Vm6s8VQ2HPO;|=peN7JX z2aIY4Ug@ThKpEr}fvUSkvr7*NgXV_)A`p}(8W-BidMbq+aBsUJY3(t!48r%I>ZVwY zJCcMT67I>X`hJJJqn*n2m~qY|C?mhrYZ^JV0q<(cyIawr{a$pPx`(XL*Xw96CYYB+9@k1(_@*XevLmcL6gEEyMIgok zC&re3Q3Vh_j9P}`jSws#2$YB12Xz zY#%$cu1@0C)rs@AoYflkAlW<0+P&OAy)yJV;?sU3={xxX5LIZiaFve15lq0R_|wYIx>Hy zT#h#~Ruv=;NWU$Xb#`d(-5NrSjEHdXg&pOhBb$BHMJpa8dlILw@<m&t&`d7H1yi4yJW#lAV$lTo(Xg$5SbZ zLBM<;5d-{#a{eapusX-NTW^$BGQN#Qj-WR*oG{DEo!w!Z<8(I~lW3i;KTX=qK#t6B z4LoXbMN$66O_wz1uIu)DK|X)+)l*<5*q$%_j@ zW14Fn)hS;`GMK9c`A5j29^1{^ph8<-t{6<8_hk~UUOQyou;zrS#d0bMWRejfTPR%X zNk;w3b+?Ul)7v;v61Ip3_xl8IpVO?QwDzKy@2CtX%C#ugQ%sl#uM@(yp^}AdLHcTy z7L6t$p^TL=YLja!HDp20N0Tg)fk1^^pN6JO#*{A~2CHitD&Y&;$@W63(IM#h3N?t6 z>1rs#G>Xsy0uTSK0ifQie_hl9|}RaOvMe|%g$p=wjPHOUD{g$h>>Tv7CRydilob$ zI+&6;i8XGOJu?=z=lZs$I2F|*9XtiM{lzc*!rR}-m!icZOfyH@m}GzJ-&-r(-@{4} zQ1y{C55SOo5>VSl+pE9V)OY;k$H7HleheGsrBeSx2ok_~17IbMvTWr&4wQL&Z;dc0H z3K1}5BM>`Nz3{AIOWZ;goT$dsw6J>Rl@X|UD?VN9K>e%K)_h?f+aH2^@*~nF{}6rw zCVIo~2)F2&MZ|p|tvb7^tKs;g@Z_H!kALU@Q_OErq;EjI`UGfnPNE2UyVrjmCKAQM`@RD75V!?Vd;+2$&|EZxn|I&` z0By>_^1yu2K3Ja7Z*Q;x3R&>)PlH$6;{IMAAb(R}{HE|@&>}f)o2=#upb`(Tir6Ls zO^MC|kaY99_frkXM%MT@B`3aUFD%b#oqpa5N5t~TYx4qnZ5SisE&#vu`p2w)qw0Ec zUP128b$GI86=lW8cgk^cfb&AVoGu${Q%7YKzlzoc^ukkCnBOW21ztP0zUx5@oBbq4 zpd_CUZs-Jb7Rm!RxPFeb6+&3~v<* z+`YVXL-E1a*4QrqQZ*4Yk<{Y7TnJtgY`Pp&pV07d-8lRn!OY#Pl>>hd<^SVCD)E{S YHDssj!Yp#9{Q+F(&sv#RoNPV9?OjRkc^Gnl;y4t2$U&Q5yd?`RyxLuHZkHkx;pE z<+{X`E7!bmuz>$Wg@1nm{JLtdA}w~Mu!j;2{BgrXR6+F0mEv&RQ~jI3-?waKH0-Zj zA!q@AuD09cyuEVeBKx_7=qnf9wX@MEqhZI?kRHqZo`&AlJmuh&D>(13P{2!MUVJ8y z9Mz}k{3I!@zN{NSHH#zA%s_L9z4C)7Z07pWjEO*@xSga%jDw?PJhIsIP8R=rs%IIS zF9Px#o}5^l*thexCAn{QJ-PBaTBGCVL?g_8DZ!#(w5Z%UY&xOaJTWeAL`Dn;>JJga z>Gv&LE&zUmf0R+)k@)ip9wX^1^H+ls8OW{6rch0iTXcV3NpxnsUh=PMop7H%L(>xq zMkp#K$zu~x%GcM|=N9Pn(gD3`cefq8X{xKskg_Hz*);AsxuIK0QF%pmNxiqB);EEn zCg{AjH_ud#v-Qp``CYb@g~5+aJYDWhl@mFfdWkN&Sj9eqLkt)rY3~>W@p;Wj9JgOA zq-F&RZ2pu6n!?w2eQXFl7#_Bvy?=UAqkoCTw{) z-Eu(-Meauc(@y+WRsr-;OtIn}0U4L}m4RD*ms8tIfdYoCy?NnxsQ19X%Jl)oInQA4~ zt&hq?n{)4BFj+oLOQkCg|`WU zp8PD#%nS4<*Hhk53wa4r@wsu)5Q)JpGB=wjz-LU976;rzAucglq4#{D9bK-bJL)WT zMVWC`iYhk`B4#N$?I#AGd?q9zX6cu_3axRO^>EuhTJ9buyIs=Ikg~MAjM~|Gr>UW_ zeHI#8zinq_VIjA^zMiXD@TIV@aBz5d`2?S5;5wnu=QeI4b)3llgPDD0!bk{jxEo+f zqh=hJCJ%i2H*RkH3W|zfa&sTk@HSRdRG56cl9vBDzT_qLs#r34nQL-xEkta^T^Xl1 z5wvy)+grL6I99nPOR|77Yj;=ITCVpg%?-zN#lcX1lAPMWP@MiTpgA!4H6Fl$*XW8G z_rIQnGG?6m)!EMa65@^)Df6z5uwjk8qrib`-t#0}bytQ@N&zO(@qPW-_>0Mot}L(! z`?L2>s8(fkaLcY*LH$jIFhXQNx9~||*8vS58sUCqn(kGSs1(ylY#-pQ41i=f_8p`( zU`RGsdd=c8v_c86~1 zJ%jaq6AWVTv+xG&J)uX)bzi`dYQL|^8+Hk94x7GC_&xRa+t)n_Zx^3{=D^+3{UF8^ z8b2*-Kbbf#fm3|ZfAA)4Qxxh%0}kM$i4ytF;Z=9ftkB&a7=B;mm>LfQbiP3kI7?xl z3xzvVSR%}_&^=SZA5!qX0b3L_obbN`nPMd}a&lScNyp)e$zWne6|KZTD-eS+xJ?1X zGM)6P6|;;g@;sv$bvE?4sGaU^_^g=BAMMF2ovrfx;*jQI-l13MU=1EI+l`(+UE)Qx zhLG+?YT;hX--_?`WIgeRoFpfoQcwI|LmteiHSR0|n{DFJD)f#)_-;t!VTb@jAh6Fw zP{YHq!u!SHN8(x2C-u|g3s2klngQeD0?)kv6acxLkaW$0CD_q;p~d1u+W^Q(I5xEl z?OBNTHf*5r#QB2t?5y$P0Odz092Z6{RP)2`qrE?r*$yy)Phc0YrLBXY_Kj!bjmaCe zo5BYdlhbE9$DNI*atE9DxZWzle=W3-aX7E^rDIxQUi~+FL-#XEDfbr^-X8y|Y>4hj z7Kja>A_p5zN&?#lFwlsz$Lh;e*~XLF#>6lx0aa3QIOWpwhOK5?wD)=MMf~{|;YA;n zSD0O49Vz@N@*)1f9kDgNL2+p( zkPx){^oj2AcDVQ2$#CaNuI%+2Mra!U%=se}dbfS_FAOE8v(J$Mey{&Dc zS7eiS+5>flS)%;_k?`K-^^Q89gPqfzVGttq`t8awC!3Aat&sVx=QQbMFY)m4jr3$0 z85v5HaEhl#e{71ntQEIwkFeRm`9$zGJ@-dVc1QD$x=e(lsJ#wnkHx7;URROCvg+(? zHbgNh9c#-=^fx#AiZG8ocA9hF`eEbA1o%Dg2LKhpvte1E)#(0{Aa&PcG-9%mI6{@^ z86M3NG!kNPK`RQJX<~38{CYubLTU$*5E{XQ3H!ap(&-R2UDsB%u$EbG5t$IK=M)`s zEkOYzBEUj}=aN#30Sq|xH&PQ5^9ZTDL?BOR2w6N9DQPhB}e{VHRsOx*CC~`{de^M5M={{gDdkXXx$ZO#gyZ=35`=g!3 zV~+8bmX?P4d!NgGga`tA`1;=yP+xoF=s0vHE-qfVKqZ>>eC(O-aIK3UWNsfg*g!aP zPjH@cMVyDx29{5HUz}}BKbI-Ri>HU}03JpNco=AB#4MGlNpFgyx4XN0&1S=ilfw$7 zStNtmb=S!c&Q!O66aKH^TvNQykIJg5R=ji*j&U2ea5tuJ$>i0+qXj$UaEiS_un*sz z-1Oo-o25BVucbNP3OdRGm>Nk@-Hxo=d?>F+({;CZpetaI#7YaLYN*r6;EQ@%`~f{gUW%^$s=9d z2as5Ti`yvO=N}##iuPI`_F_3}@jfK{ow4Lb%WMaiBY&2VRZuN1 zwkGnI0c>237GqI*r>%NfM@O#Hu$JZXy~gulw3_#x+VsKV*Ccv8{Z2MMT9$zaz|x(I z|1s^!ZU0W1i)|Vk^4r7H)0?|K=j)AUl>nG0dPjL3ID7MYZinbO1f?2+AIHrS)w}}? zsrT2An=S{F&M5C=rHjXB3ydPqfm56&l$t)KzhOR1U;u!V4FZvN+3-t55Y+^ZLb-7y z5-GKh3$>2;`&4N(lgxaHP&AtE*@0awHp&MPQ2lflxQ^9a*?6{&nXvC&q#s{K1{06Q z4wwiZR09XdnzQi7&8BPOv+DdOP1rP;sZ@Ywco=i$)3wW~>AB1XU@E;&D);oAD-)6r zsZUqc8j?K4;1t=0E-r@$rFuAaejc+Sjgg+bZ2~s+(VmY1((!h>hl8I#0f6%Tl#4?f zELC;4)m#LRkkuqB;FZA8KZ1k*YvgGSn}#D}H(*284=-cTC^ILgUwYs8`S{Sjcvmri z%`ap{4x0!C*A%^aJs|?yLWc{$F#^s(65wbf2#;lf>22@R&d$!Gj_%Tih7ED41jZ)- z6zckKvQ5!rV!e-I(LWedL9-uw5od7sNAN)_n$`v1S{J23?ZwI%j;Srd7i+A*Q3{?% zfO|6kyE7hq7x2G-3M4>cS=gsOVaGU4TsAzS?aboxSi&NGQxqUPkXn#&*FMYE>=r(O zR8(%Xf2-c;wxaVNxma;$`=FLSB=as_$@<8lwMl%RZqY@V+d)Hd%>2oV9htEFJ(2$YY zdNYY8caFG@`SK8nl@T0M|5w91(&03{4W9!812xU@gdDSb0+xUn;2&+SgPq-x4x?7^ z6A#^<%goHo&CI0VT-VE?cVy|qDg)TwUf*9t3&cgI$lA^7;qx|kMqs=0+s=G%@Dh`q z1RCS>{BM?-<^6_MXsb`$7533bJcuB>sj116yD6>)px(dOu6-I#<^g8H`e(Map`dlU z4t@Og3AaUexu=wSs&+D^!@tbV>U+a(wlM8~(toD$n9~SBFqrL{F93wh#5lzmaaQsYmM@$mZfDcPa@oWqPSr znAI5z%N~u72XHdZoQcWFp$Lx@j9P|*K5Q*H>hk0qSO78JT~9(?5x@oKmcVe4VnX)v zK+}c+)}9a~=K$j+z&TAd{=fy`h%6z%<6k;#h7s_Q|3|L-pLd%5|28m#2z385d7a~# z2ST#rev}d-Rp`Xh?O+hi#VKTHkYjAJ|AEYx2X?u90sJp`!Mz6`zXf=dHSvylcnV5Nh#x6QCpkF=|7 zn}XWc)qqBp@QjKHtjiUy^#h&$22)}2ZLQgz#ZKWa%SLgkTnitbzEyj$#Rv-s84nqh zQhOTWILlJq11o?qZ22xX5Qc%n1OW z%+8|RXsn0X`dQig<~_0GT=(>9APNFH5N5uFBx4hD`yiKI<-7sygCzh$fX^O&`xD%q z2?nSp2$V%H)$mpZ{~0p?9P?ShbDYnvTm>?J!m-Q20MY~3fldkCD0u3f1E6E*KXnE6 z`JaLD01rERe~p~>tzw0S{XLtv)1ljE0Qopk;dfkp1#Iz#h6V>feHff-DDCA}r#@*8 zz%}#o5~dmDQ%rgq>G{}m$v(9clq-0f|KX#+0$TcwKZkgNK}zb`n#s#@&2DKY65WjB z!Iw(eh*U5BKOq6c0E{~Ac1=5yASdrzf(Q|eDK2v{!BASO9ajaDc46U^223_AJ3T$U3wUI|S%^~7UHpPT*uxjjEdrp0myYK37s&;L!GEp$0ekGf8KdE3a`TJG zX^V(MkRCXRjMo5^X56fH*){;_>Ax_>zocDpW4SL8C7VltX{85>E{=;3ve}=)C&y3}o+LfBqdQSK?phX(^#q>T+P}zau@jKOs$PKMtnf^-^VD-rPEOa& zU!v3t55b8R>w$ZUh7AY_Q#^KlILtN&loc26CN}`genC|C(r_m?FVSv-ReWimR;qzA( z<{N)V3^*Se5)dJ;UH9`Fja5-oQv1oZLLOT4FGo zpEP0o(j0Rw65y=oI{GusY;)Lcj2#@f9331M>d$Z;vkGsHy$97#095fo(39L~Sk^tE z*qqLN^#uLh=lV$v0$%e%dX?OA0iY#dGpfsG$Jkhx+TMZKT`GQuNB9H;8+idFIk=7) z*7)q7>o&@Kz}84>C zUiw60nS#7LS3VmQiN9T51Vru?y%TGeZfE6cs4k4WaEXY152R(`QsotB{|AtP+=Az- z&(?}zIKq9Swy5F3ftN3EuC6{}zYLu(WjAY1b-VTX)ZegND zn%v@e>9qPxCnriZ>hi!^54_ZaoZbO|2gnztAn;uZn3uNr|B0Xclkg8($@1-`zA-io z#3%y2gV9WA;9xUzGG<_5W&JYt^8=MtNK~Z|MXpN0mz0zgF1Dv}Qqt`MTOBgO0O2w~ z9Q_^efLhgraZ-Geya*7hU`kC=6*g1&lL19k9&c!^OP5HzZ^`J(+Mo}}R2jfkvJ(K8 z*Qyy@nSDkP#iIHhSsqN7z}#NlRvG%*aHxe$vK?2n~yMayS<4;{kUcSp@>XK z*>wWARD~a~B6hnuL4Zp$Ap3BaEa2%t%nY0`@n61t@i^}r8yia@691bN2k>*7?()BM zzT8Zcmm9%9-LRkY?x1V(#_#?gmL{h+5xJ>8<5TW=6|Wg;K+ZWPF*UZPu4!D;(u|N9PV2_9N}O7 zmWIK>)Il6!Le>VQ-CHKS$1_~t&j3#HPgmdzvH$z5(?6X)VEm!!9Lxl*_;H!wsAX@s znA|khlSL>d|7=(XRa^qfrx9c0&ifkJorZcIUkTlQ-kLQjV-8j z0_w{I2m6gIh5vr;*shHf528@>UT*JtQiKv27#W?BktAl_Mf zqX5k5UttH`>nHd0(l0$FV+io2j8;*cv!2aU#bdRLRlRILcod`5l4uE_Gm?=lO2x zfl)aEfk5##9(7Z>heKetX9Ka9n!~`@nC5Yhb3;^$>r%Xj(+S(#qQCPWViP!eXFp?0 zm2m7b0gStx)4wBn8GM(#-H4!{K3wpV*V(YQ(Ca7B9t*#|U&Eh1->*d3_X@>^Thep` zq7QsM6KFjl2RkmOXo7LmFW`6lsb{H42At<~8hMwuxcda8+XT4kgKeRG@J z7@JynC-lImQDD4f`{lvQo!UxUL*bQxqLR&2XgHdYn9_P1N%IWkGR@xcHBBY zJ8c^#F;a~&3MerlB72Fe7WBr5MAq-rmks|0*5@+shf_Qr_i%DbU#gn#R3>P@M{#_U z4NCOI!&xaj*+R*}*fQ})viDX2_e9%QD~lyDh@+E(ron>|<8#^7uTI$n#H#QhNBeu7 znUjO!IEi8{GQA~f8)M8Dh34D^`T1F6Ki{o>+fljw)AI3`*K(zqD#0r8Y~P1|707Gg z71-og;}ZF+Ym}Z^&HLu+zH-j0zUPnS+j6c>&hWNG=529!Yd~vRUD?|5*ViPZqH*d1 z>RwP4=9Fj~!|tEu6)~z7d8$FLiGhf>Hm`mB1CK^|*{@&by7RIo?yGALX!0_%QP!@7 z%T-w|!Z7hd2UV4!)oyO>VkZq9o$Ys426AWQj-MX^D-Px~flT#%ytC}Z#WEF6L$^tZ z>pM+h1qL3qocj7wPXh(T(op{L(oV_AR7=gaoB6h^+S1ZmUkehRY7+jYp!d@EVlOBN zgod*SH?rBd7FI!UT23|FT#F}KT+fXU>2GYk+~0E~e)g1@Dl(Z0k=UkP8;zenqeYp} zt0=iChpFS*@$!}yOsnH&a<;dfk-jQ4L%}t3^8=`5OZa4BGN# zub5tw2Ex-)Hm1r-wB>*l>^94?o4fnEcIEO*&e=-iYr!0J=c)xlXoc0))siZq80(;r zZ%5VDW#7KNnayWr(9UBZPwYI?4Qm7(`ZE9NKjPT@%$l=>s-?E&qw`1a%^|jxTXyVs zCm)-6c1v_5IJ?9_n#!xS^q5$Chzc{W_e+F7PYhx8S8cr^Iz%bNM0S{sSoC{lnO|6_ zIm$1nGr+7vwQYzV5f*xWcx!lS3Vm`~3%$XejYr)cZW6uQAVK{wjBuRuqNcnzf&0qh zoJ;Mk&z~5M<~oKGntoc*ncuTBYwjLvH#p>Lc5qNXQP&uq9!VSS%zhOWQsWR0H|K?} z2tD@_>Im8@O2V5+b*; zXGdm6zs2b2 zvS&8KJ0EcCQc`qD`K;jVNzqsJ=Y4}ps^0`#UCg}Ux7|`+r6IGmE8AFw^#v?PMhi*IMGIwtQc{;^^lc$@T6fWrM>r>v( zc6et%ccO{!#?l<2Th1chw6siGkBulTT@|l_(BTl?xYG>hgTa$H90;yAJneBVQ`3gi ze#jWkMIlvKSXf}$<$I6^_V%UFK*+=Nw|IDm21ruxHR7OjefVREn1d8r>U>H}8ib(f zy^H!Tb=1o24j(U^o>YV#S%_K{o5HxUPgpZ$-@w<)#KWU`VDqzY61BdY;4wm-5t7Bc z;#*F7t)Q|>`dsEXam$29OuyD;J;oFI- z9>PS|$uf0czC?N9d#EP|)4NT?#KfFYwv)+LMg-g$HX{zb&8?4KDu9eH{v$;gGf84V zVLH0Lo@rExzl3r~c(LZh?%hSEN5Ia-!=G||f<2JytQa4u6PSAMI(c+trFBJYk^Ojr zvPMBa&4B*)$v_`lv%Qc)itBK|i}EqEIpZF8xQuV>HQx@AN9QG}9_Rf&*Ri#`y1IIP z1z_`We#C?Nq&n1g6~nLN-uu=kT3$+DP{@kNWl|f!nm?AGpiR;itWq~`{y9y1n(efP zBGAyQmJzdbbUru~q?1ri4JNO4> zTq#lau*>-q=gje>Tenq}4XZ{vI&5p^!-&yak>cpRVLb&D>Sc^lVz%0@>(i{awf6;$ z5Qp6wpWp<@&PaM`?bAB@RfihOxxn2O+$F3R9INlcMKp^yYrJiKQ!Uk*H2&-Qqv_6_*d$F*EaqoNaalg|eC*8>rqT^&kqaK04wO zF!b%v#-UU738Cf~kp2e!08zt(t!)%0{N@>sK9-jW3l06U&F&Tzs7 zboFLGMIhS;sOLuojL~;qQ7>IT2H7*7;g|44QGf_uR`-lx@ru0NP&lEG>RVgOx6vZ{ zD2+GzhCVr|it|JZHzvC+t?gc7b%pk>D}Q~x=g2U+UF1CX{yZrvAS8C66*m@@EjP=m zTl4A6)uN66yfYRdf7q3kn|q&k3cdc!qo=3)_#3ZV@cStWYstVN9jmm`ZZBSp;r4qU zpC&FFv%2%+M1~b5X)m=e1NZDxHoLU>?U(XXYfX)SDAXyPLy*gouBcPZNIZg;mfZDT zLO6FSQ+rE4r})d_XUK?b0e*htb8}5?ZN(^)o-9Peg&LZhX*#}ixxfY6;Q-s%w(%vcv*OY4&MBZUOJ@NHq!IelBxj^*hYH#c{dqOZZY zoJ*6e-mrN=Jg=n*HvjNhGt9s@_luOv_pjbG7H z%&#+PQs~P^7%>qyf02SEE>8clULXGvQMECsftFSE5b33DF?Y5hCnJA;k7;*s(9#XP zsD{!z+nfHf>9zToG#*HG$sKqv_zX^>eh&wvFa~lCu)>GqobN7LZ|Q;>>Yqf^mAu#Y z=8_*4JO}0NtUdT*{#kZf`AEsPYi%NQH=3HoZq*4O4BBc51MFkfURXF;;pA+oDb&%v zQDyE9A%$i0@lF{2unbIOIrfNKO4k|Y7!0{P3%h3ekdO$sCDofgpDn0rD|#|tyY2+u zO8JQo2_!x~EtXrl4&VmHiEEeF;ut@rb)4ubNBUVQbkJsKNN%h|8lsWG0@`o;6L%XM zPwFven-{O$b_*)&nc+!ciuP31+PW2rc~?W8B0U&yL?}HhDcLGS+_Q)xH)y*_%rv5L zr0|R-0Vg{aeYC76>%Cj4grK=NWMpO2h?_-HF{1i9;JAXwJM~i9MGA|BD1h_h*wq4+ z7)Vw&Wg3Q@|KSSV9bv7`=Pw1M9FP?~bxdP@s=(xkCIqzCluG=JN7t8L0$4Mo_NH z$*3tN%)S7^ql$J8w@Ew&S&T!CeO1bh(y&Jv&$+ZhS8H#+%dq(c?-&kLTA=3pxM}5? zX-h~fD`I%sg|mLES&r4Wt)0+q^RBD%usRy1x*^WyHlEOk36x4MP#2!=AOvX1h|wH{ zCeC(xvq#XiJbj%re~%0CKS>nLaJDJ-F`^q}1DKRPDg9T{;kVoP>zU&AHa_&dvDl{Q zX)bx#(AtE9z+MO-)s;tama_VjO}!3$TtjAYjivu-$x+fhB(K-q#%QJi7*iWmSYF+w zn(cJ{W-gR$Ol)oO^|<=^cxyD{>jB9mWT#p^Yu0SWgJw2l=);m9^Ih@w=p#~H8Cb*N zyM#o&G6#i^Y^S06cE8J#Z_)2chb!UGlL|AyJ)qcf;rm&XpMzWP&*@08bM@Z*yhywl z4t2ti=`?UeO>tb6vKbuM`Ea0uk6-#mVla|NbjfZ#W1=GU=8H1Q;e=zUWI)_sW4+XN zfxPqi)Sd5#6n|%(U)qCN=LmeGwWT~fV+pbM>hOX{KN~0gwOR;U`gdVD#Z)2pp5{sf zkSIB+4SlK<{t*`GPAp$tcs&$65H|E+YS#J!OhmuaW`QpN5B*?4+mFdnJ&l4NvM2@$W>ZHvK<`jEF zs$V4`@T(eiXvawO?>0w~&zY>e$ut4f3gpJ6u4{)m++GWbjRM3ay4A5$v0qCSrq8>c zvVNL1pL_JB4425hm^(A^VZ~^h#&nUuNpMQ`3Q*YFJfPyXj4{)LTEDgI!iej>P}?K5YqEpchs{AKa!zwU$Y}U zz~E^R30g9vsn$c3cSzEm;pTEcWfjs2tYof5MrKN*W|R%5x`1LQk=*G`W$9JTGP8pK0{H z&?pMedl2hc-E*4$3yiOb0rK@%*+ZZtlA{y5D{ZV-ND@p?55J+W^!aY;w2HN3Ohlxs zn4ljTYehn0_h6r*M={=~SCDR#T_Xf)h8rSxKA_?ca!#GJcT@CSFZKT* zi;O4iQ^hS778Yhhqy*n8DqW(YqR_xHD$dVidyvH)7;Do{CrL64NXQHZd`!h;Zlu|9 zr6oBQENXBC;ixqZ=|EbSzqd+ItNfZC-lX#*{c?V~+>3BlOqQ*ak1jQu^)=^K?b$sN zA`uC!b3_zA+0&9M>him162xw%m3D}sqjCy@Zs0!r7#^N2z^M2o+zXSA*$x+pq4r)g1hm0T z#njUU#sS!AGcg*d7*;gQG;FvlXw`HQqpGH1*)+iEGx(!6prfUS{YJPmzFi7kkjuDC zNC+-NS)1U6Be7auURS^ej(#j{_PKWjW^}9HA)-nWaI2la%fP^b6ki)NC{khT|0)+& zb|3Gp?Nvioq`W)7!$Mq$ugDQfgwxM`bom;0mqiO*&5fOuSdXrm)*P!`)Sb-X2X4YE zdv9Du1_nIHS2mwt%xqo+!XB}iWZ@F z^}DS3_6EI@&j;ngGGq7O=tya5c|u`Zo3Ex0xbRog*9XUX7`h)wa%|Mq=M} zBbGazAMBHV@M`M7*LQ}BJoqjPa=|=P;`?VVe^o&(GreBty-X6_5g%?|ls=pq79&WX z?YUmKY(*kD+JACKhz#?KeVAdX{+k$u)YJOMMRmurUtcjz$+?OzocgXE%*7gRw#T?E zK^U0rb=+L*q&t6(yk3{Re*H}N?Z(<@so4`4R+BP!%&hU_^}-EnQj+p=b!rMI`iG|L z@rfI%I8%B+dZQ6G>3NVW>>oB&EJq3h>#p32)~ZXR7*?maBc0mR5-6zdD;`XEsvUPo zZzxHJQ!3UAP5wf5F=>{+qce8tRbj^0b+aaV4_BwGH~t)+@`C2rWRX^oF6VRT)Psz7 z+Th_17Bg63F%^2A0`(w-BFCouPIFZUId94Wqbt=${wYUV%TxGpBA+J~wp(5%N%=D! z{k18+F|@!8PH-Y?!|R=R)NK;zj2CThIMLen6*ohXSOybVxBE*#_*DTSBs&-VqQs$i zb$!^K3omPEDI>xLZy9%o1b6zTZ|C*tK#~3NHOjCZ*ZXJ%j%6d*{kY-fiK;ggt?g>b2Fr@ztGc%V zO7j`23IC8Xbzb&rs=HL*TmIuW(<_@(`XiKdMsHmnosAWpf57!cqnV6ndfkhD%zS?a z>{(~OR97~3BvZ_WaX@+PMm3{CZ`Tskewl^PO-3xMHG*#k(^vrv7%se{?6&1|qEg;0 zYZv9(p$#u})N^?Mo#8WcQCN>Tfce~4J?TQjY2>{Ry21yTiW-(&rKs1b5tIJ6YC?}o zj0y>_S(aB=juvL=okjP$D)rVp^g70vrOubi7R3jouV+*;?-Xdb?_)4-?gOQ$@$uL& z8j+NSi@^g_X|Hgi`R{eJg6^N@1hZttb;x3APZpX1_rpxW>~NuDIN=MA-vz^->Qv&y ze7(&C4X2fhjjQ#VpBV;-4FoQeW`q}hAl0Vp54j`ssFfQv!r5|vc2-zI7PBg06Oycz z8QT#S?`;(Cyuv0O_}k?vKA zJKrBZ)jywS+nRT|E*tZEj+Nw<>0q}(jm78t-ppKYUL=0{&89C&jT^#*p37!Zr4G!| zNWoMbUc-xdnIoRcDY2%V_<*mY#!cU_2QSbM+N zUdK|)RrrqO#*wnd&);CmX^m&Un;FP`70t91tX1MQJ!#)Mv8|GQ=$J6nSa#R9E!1gk zvrh8vkv54y$+xPwo)m%KOkeR6Agddz!1k~I!neYndo*|bFq08$))se5Li|w#_O6dD zUQp(;$yjV>iX3+;;k~^tx~*6D>@=cosyHht0o&z7XM#nO%7i)e_2&Hyd~!!S9}_PL zqIx-DZCGz-y}2FK58{EAHT7itMoBivlc;e$c##-zljzgZsMu~-@I3?t z5q~hryv82E&F;~C3ct%)CQfOUMNNEFoB>CDDE#JivAY52&=+C!H*egvTM>2rT~LYA zvS~C5yb#^g5VJ*|xO6ZgZ{PY>GS1NHjlHc)(doypOf#j`N+K$8pGbgJ2FIchqv>-K zx7b+Ae-NO^1K)xL=3pAyOV|PX->y`!2#GhWRkYG)^vad6*d3-z2UF8Y42_Ibl}mHa zxn4^t5O^NZ1S?z!ON!4ojcn_^Y5Kv{ zdH1((fduefSiKH!OUe-k{Ay*Ry-V{P8C~0_Up5Jk3`Bhz&b?@yq_L%H*EvnFp%PEs z^muZ8s4@nj<|Gn?{WXLlhMfkuICmVdXXOa*f6KX1&kv`JsTFqFdZVeWE^lwYD?G?b zk~&i_UKYFfDH=yed5ZpRa}Fh8x}+}Da^=1OdNVy;Uyk1YRVKb{wIAIF9P!>kTv**q za|v_irYrRON9`Mc=_{{-<#feC&p5d7j#sFfg<)-iEu}8KzzNx|5=5n^m8Vg~eNnQk z9lR;kxK8h2tngI3#(_^KK0y{+UjEw{IZP(>h?N0uUaZaADYsb#P34v(lFYV_mL1y3 ziZ%YV%^%2qZ)ea}|4$qwAxa36JcAz2r zO&#$qJEyIgtE8$^zjVb~LMZLlm8QaHKQeVPp`+Dwx68gx)k@6L!wBV`@YMlD6yPO7 z;4PAmEWcEJyQ0SJFNh`q7xmmw2M_k^oJ(l^>WB95d{bQ-H$`SE zQo_>_cGVighl2j`xX>q7eOin4hWp|pbZ;|QsaQXdZM03K$6?2fO-&Abao=@3e?3^_(X|_sb?pycB&? zx(^{kIdymVKVVPfSgaO}WVD|HW& zmv2TUs&|3n)NIbsj~{EG;g9rhS;mAL`}jgw1*BI(R1i71v}7F=FJ9Yg<2b=+?zwX`#&{6k3&UNS9_JkL$pPf=YGrx3P~hUP*LrjDXd>m`@hlJ zO?Q%$lS{!GqVt5sE=Rf7I92cgXWqn(KdzpphID`U;i^qT$)hU*a55UeM-KdeOWg!i zWCztEBd2wg(bc@v*oG4y-H+8F_)H`==Ee;5=WP^bKn`~gv+pKMm5fPKAJBL(!68V< z6wl}8pW}CsufBvsU-2R=^p#ORHZdhDTipEHS$N9?Ba)(J$dq_9w3uyhXkL?Nkbc!j ztS>Cq>3v79e*}z&C?inc9sc;n?Dy}_;G6=A&)j~=Qdd>+Bz-s=GiT|Bb!nZbd6e@F zFpr>_!*;HMXc>5kmQc2(PGzQ#*37mvBrykk?Y=n747LY4&R^(*2(!uBU;A2_bUea@NCNZI z1xDof&>r_$wOEHla_2Qj{*r2W6?cdnOr40~^R!wHXPwE9eGOBe>KClmNfk9$#BZqR zkxD)t8{d(HyhxD|ID+smy^Z#$+uBFKvlg?BHeVaQxT)H>JH_`?%vv=?eF5NgNNa!? z1GmeFcpLEXwk==Rs*kbJ(-?X=cH^CD@;?=hA)qEJeS?Eoc`fSnW&xEr*H+6HGh*ET zK7=9AMT4oHxuu1^;YMYuv$LmooAvEg!{;ag6p9#TBpFfF_f2n=yrG*iYdS2G;u7ibzRUnV2mgkyc6sMP7HsEz|LszRcDPgC>e zjxQ-{aB0eVS-ft0yO#Te%TwJhrC5Q?py+T&0tB14p;z&31vnq>|BPePAOpK zaIrIXV6E$8(W_RrG`6$-YZSuy0H0^X$0PUx6v1){a(wCyE_kzHXppG8oo+Fe+t(j2 zUy&saq*cw;l#ZiB&VWR6*(X&Eh<;|byA@l`Z)gA3TYg^jKv<-ME^Wkwpnta7qeo`_ z(1U0cT44IjT2s5?@XNh1{wKMUc$l%(1j!IxT&d61xediJQh`_~KbmUT*&IwT((5>i zW~{#Q^AiRh9%hIf@r3JvkeQn?tI(NqZx*LXZ+yQ}5uP|IpEagpzD*cSWGEzbyd{oq z!ro9Cl9lH7-uO6)+I3=GI#;%JD|;krbMZdEacs66>{aM%LsNCUb!079ueW^C{J1PjjsB{ae6woQB{4NF|X810yOt#f$%JZPcVYM_}D% z)r6pRiX&kRAXUly%A~6jlgJ*wtjEsSbhlc($}2t@e<`erL!&no>09XcY{`!CF3jJHx&ChUt8D!g(0`A5GvCs`}#^y2@f#E2=F=qn^RZAFbW7q5JSo4RUkY9?f`j}INK$~ z@3E2=oM%UBxXUo0zSXp`1G#mWKapS8cH4fQp_x^;?o&^4V?<#b8~xcMlc#ga484(d zfic1&z-?t2!+FEpfl=$lZ0%5^!fC>>f)rzGLS!ngB$Jx6lJhDJrDAMhSJo~m>(N<# zMa@RNMod9$s5&zI*#D7{Pf+o8zr#Ww)Z%xc1A0J`G$RS2a7b|^nIdKx#Mro3aQQU> z+o>`*#TK-Ix*q2@cey{(`S&g?WZ^=W2%%4=Hq9{WSVq}@IrLy!_iy>hR(#*> zEStZy_c}VZ5BzG7sJsQ|#+B=h4EdlK*j)gq=Dmm?oKY!?dNz6swJlutre}3$sU&m> ziH*^x1 zi&IL=*ww*vpC-2)hX2K~;5rL?!@A{-`gfprS+%QX+Ge~0YF@MlJ~HpL>KnVunGmVp zT2Ip&;gl&ruxKTmGO1}bgl|W3hXG@G|+bINt2YxVEs@srD3hIOz+WSCafrJeBd_ zLtNhR@Vz&z9#HW8hEpKNe^qp|et*TfQNMM7w|L@zu-ixPyJB}eDSEDJMhds8+UnfA z{F7=->_By?2~g;!R%1W+mYi};$(|F%`hj0yOvnR~jT#`OP5Kn#ZX{x-+A!e&O>iWMi^Nmv-X1 z^S2MlW@P@#?(T?QXM-?;=IZ)_mflij-{J1npM4GQ>v-~$)^k<#)8XZ16))tHqYHN9 zrYK;D>}vDd5d+m}?Co{DG@7PfHuKtgVg02`OnZ(_hXSdp!_0+}#^=O`bHpTZ*~rH> z=<+8mdKzPix=-g+u7fNNypCD>uZr1CUzZ5ubVnQ%Nn%8*+P5FE!f8X&*G85l^Scc7 zS0>^)ql9BkJuC-XiVB&vAWL_Q?4rF@6+Y5>{2Crd{WO<-iP|-*ju~hYZ(qe_zYCr3 zG_1WMlk0c$-kLViy~HQwxxR^1q8j-=-p?@*=m)_Xn(&8Be$1yy19wijO@cHed=5^k z+P3Y7!((|p&SQBV2i1An)bJ>$3Hu&urZ1xLWsp`(`a9}h z{y5EnRSSz@N%e`Vew$W13{;fo<&MPas%*$OsvQgw6#hv8?K-=zB#gZ6iuclDbHvBn zicjGu^8c{)7H&~~;k&PafP#c5Ge{07Au)7^G)jxojdXW|l7qB#O9@DK4IwR^(u3sC zL&Gq{dHMeK-e+IuI)B2?jIKU+c^`@Ku;aamvaaobQz_NO`;u72ru;3Y;2t=r$tZIbZZHFBjJE z67@J&*$ONAD5#cSZTwqup~B@-s6Z)Stw8zCGySpjqa?m2m204wP!}FL2#Zl_Cgkm# zC`J6n>O!gzPIh-#jRZTp`J0VRqIQ$@Jo(J{xZ~pD;>&!vuLd?efTIBhHCc zNjIK2e)p8kqmo3wbd-Gip=_oAzea4!Lv!BClQ`?7)w6wvwE#FXI{$e&?!^`3m2$gV zF#qS_s+2Tzm@iM;GwYiO?Bqly|2rX~6!GE?X-RS14`~W!YLTMo9pP9}R#YrVGVtq0 zK7J9~{kUVrm=WAzwRr5J<4^K*d6b5_+T-o>6=&!uvs#hMwQ8EP~Nb@W^x7QL9&J(o#?WqeiDX5oCx%vFxv z>0@dt0C+^uXI+P@ttW2zaa2Us{%ura@=}`rh+3ovLzmZ^;3clLb*W9i^Z>_`SG4L0 z0R&gUqcXyMac1fL1P7aY>zXJZ3`=2Vbf;s1GqFa7$T7OB-zL4jEy$TA>M?;-DD|A- z)-DflerP|GMgQc^s8S|1rBdwMzfWl1Wf+R9HIP}m!K2!OUOMU7@c z+G78E1pgytoI#T3M1z>gkF7lct?tELrI(QcEC%T;9SmtcwJ?MrvOj@nVb3=9XoA>x z^*(9^*ev-Rv!eC@1EHdb*{*E4Y#!bxlJ{&lh>02Gg&DF%gQ*M4b0o#kM3X82CK!)k z#lkfnc(XR%y#)CzdL(N&D)bzWUDuy*OkJ+HL4uea)<+AY7~vnD&-%GKONNmAybg%z z4jf#?KhxST_NNBkDR`s-QwhLRGEU^B4HjS#T^NY))Tj8i7iH8|17GW0yTn{75Vv-E6J=5O6z((^WG3BAj796wx`A(Nv)6{aFJ9HCixYp~yLHZe{pTQYXDjv7B1aAmn zPU{=-w`sO9rGswlRVWk2Ps9g#UlYc5D*OH+tt5VI54daAGbCY<4Sr88XD!`@(ZaeB zN7zcxlEJ~Yh%+p%H4+RN;TXjf{`Rv z^s^*zWkmf{_v+mrZu{RKZeWbvMus+3eH7AG`G7n`h|5XcYGAACaZVsk&&0({;W;Tp z)QWk4Evn*_n1aQQ$l1f;uq>pU}74IbXiuX4r>qph;S#XF`GCE|kdhHOIk8L8jV{?v8xxP*0b=CO7qU_=^; z>|vxEN*q`*g3Ank%F5AMZ4S#hBeps9q1P)p7h}|2PD@|1t{8l zW@O0jmJ)Zyf80vwA7}qTS^GylB4^EMJM`~~XkL&|!ow{*EZCpopA-Nu)um&Er&pMV zBQtGa!^w|PlCJl5u)x{b#>wfWECMQFi4=1Db1i4lK3MTLdfNE94X56t@<;|Nz0-65N_f~7KLRLV?O}>lGvrX z6LHa9US5uObxAetlr@WvW(a$ZM~WB@+|+jP2mzd)N)V$6t%sy0O?2|SBnk(Q(Z*&p zttycqBKoIL6t%o{?F-O5yTUZN%9t@aO=`OEDsurx66}V&$|>7e z4EKu{LZkAOzeu}D^mAl`H6kvUCO4_DzF^w>lN^-P4u(jl{qpitgm1sgdVc~i!!a|4 zJ)$Dgt?YYn2vZh(K_ZgRhzso^SZDL>GN%jq%^~dI=Yo)0Fqwb? z%=2{=zz}YQEw`wZ(12)hm&GfIByH&pFL6Rx@R^5M^O)5p5c4nCpI1zDOA&KGVhTUt zKc(12$ph4^q_A8q{{mvuAE0nJ{3$CzM<#+Ml|*&~BvH{g9pXj_1|MWQL0hh@v^BLW zy`1W5+--K2j}!HIF-xfc%Lzi_vM73M0jN<1W~LSsfU>_-w3w}5;>+Vo-^{DO^#B{} zKmQiYw|%)Y^v++ltehXrcwuFI7XBx4d9Q_c_C_X%C9MM3`#HusZ5}{KdKmP$ZP?=n zgA`M!rJhG8M#uhLm)98IDQ{Dy{ubilko~C-&CQ6Dsw~wHt0Cg!5DSG9bK>&}IsE%V z$U(>0je~{L@_zlTO-_z{xct_5zC5Yu?l8-(fF9!@rLNdwv|Cqn-rwFI~M-)=i z{eCD&nLx791DBmksJYP(^|0kF?)7SKly?)1RZ1s5f8)_lf>`~s_`Ay&c+r3#0u0)H zj`%9zsM%`s77+59!iW?E5+Rr`bxh{^3Sl^7H*`BqJ*`e({yVpbCB>I)*2U zX5@Mh=2Hfh2ELK{XFzFvcAvvYG{T^3DC-uTRd9Qib$g6y61xZ#lQSPqKjgQWg(7cu z{IAPr4MWce;QeR-$rPbR=!`xnr1 z2F+kOGv929T^DR^j^(ySLws74d%E|64TLb_?1nKWu;ywpQyzhjhN}arh#~be!(M^2l!`ibOPh z2+8f4%mQO6!-IyCpBLsErLC{8yIf8d0bXoR2~0&Zm^PF#o3D7$`@>hGVAva}7^sio zy9zHV$IVYoKIjjryd2UxdeCcMSi@I^2RHpZlRaHGW6+v;|vjG9}?)T8XuemoT30G%+kka;ZbxrfqWnWKcpy@ z3UwuZVmLoB5uk{YWS%YORPKednSGn}XXQ^C(UE}I9UQGpZkkH4#9*Tl0*(de&(T(n zZt3uFcD(E)Z`f{nug?5ICS}M;r7*wqZXwC~>&yaqXHDIaX}?VY$%W<1J!gkO(T7Rp zy6-?xeQwoiaEswIlRl9>V2Ywjs>>I(hS7SB9DQ@oci$F_dk&QGcy~KD{^@6u0QK?1 z9c63*DvEDm&Vre-TVutnGgurMbmp*SA0$6_>dd14Zi1@|Bj6hK6%h#ODE*l*mGF_v z{pzC9W%J*C6o)0(@|QpQl@~9fmjGR-p5@ej=nE-)$@alEn*dn6hd-f2;IbRb))0Q) z3a@1LD!$HlZG(E>0ejmitndWl>^h_MDlz);sGr%tTR)bnfSiokVx)5<*39i5Le_?Z z((oGI3%aH@I)OgeFBuBDTqK9Z-zN#ORaY+72%Q?~DAD>X)0tm4JUK0v+|=Z)Hl=&} zPcBv18EBw|O>Cu=pW`JSK;t-d{BBa-Ryg))k8L++YQBN9x}JXo8bA?6y~fXu*7}5X zEUt)IaU;oigj{*tT~~Go++7jr9=-Dkr$9g?W8J0n_`8?Nq>|)p_r4uw)w{i_!GZ)T z>eN@ye<&ckvQ_ZqxZfTYRYySb(($E9dbSA+FC-H34Ir_k$%KTCF9+gG9Q-r8{?Pt4UVMYDpN=%cC<9%{Yj$SW+B(qnn(5ZbqrHiHZK z98mnhRin7nV+3CyGAj9p0DmI3;`7S=-#tB6+xvT*vEz0UWrr)=T3|WU*LN$O|B|XJ z^)J~?mv+tt{@rL%rk}SV@2L6D;_r3`A<<4hCz0GHyR2X|HmbJXha6q|EYwON@Rp|7 zBL@8yx}H;h`Yg9qDPD76!rMxY=Hi+FUYYQs`T_>ZdQ5hKRZgHk2|f4RU*5sO-aI}M zYVpsHA>UZg>5Ns83b^8zLj?Va?Yjw7Ic_AMGt{w3J%8Zfj{UVWF6#_U;|Mjk+WsKu zw_Aai8+oez^5yQir*gPFUQuZ-tLy2R2lR!AdcuC@Btq*QWda*W8ab?|Fmk;cd@@Mr z|6M6dH15q*rpt&gVP3TV3TRxCP~(VHxQ1#bgA9EBT-g`MCzX4Y6G6jF5%I{?tjCkD(RCOi z@&3LQJovxFbyP}Vx6=}Q$>W)iMoy4vs6ao8H^x zn>%{$me^J3ZOnfTc9~rYl+km(CIg@8dgr-z1GQ0ncJ?@WBTpJ(-L&HfzLc%8Y zZ1=!VGwf^G0=@F zAu#c}0nAzJv~Q&Py#OPFZS_9%L;f!OUIGH5F0#3|-tsn=v|t+fmX+=3`&2wYcu@oP zD%v#_Zv3w5;IqHB^K457Rjba&cO=L;ctVv`EHCCM~9NABRm{huVg(FM`IyQ)yk z$w|C_RL)+Bz6VTeu3dOC#fcYN^a*g_S?>-!huuf~!=N;yw*UiLBQ-hs;9^Dn%h-a0 zmj0TN)3n1-l9di`ZP>Hw8}uQl&dufGiejVt;3ligPJg)B?i^d*$lC&y@T*zwRsYsX z;qE*&6eL?^T_%5qiGG}2bwufB&~PvIGuh=hg8ogiyvrX7+O3JKo0{<4?(Rn2&ZU+aP$jBwsR}?7Za}jQXo!XqgrOS!d0jxm4Q`x{SmDY=C z`DOt4^gkatF)X{j0;-Ik*e zo!=-$HwSfLCrJ0->(UbZ`i&geYJBhk{}lxt{(wv97m1IDRFHmoO-@Z^SpsS$5)y`q z%}p3ojzdfg)DaZ`#)W{qPd?9b%q3lpI)Ah$xN8%?0dFbm1LI9TfPy>$*j{~Zy}Dv9 zD%b~R@KNIfAI`$NDg2*CT(p@m;4A((j!((n=(!2yD}J0i%V7;w||e{#xs2ug>Zr5rYYG z)2}2jL~O?ZqO@^2ihWt+Ei*kgp!TOCkq%YNOa3y$p1tPDt^1kSbIQBUVMq(PijKg% zWU@&<&^m=!4614Kh)aUcRNpYG6SzorpUn=B4CU7&e7GnDJ=jGqH#@iJs2jyj&(HD@ znRY1GL#O5nE~8GO_V)#^rxO7Q4DiU0>6NMt7TN41&WWNoiPr}EPA$qFRyZ%sYI9$8pWcuDnA0T3lSTwe52E9;SFfil$v75j*QA~AJTn*#zYrem9$o7Mac zvh3ecjCEPLz&N}BnOe>?E<}nB8KBh?7kCRfwiC+)yAetfO z9+j%OK=gsYQd_jfk~p2i$8M2NC$o4aSr66CZBX*zn6Oq; zS6RIl#IL4}Ae-1A!rft0V*izr)ges2F~GjYA|>zbo3d-IXFj}s?3OA#u-C4ev^l1E z?!MJ<0H#t{#gS2qJm2<68H_1!o?-AYAs2bqjrJi6bkTbC)kIWx(2p1whAZ_zgs1gK zz;(&IBNnK09kwSq?6f$mq-^kxYeEe{&gFO%bu!aSrAX+rcH?5`Q-k2`ayIwJmCf8$ z)9Rv>MD>MMAj&2euW-p$VhEz(WL556SisXD8bjr^`P*gf0Aeut)l;&D_^_$DX?y+E zkVCAPfb2dBN(KnYd@lau{Ve-3`d{_>rvo)phQ80CbXfL$?9YK^dM?r$N*x1JSR&au z{e$EP>YxLFZ}pvs5a0Cp(~wX4%P@!ndq3-L?E(5-S`i*?5Nus}PF|kH-M2@>?XK1R zHI8SpWioEC*JmwapNnr(^dz8fz|#1BC9$*j%C!tGg+7+NJwX)J3sUKW%;zMeY%rF{ z?*ttoOnE-s*WaRwZ#?GMijWU2fZ7oE>DEPY(~UA4V09^k^>g-d#|0Ac{6tQX74 z?oz3BJ5Sq5#btz{Spo>xu7Jl3!2FH6@%HBAqE|GL9snbSl4Odx^RiaJ0`lec$TmPZ z374KZi8kCN;g!7G0o8Ho(QofoX=Har?>(t8e>C(~+IZ8gd)Jt6bf{5|J zrfZay>t-waZSuc2FG!x6ZB|R?{S#Dt&OU-O{kJZY6ok~X!O}gp)^o4#UzC%D(I~M0 zB{mxDcC2qQHfG6>js5L%wDy<;cWs0gr~B||0$zLcJhW8#CO*!khy;&v5ITr~|9DEG zu(mZ|Wsr}TI-q?;+9^e48?gB{h&^ckC_j8_a4qkgv~qiaj?ka`y1(3q?I|I_TDG$k z&sRC+=x$kjRRE%9M>wJ)beUH;-TpSqp4gX%nK|d1es;9jP34Jo+odN+^5L~_CUV}s zRST7!vp-p02Y;5+|HkE0LRkP2HN~AOyR-l>7)ksEvN`_$KwW9bxU8$smsdzJ6!r!n zC%xR@YfAyd9?2ti(T9hQ26o;S7JXS&{s5)=-H7n9f@rg^N3ZHKR~AP1tdGboy(w-^-u<{+1OL?_kFi2u6FO&2;xeFv@Orh|se;D0?; z(^N%~!XH_V*?g6=)U%>_a}sedOqm#Iwy8bnZ7F~K@S&xR%V7ES+L{*0JA55$-nD8Y z)H}W?%oUh~6waQ&840+x#>R|_$+yzo99L0Wl`g(8Exkf}#pd>yc19@bDJ_5aTNSo` z#Pl=@kNPCdu;^pc#L9;uspW6se~OBV{u{rFaAjg)smpvUK+wrgQ!H@C!?3$SyJ1D89{;i_q zcpd#q?ZuOs7I_pBtQxhMVm!ZgzWV80R#~-xP#|}@7@t8$GhLpmnk$h|gtxNqZM-q_ zG=J)VlxM^AqJ8gXhEZjpCZo|Gv4@p4wbyagb%q>RUV%L_vJ=aaID5xV+!^pyk5qoo zaU?aR*j+GfnSeN9+UoMO~!Y#ag#`8)pJ_Rq+2R#uiGkZ5$;O&VZ*qQXsiWLf~A z52Qv^;2x6$CQ(Mt)y`Z9=dKv8af1=l_BNT!;`rAXXENb*%3Os>z>&zNIHHi>*r+80 z3a6UX8^azNW-K=-XhBiYfR+v9KyW8u*t^4~%~*m6GD(#EG}TJSU8U~sh9mqx)YSioxI1k(JEz%V z^-t7GF#i{_)uN9=`6utQ@QzQ4M5Ub5W|p(wHek+P_Qvk~7hHACDp+oj#q=Kqbtzn3 z-5cHB8q&yVuHy$%5La6rUOg&!>KYs7d%MC1)zSab|HKvGvm?kqc?CPj)8CVuKw@0f z6=0eX&u06sY4)RS&vd{+RFeHf?i6OPg}bm?m@*PHN53Ev=DuZ|bCY|#QAAg`a(p&r zGCj$!nolWzZh7hLhbxPUJ*TP6Z=)ZlAy_8jKJ%}nlhcthfey8vq@T3NmS~>}Cm%~Q38(WtkTtodcads2sR-MFslq!*Yk~%OpN*APWRQ z9?n?iWW81}3n>j=^0tG6=o(`RQ@%!5yxlas;QENCx)Ol9ZXEE{8Ccua!wXDXA9-1A z0!BFlQfj#*-(j@pciDprw64<8fM>|Xw+5TX^3W$8zdN-b(nX*D z$g>n}CTuCAgk`?}HA70=b8uCHFFcIC-_FY-qPc*ipTUsPjDM95&a^&mT6cIVL) z{;@XKLvP!~bYG!*cbCh9@FbGv`l(H0e1U>O;0+#fJX0dQVcbUe~Jv&^2gqT7f^U_&PR{S~E* z+spe^W)ji5TN&C0`Q}V3FMR9={2BV&AA42Lm1cljK`Zp*`MPWJ{00Z@QN;Q2Sy&=} zzS~8u+FC`i<5Qk2yKf-DEh_P`4x%+9F!vX;9L)s(4pUcR?5@I&5`E0$Znf&pxfz*H402u~nO0ZqDImULpH-NJ zqP}oWBS@h#(hfCR0iK>5dMsnBiGPRJ}e$R(`p95_#1r-I!CNk<`{;-977r@BS1HcH4h> zzJ_W1a9LXRdxLBG*Qr@qhH@t$gl4!KZ9FbJCG_+zGs2n?4P6--BG;vYhJ3PhGivz$ zll+2QI4rv0(8$+mwXOD5M(gZ%XlC-jx;-PzC6Tk&pb>z$fnD*5BT zIyGmb5^_Bt7I5>PZ^4X)TK1$OKO9%rO9opwRDdYvb%oNzAG9+H9 zFpTp~tsSS%+3a983dKz43?B)N=M9AKPP3M}kx=fvD8`#EP&MdR!6KWS&*H>*dR44= zd3Y4#bfOB$CGjPsy>J?Da5XGdesO2e#@}r+hAZuf zYS;{O=Ox@iL%=$rba=i?>E#0RVPlu$$P05@Tcf|*%%o0_SDY14hUzo>NYSvWSkZY# z^IWR<*{cR8M7d4;{n4@g!4aN+kT3ND)F0-X454C~BU8gS4b6WAD8h99?zgu+Ox>}Y zp3B(7AQvm;sQXTXhyjXimp=uhOElDfQfPODua9c!Io>1Gr`waqhg8D>O}|r~PVrQ~ zW&gktbdN5y;PQr3flrk7CB3=Y8%4HTLz-EQMIK7zU_*E*Wn&0kY5SAS_20=n=FMs8 zw?rlT){_V~CjT`OOkztjFW1Jrmd`ztXR8_aW{E`&Gv&M1<<{(b2dV1}-U;;@>G;8t zj?dy*sIbL)ghVL#y>wwDv|Sxul!O1Ovo;}5#E>mW*co3E7sEIE8JW^f2h-{Km=k!0 zTrt0V__EK2c^|n9xAEZ8R@^lL(|y{@UVFmddqve19Zotj5H;_)589`$v+MgHIydoN z+#l<8hXs8|()2JLQA1MBLW-Bjk6rEu9)cUf=3*2`;lNJ z`{i{*#r79hRzgt}`q&G0w3#Tp??uy#+Z5*}xb;Ie!}ZI+_Lba+4-axCFofN%Bydx1 zu9kNrCdzx7JN>U^Wb%&;fz0Q{7j)CCDqO1U{X;zDNV|W$%}##u$xUw^R)1YQuFnt1 z{FHuf{6Yi2g1mh|BIO&0Wmqo-^|6<6d@$$k4?1YM#>F4<+(asHzp+5#AS-^4SrDu3 zb`L{uYDTc64~-$CkfjIthG0r>{W{W%ri{>pOZFyKDLwqBW!^w*T6!JIbP(H17ln&l zudI^wO?__^drew}wY@id{c)TY-uoD7x#7|;(C;7;!|k7I%Objdg5a4GEepS{WOwu{ zptNjWI$~-G(WfnjhgW~7187ogNsY7JNXD|S^|^Ytm*!k}(-*oib|)*uh+vBPdAl93*5&^CTHTUe_n zq`X)~hx%^dh(>xr3_|GKK9(ri2o0(3>$2I^F@`=myWC4ZK4G$MRBd^q?!_EOj%JHl znG1FJgIwyJrA9r@))*5D%-?hH8+-hHKJ5T|uRjpKt)326AldMtX9&%murw07I_IG+ zFhaDt+-|JxQ07U8I`0|*C3SlH+2m5Bhi84)Pg_EXDva-BdNV8)>`TB}Le>9^UP<`0 zaYcPj;6J`}>o3M2AA+)fHK~zOZJ2ePU{J|wdipGMY?bXn5b^UZbaud=&2av1LWOCY zz+W?e{9Xu!@c{1`!x^nEM~BY^2&tly2JroRy^>8`jPhh0-BZ6Imsh3F7J)PI>(+r?){(bBfoq(!lH~Ak za-JZx(o$?)Gq*ROO2-FFo2iYG;31FtK%i69^MI=LbiMFre5NSA zZZADNJ#W@0z}MN4!2V1pRb%n}e8-2{n(JptbeT!h?N84eVEPo$0oPa*=(f2V<+*N> znS=+K%oGqByk3?_y0>x84*Sq%M`6?Pz*gkB1YbYJ8vF|SZX@kGiU1`U!KIpbk=_j% ze~ip&5O6-0`4wE%n^<#9d`nXLPH%TQgL(+PKA2jk^M`nQK100tj`V&vw|aW^w`yMK zVkGJCCR5+Xcd|{29k;4}ztWKSY>pe+e0}bR=9+EC&3zqFk{+iM38qj)^AybUTX0jB zW1R0T*%DCP7=xV!``cA-){fETc(j>R$RnHX=ozNEn^%kDkqpO?41GrT)WnV;BAF6& zu&WaSV#zUhO9NZua)%+arms`V%eAwp3~W1_xu1a&%_F*MO~M@Z{h=<4F|QdhHs!QZ z1Oc!t{$~(LDVekvpb%cux>tYbkx1uAm?ZzoEMW_oO2pQNOF&<=^}cBmir?dNz|L`UzD|~>Rj zTU;QHBm9QXkF}K=_G4`i&5h-mXYgz;-jGBf_R`H9n0>Eop#Ry^0vUaw{^M7uMJ99q zj^{I1Q2&XxTZ+Gd1|U-Mhjc<$uLEaza&cCNM@TX`pKFl5VjPZ|%ILOryXmZ(?dIt1 z49bqk*7rw55ZfRZI*KQDM}ThH3>mFTePr^7X1_3S7AO#1MW(EZ9S3)+xY$5{>(|x; z#`{-#n8Y@E`y$SF9fD#iBO8cY5m7ajlsY;l_k$ebv)u2a18}v7JZ(T+`%hD^UHirR zi9>x3lbx?#!flz7 z&RAT3ayTu`F}rfLX?B$i%4wL1zLZLJtYEs%aH@gqnHSC9Z#&bS0>4R`pRMy-bk5*a z>#v(di>&QYTCNED^46(Ii7z~KWHr8dHa)g7&r|G=-GCibTcuk~pcqwyJ5sxn>bSS! z-LABLyg#rWMzXPu*}$LsA>eb!cT`oSlG#*k!Y_n0JryR8^0_KNC+`6d-hb&yPa^%( zyA4|ty2Na5saqx4$P?>q!B_&-_@_rrw!f&qzGPEMxTfg!o9W){_W0&0X(Z>_D$wSI z0RI6q?;r3r`z*MO{3|5Zyq+>M3vCq?k{eJM(LUw%}}lh(*H$Igk2e9I{75BL+D zS;ZV#K_`1zPeLlDQcAn~?U-W=Ob{E8U~wijTxzVufSJT$~lk>ai-au{i4pkO}^T#h3 zOBa&}5C7FaOKsgCfsU9L^R$XlJmZAs>!<5S#F86Ffe+iv&^O1+ZqJ7~HxNd0`X>bF zYuVOy;ab7$wc#m6&1ITWSK?fiqvknLN)bmcm z&~$Qc%0n#h>a?C8r){D*huw}$nQXBRlWXeEK6LVxU!0>2Z|JHBSw;pGz+3KR_?7nf zvpFN)@D*z7eeyR|56LU zaRGRn=IJ_-qT)G|)9osklw)Jh{U5p44l_1(K^xY=%OT?RO-f0-vvh7Hezr0fgy0?W#%+ORX!qZ|H4x;gu| z?9bXe237^r`%hdCVfk!#dB?J65=$UNYg%k`MbS5Q!|tIJE$$Fu7BOq;qqkUWIw_<{ zNj|fC4Ge|3(ub_WDn$w|$)<3G3@|kBWUjSoO#Lgm3|NR=@UCiQ3 zKic)HI>9#N-tpYj)HkIeMYNO)4-%bWgLiF(WB`{CcI# z_aRT7@x0J`Z79!{&g6n?4lHjkFEwTREQ|oEvz`Tt|10D5Tshe8d44B;9Z&K6H?nSd zw-Ja0qou!r0l+6I?+xVCWyF_*vC1&mR$29kc9_hLYwK$}iJh`@Egf~waQ7vZUfb4y z=2xNV$bbx0j+tJqeQ20>$^X!OP;N4N#sx)rW+n~s54GLKeO|h zPt2t8vbwy)Eb{MCZ}L5?oF8beX^1yNnoXn&fZqKz<9J@UI4I3!VNGx7)CzkzGMh!9 zR!0sHSe)U$1 z*_Ei39UcN9DvJpl8^{Gi`qMsU{N?OyV!nVaanIGE`YXXk_CxPC{VSd`EknLvKx07i zbhgWMmz39Pg2u$kRRG?@l}n!L9aLqQ83txSBbGQ%MJ;A%+noBdz$tU6#q~JsNAQQe7H(y zTq9**ypHDQk3|ofW?E#mfvl1(gg2^^v(8)3%>3syAljp|$Svb9Q(SA_Um{-+qBus8 zV04|tIIf~_RORLAORD;u;>KomJ?lg>icS)-A|I8kZ-DNnLkBIL0-B>CsDP4-~>fFa}|2OIYh`s{IO(AkG zZ@-1Np=WR;-Z~FP7o{4_O$<$#Wd`*+kZyOxSx`qw`+>o3B`0;sy^+1SvQfam=U;Z{ z;6Lz?j9EO^YLLJyfQWd;FyMbw;BRGYI*ZRXfQU$9zh+;c0rkUHmvs!vwFL8mgP5>) zLdb(3(g*bP^bD#{@jg7X5Omr6LFkx^^FWmwr96e)X`$9n`otAq`Z6Q4?b^dTq|!oT z;;Bt~IF6WcNNTVtTi4e^N%gj~lktJ_JPiZiMf|ZBc;bTMv-{8E19>gE9#XGnQssnF zd$9xCkD%~&XLI_AiYZEyIPU`-AchzrNiqUo)e{UiV>cEyUN}#74C|Bjp%8Uq^gRLK zVa=#kW??4~zQTik5fUQu1oRs8Pm~3qLYVDQ zNV4hSnjFl#qN-|uCC~C*PPFj#$t<;wpj)(#zWhMAUn%-(A_Vu-K4`x3?4RBHqHPgX z4j20${-ao94wuKbhhpO;k2xG3Prgbv5j(r8HudweycxSi6Dm$dUx+v?UkQx(PeqZm zhc?gg{6Gu}nfM{v+rKPz#)o6b#@rA7L7L0y_na?&`7^Mwv3h3W(w7y5Gqpi?ll6W@ zPMKN<)}5$gqW%+l06;`5Qt>gh{=nyTxNU|zZp@RvJe#@hhz`dGS-@rj!UffFIWcD|`6h{4r=Wa7kU=$m)gCneYcQEk@RBIZ-4@0?hG)ZQXH;=#h z_2%m&kV!4_4$K6u0n-CadwuusyL&seykvDXw)IrE+)?mpLM<`UVH<^>e4 zw*2!2dZmh+!P%f6#!+4lfaqtBjQV(I%~{teHcS>%>#liSvPdLT!_zsEm}IrppTGq2 zMogG4bI9po5zpS*j*^7n-8a4}J^RgG(|Z$}miQY^J-;I6WwMPLW#LlXOSsp>s?iDd$%*pkXT zwO)$fP!gC6)`6DM*^)zHrpff@Ea%L&!z}~m_EVxs!u*aL;!o%UEHs)q6JZG{ZgnDE zPmRNHD0P|l8QA!3N04clj8JUi)E$z&_S5zOWFV)*ExXT%H?qNqh1#Cn{@em|7Phr# zYD%MJ*T$Swpzwu5HX`&jep&=3^s{kcSz|i1<#T**rzRN_looqTnezH|XJcd`)Uzxu ziPA(K(e-;Q{N-Uz?;sb}c1*@z7YDHJ3ACpIka7-p6l!@1I6kSImC03+mIXBM6&?H zd6i%OuWi|^b0bC>?K>^1Sh1gCCkTx%^UrT)947o-P&YBUk1xUXYwrR;(Ww6 z3vn8i$00DZul;neQA3`*bPMQ@lsfK1EL`-_ESuyQOXR}N3Z9lG8PNnJnYUhY7Mg`~ zrkB39zmuCd6{+U|JrHSfz?Be`Ovvgk$wb&;ALk(O^EwI^-=!Ljf9gW;=gM}5FnAAppQz1N}`D3iX3xuO=dmz52#*+R7fpy znDn(5l7k~77T-EbVu__~_)?(xuDbgUS6P;JdMKBPrNOXITxZ2>F$c#9Fvcbq^n2JV z66d%$^9km1cp`8)eN4?VI6)H%o7PKRzY`#!V~St{@-}~iyXCx~%whN91Izz8bYIMK zAg8!U5nA`RbEs zNkbob+70m?Ih!92_&&28;a%dpC{<1EmhbZRr|tbI{HKT4FE3M{t}TRl3l$X3>)19` zxz9K4vxqb^-_uPyFLZp`;@&shZTvb>#;ps__Ycn-5vgL)!FYX{wv99ADfc8(vd-ZH zS>16X3syoYwltcfsRNei@t(-KpDdnf*AxZjfNg;JX0byA=j6%#&TW`@BAYgga(|b~ z^auR91@n?K+1bryna{oEyi4bap!3FpRZJ`u;ZqNbV8&NjX4|Lm?FfK`*5v+Spb{g^iJACMZ`xf7KS(&)+qjIW~dwvm-oqu^|F zvC2(}_`gW<#ur8dTN&fn`=n?8sP?w< zWrvKl!DU(tBd<&>Q;s<=zcNAzg&YP&jvw*M#c|<2i5vQSQKe5R~HGl2)TOhEeg<u>?~a#Tb>abB8RyevR)JRozc=irMUp{u#Th$`vHE z*!O!B7GE8{$ZEr84`%K5uRW%EB;N+34f(?XdN8I|T)9@8Z`h+QD?1gzvw?M*y4=aR zPRSOvVFnscV4eVUi}G8$vv{In->6DELkYa2pU6PscYxh(fNPO_pspQ@^*N|_y25tP z0~{!{>7-v1XkYZp)A#-9R%!OuM0oE~aua@%G24f7P%c;NYO zk84HZJVFU;a4jCa^r$MY_;-UQzG)1#8{O(mu|MfyPYI#J`n*HXVCK5b!itjn?AM*I@UOod#*`t~o&@MBpha{pGkOz{aF^r* zyfz|g&o7Pj zYjVb_@BsRNn2Ok~IbEwR_cNygwywF!Uq%4*fH~vag3*FUKhlpTPVO<3&BL3op8h>Z zp9+QI_%AkARj*n-hDFc}hUOTH(-ubItaz%1XCioI_a`=g^;C~OJOpYb>%4fr?qqJe z06@|h|2jsOq^s1ftyD=6Q9I+ElIy=(DBmY>^pTbLoRWC+7qrg44qPx;1kTedMENd} z&>T@a_v&nFLVi`%Uz}Nbqdkyu=xS39EFTZi5+(lOqh;-! z(U5KE9_=i?#z5jkZ4l}BylO!DMG4xG(IsBfs?EMd{k>x8OV@q1zU&bO8QZ~Jdjv^` z|6Hqkh=?+`Jhllk%{#1HplR;-l#7cd>x7zb!+TzN=T%&f1Wv4~3*#HAf;Y|-T3SoaPGfs=)Id?O z;66#+x2Lct41%J&Bk#^$Bi=aEzrVpo)fQ)2j_&|U{g_b?izHmfjVrwCFEL^qYi&fO zI{{L%YP<)&!8KnS$d%suTMSJ zJWjwks^}N~?Dd>Ta&P1fWA=io9}z!rosco{CBvFrdh2mm*n00b%fYuWvsjNQEDV0i zRCp3vv*XE9ng&l<`{SKIZ{R*E5MCK3EUCNmtCLM3gFXZCv)&tVhP<{=A_poSv6g!h z=5uDM`f-L1f82_F<0C zt3wSN3CSE(B+3e;M#y!;k5rAr2v^l+bve7w^V*z@4yGgMf@Yk1Saq?h_Q5_!=rO7q zYQf#u_x+Ln@aLzFDyed^QbtC=Gyah3XP+Yp$b@FcR@4e6GH*lsKB_Il$y?7Y!DU5= z&=^^Q2(-YW)?RY1*RBA@ne|5Iyy_!Qv<80rRxT1lKTYoSP-N9Q?|nF*(*l_mSfgiR z0#4sum%bt;OkWIs6hX>9WlKB-ROE){1g%75k$MewD_*qTvwOqy|MxRC4ZHP_4B5aD=h)^(9&a5C^e5IfizYQoN$a;Dm;jD7Jw7If z8oK8n*~_bP4Dz=jnr;NwgM7P?%8U0H3Ouy43QzhMujFp&%@yPo+VJ7cb8m<@m0G6x zXNL+AO?E!G7TG4l$btH6TtX)sqjZ$uq$1hSvd?1uE`yyxC-mg=QmKlFsrTpuxP*pDf(FaXg!nD_*){ z9tll7k*y4)AIT&fp0#R^MOSvyw~1YR5nQfl@22Lx=U1!v>(w55NW+f=O3=J3D=+to z;a<)4F_Kloz_wvs7^UCqM^N@8qwr(NRG*wo_f>daGC*XQ8WK;VywS7to8d; zSM_RphI>&#{Qb*}eNN3Nn6?AytMI(C(nAkKiHOlFij8I+>bZqkPo<%u{;B!T?;jvq z1kQo_RLH&ZhSiYUH`YH#Whu*-*XI2S0&?{E^Bn&Ge{J|+)69yNH(9J1~W*9wm`*T~VY zqa_;RpVZb_s7W0LPztvpuiG%NFzgHW$D_T{!tgr&$KT|?0LYCtL2L%VdEHwt+J5Gz z%LC^T4U(d)4%(QLpjCkaw@~oNI791Si3X{Ic^tKv39m3N_NV>%Gb64zl+7M}9v6g1 zbj&B~u3@;`vzPC9f9uxmt)UJ7&N2dT<$wldv#ecbvzT~$hwkY(BrgvBJ6hOw%RI~t zl{uKHpPYmFxD3r#VXM#4>`GBjm$e)0zvamH9hi(O;I*-9`;wh3cvtE&XH_uVPG-uj z`u)Bbn8-1`ARa^N_P6}dDT<6}UZh26ZhF|0a?+A&6SF#FsKBkhe1~1`%_M3;aJE%L~;QF7~`HH;O?yXyFxY>_x16Hio zltzw&C=;L2Se9rPF1!fb(*|-;PZd_QV)aXUN=oA`KW9)Qcl*_)gZc8IQbCCj1Y4LDF~&EILoirlqF~1~v1J9+{wTLjn3|r?MBi{S z9#7Fjx5(LKPU__No;b`G2spIB`j@T-@Su zLYe)S_W4llNX7PJ7B@dl%Wx`l2I)5X<~+y=Z8hIkp23UBk0(a64wfPDezyms6E+U* zb_{P*XZBIO%pk!X$g`5F1ILzMFOCvbTYh%j&vqoMQi+;g>MCxJpsmSGO?kN~8hovI z*&;3Nw!Dhd2O&N?IiaPC(~~iN_wg64%SEKkQLE~J;B_x>euR%orPe#m;Ul@oZBbP! zm5%#V@$@}}rI%;hkv$>;}{9n!J;a4s@C#PtlR92zo)};Rv?bGBDGjX?H zhvT%adW(YTBM#(CQjw>(GLzqdSxmn1lZ4;fw)?g7f0ksW!=w-AU3GM-gb{$7^~b8T zZ2{c_C_`q4BYT_e^j)TA{8EyinohbVy_V{F)}{NEj;M(X5BHFMTXcbf`0coWnDB~q z3;j`_N3E%C*#jH*4LOWO9Jls0L|`H2VyP_UTS{swuMjn)+KnqzWvHf_*?H@6pY|zi z5kdBlHo3&fCr$lD^b8+rtKYKpKdyNN+8mOfb@ZXxY4c;V$7)91Ygc&Ub9QVcGya8y z&4VU)(gW|+DkM$A{q{rzPg{oHRSj8L)V#_M1x?qP(1a_qIw>-~sV;Hn1&2>W(1Yo| z5p>2J?d`ZnV|JcarYBFjZ3=j7= zWWKr&a|3CHW=S><=UJ<7Td)YP@@1Ue-AW4)p&=7R{;Ry%{QUv6rD^X+1tIbVqE~sL z{5|IC^~Z7v&a5|k+U*&>=%P%pgD^VTi5XwB_*m0|xR3{#2sEwxJn{y9OKkVC?FioG zmpSS0!q|;oSD45-jTPXVNym@GFZ`bZhLKIKbm4wOz*J&f*&#E#TnSbhBmr?A^?1%dIKMcG4ncCO%Q6w~?2m z8g%hsc@OX9X_NgN*)Wb~ZBL|!U^P#u8^5KleJ6I&39*!YlD_S(@a6VBJ5`vJD#^B{ zE(ye;jZjcaiI5?xmF`jEB2>-T-1XGg0|z<`$Sw>mw4(6oUBt8j;Q8AKIy=gOAsi7~ z-tHQNL$ndzoJ5wSL!)r1UQV+L2=D4LUj|Ela$Lr2cWg(Uf_iW9;9!nKC@v-naOrV8 zGxpzU9_nWUvgcE%A%|DbP+e+qSEmIWnEOJ;-@|-{H46!r1Wf$>qFEAed+~lahrwkzp)Q6|0ZeO~%!) z>8=GT{zRrZ))UvvOs|Zj&A!(X4a4NLl$X zd-!ST3^_2n(TFyfa=vFgGH@&9;;OiHZE(xaj8nbEbKmN=W#O6G#m^}QdwT5q3yiFYS?_EA4c zm0;ZL@-4k-Z}js!i&_C&o3thGFfHY4<>8U*%zXl`(gh2RAikbx0fuMJSA%blb`Qhu zhI%-$taGAe)o3MZi4Oy$tDQD!a;Kn&6VTmxxnh_vmqdsjy1PHG3?5~*CY~_e z8vVMS#rP!c{CnC-8a^L(eMKw{=Q_EFZ&EJ(52>l1#a%;0?))Ff&FO!8($O~eBJZOn zQEFju5^}R5MPtD}pm+~LaN3i}+G1aJO@K_1=_KAj>+o7&fxM*akM94}JJna2e~TGf zjy!Ws$x5w%s7C`}x-Md47P4u4&|Oi~qWfLAUqV!lP(pI!j1>rS`EJIKlV@aNuB5%P z`{sPxkdwE9c`ZmIr~}H@CIPbOommUDl*}JX!dCWb*;&k){_;0cW6Kd-)poRXFqd*} zC*G&I?@63_&Z10MRC8mf-pZ6r_M3Za)gpQ`G{sQI;NJF_|B7eh{5R@(>7(~BAYH0ydu-mB9| zQULu0%HK0ZxbL3!Sju(IM;w6SZKJMbyg4J6!}j)`uL~QM?qMq%*mn2&IyWi3BfL=m zNG@1WCt(d--nT^FP_6Y>cm@l3`Cf~8JrIHn93%$)5^@aOk0i);-D0@reEB3g%u$km zCA{;u%2II2QFNPO7*oUAVfxW1`y1ahL@Z-Yu2=!So8izYd45BBr<~ca6o!Sx@1nun z=d9?NCHM0H*>3P~NLUfMen(Ck*v zu8jxO@^Q&pFEEA89VABYw?I|n%MyM!C|yG@f`*XWNsCd1=<}`>qoRNz#*|v+QY+lJ3>QP7&6?p5*Rem7d+K+-Y#8U;1*_ zB`ZY^^l8w7RuZDk0&8BQJVA}j5_cJsls%X0AQbmtVNF2}A$6^&qwjTC1krS$@Pf7v z=?69SremDGHYJ*Nhiujt1SsO}WE3_R_n6GaID>CYGVQCLR7K`3hH znJ%!I=N3QOl09994~lO^g}F1M&x#{xH|UMpMBBBvK;%09Wo51BncvZYNC`)umhy)N z1o@lHHroH{+%QJgTIg-Dq$A6kPdl0i-Z*j?*$dsO_?($PzS%yFkhq!X2K~JF8jGGf z?;|H+P8Mu*2+CcYZb?}t4F@kwLivr&&2zrs@o)|g%GuM@S@IaArJ%g~Y24M_;QZzUwtfbG=qE_ z3$KQdjiKDBm6rSH=D7;!4GHX;D$zRxi-A)OU2cH=8BEr^0K@EVd^T^aZ$QgJ&z6<7 z>?4fDLoa}Bq9VJfiVnJZ_KZ8uC@+X@#|4vN6Q9KmBYaK#jl~9*gf#bFC(7u|=-rmC zM)m|k{*ExjJGQYP6mEu2gNLDG8@bVx%vS{Mpf5Ur8K#4CEf4>J`C#byYTr(Gw@+GH z^MTp*ar?e18A*oOb0JK5L?Z!XA09sc*XzA5kIZJi!vHwW)<(_xRnTT=ESdaP8c%p< z4|<>dOkyP7J}Z|o1;pn*ZRlQULoBpTa7J|`SWrYO)0AhfGT~8H;c`MP^ zQ+nydteVQC6$bScNs(00F2*-_ZqGM8Ps&~dTQmK^~j5a)0B(& zMOu1IG+sUU`dWh1b>3EyIV-Jsc{Opi8!L%M%XmOt%uHHKi-jF0ZVu(pe)u`$);phxlo-W-DQI|gDY$wyyjs% z@h|hZ7tDH?@w~j09)z`cFs;+iKW+s2SpJeY9?lhtz4!59SeCn*4or_((bxvQ69bu8 z`%Xl7Ph!05rIb0RxI_P}3O5AYK|p&ZlW!(JOk@=t-h)(oXTnjbm3*2F)Fn-9)hYiw zh%d890VDt%z^miU&J`9T!B4z23v3M)w2>>XiDgN90?aZO)I1&J@2TnEID!%fm1Y|e6kqw^^+z2NH`dN!E5krP zG8#)N`Iv8sNUHge8u09B{j6M*BGX)M!er*(P_aA|b`GKZ?$p%l!FZJEr6x`Z54n2v zg65YQs8E0*XfDaEvw!1{#4$rS^wYGq=UUBgGUs#;FXJO(9!BdQy6s%uk|UUI4h>;B zggmT}B>MyJR_qqCpT)HtBdA7IBkg-^Q~nK6Ga7Q!c9`AaMWNl~g9*;{gSB1HCA)NI z%=RdaovP@m?)EwQJfnFrHovAl7wx>9>>VJzskCz1C_m`dmKuZb^ruso-WcU|J@=Y% z2=%pWyJ|3y z;ivX@dUnvm62D0w$!(RR{9cFw?dw}l&j3#sJen+y@P7*bGeybCuM^lb)06YpOg*>&8_COi?$_2-*n^s{Vpu7eXlidO^Lp>o>4S?2@${wUn~M ziOBJI*Y;6Ax^)O{ku7GJe=A7q9tsQ>I@Khrj}<=-G{x2eWezQ_rroyUl+Z#61uvM! z&bz^^wBZ)keZdhkQyyDlF1qg z+*C~Ren+>6vs*>84(hH;mIzfI_WaD5*J2t+3h^Arhg4@aIwIVWdvoob0L_0XHEW(e zHrr`93=^9*`-iII5CbuT9MzsMi+zsW?i*a|5%Cycb~d&VRd!psJ=zrSszmdfF8WZm zo$y+zy@z@EwG9^O>dK2?(y>(I*jf}U6TV-B@0_x7(G>Hh&=s*Cggngepn<-gn`(9uY$OHP6lr5K_oW?@e z!))DOx^(gnrtm`Hot0}o*r6ay`IumWIz&qKMD+y8T>%T?vAqDi_&-JMvKsigkA zjwfhMk>~wxo9utULcsSqCC9}GkDThmOzKBJ>Us;s4DG>3S;`eB$b*NQEhlGN3pSPb zC^wkP7Tb0Zk-2EK#Sn#e{MI6c10`~ZT%7j7TRa)PNwirdH1Joh{|;*p^BM51J|8D5Z?hWy1l{8xX+ zLMn4wdjn`<^c~nD_h@5mT~wkP+%%KPB$QbNiu)XyjnMJvZM87Yaf&}B;5@^M<>_e$ znjZfTu=*tz>JtPbmY1WRKV83}lYe<Tw>r~VSBSF_f1`E1S$}ViBzIqGq5L! zFe_RFMgD7gyakUk49MTokANB82TXZ>9T_yjm{?rnZ0(?mUu;$LnaERS_Eno)Nz-tP zeqBtg;VC@=GnRb5zEDp5e$u`PM=Zm5*_LEtu-+u(?Pd^PB=&+rtPg9sMB^C$GucsK z$?CYXVynkjwb$J{J&KpVEm|_fcIlDh|xBF8(;o;tHlWT*}o!{3Tz z>I=FIH0G&6V)bMig`=jXkWYU-x$;YoAZ&|-!61+)9-@zk4?M%rgvXn-VHFMU`y@rITQg>8I>DP?oRaXPMs)9 zl|c|acoQ2&w)IGI^Ll^0_t3JGdA6(ncPDX$GhW+-ES95e5Ae5s3M#4-`rw4@UdnGL z2^iY42|!ba|EcPV1D}0g{nn)s5@$jU1DMeRK1Fg6^I2lUC<3F_H^a&)rAQ0KAXkk^ z+-fEJ@~MYrpJE9@uw*O_lEUgsY-Bh>B6~j`+Iwx( zwaC0kStEPFUW=0ENH$DH@O@;lf&Tpkkask^8s^)mHU6A1*$fnApx~9Rv$lZH^X%s& zLp$;O$+mU^@ zAifs1I<9QS7Yx&Xyj9M9J7H-R0?<4o0~^8mOE)gme+-O4t~Uq08F`II+-G)!r*Uj{ zeO5n4x!RPNG+z)}&~aJ^>%d0^H*>ARybD^2kP@gYJ@#TdZ2cqZkW4Nv9#0Q1z5WQ( zJG7!H>E=(Uh^WE*Q5H83nWO*dIswC(`^&Y+(dQ+LRTeYM$Zuj1bPP0i*E^YdHEyRg zd=gfuuw|QAp(et5_{qoz1q#rPns#CNwdXFWu+8=|mws z0?PzaFo}xs9bD#H9uODuDzinJtB!GJu=<94B0@$@V(*nbXQri%PMO^Q?N%h$f?x7> zPGmrh(qn#>=RHs`t4BfPi?bJy4uIe(?>V8jt{HuN(^w%!d9JOnGtaKQvS>1O!@+BL{f9l+o-!YUd*~%X`^g+MnUg1 zxc3I%Ze__QXwW=8o_21vMxNfRJNFof9JzKoFMD~<8bA5ylRvEf2Mha(0zz6}6U(%E zP-uLbsFollP2^ufRO*B=>R%c5vx(BonyaD6-^FIB%xnSL@SA? zIV^*_%=^;FRRGYMF{WCxA6Y0bokD=GnNDO!sS|WOiawHOY0P-5O~T#!-!_3G z&jpY9Tk$bkN@wIoWyGY4Y*%wLqNG3i15{-3?2x$Zzi5%d3XT(3`)M)Hc2{~=HZAIE zIq*M#LOr$?zzv96^6u2c!=xk+WJDtSvf3&GcZf6Sca@{``{fV&eUQz(j2Fn`&C8Sq zAs_DBgS1;mMPlNM%Bs1gsVQZ&_T=&<_E$IK6A>Gk%DYRh`M$bBl`jp=ISw$8s$vD; zyjkZU;7+`UQObkdzG2aLJWqOlJbHl@UB$^V!j5smTl1^3jLNZaD}@uj5E?A>W*Z=? zT0ql(aouNpLDL?onnv0KE2!)u+HCT2Ueh0cX%yt;eI(9CM*^IWJ?5}|IS?09wV7se zjrKh0tf~Hr>E6#^y;gs=3Cd1=&0T8*K<_vJ%%by5Pk#QL1iw~L9wr&a{!DY|LEZ%k`j;p`F4E=?IGe1CuE2*X(51w@dg!q zj4F_S26B|Svk`Zlm(r~O&8a~v-{0`PF_@A^G~NxXNW87py}ig#FMpeTpqf?-8K=a&KO~T| z(1@6OMSv^K=8=AF%EYPO4e9k&9K}b;p1V3+Il!7ucc`T|9FLQ4d@mlyFenfVGS`!C za8}aKJNx@JW-tlqhj*Y&FQTl*g?LU(4X@A#ikl=b>GH%+WLPuZ$+h2#-}&9xB!d_V z!=mywg*K;8DGuGNqOdsWsIO~o`cbtmTa@Ko5L(Qym6~^uRWA}_ucK%fTPoPFP`X2~@YULaQj&;DJPkD2ejnX0ptp}hzqm5T2S1in`M8Re zA+I}6PKy44z?QNk82t|{eqe!0<`e?y7>$|N_T2|;(DI;hL}lvEFz+~YGp7_T6iJ(v z#ot7W@tQI8-N_UPn+%sZg*RdHH)Uoiru-ZW99s>-TUu-$B^+of{tP=vuW`0!yc?#^00wHfal{v_L-FVee*c)~D=!(Q>9P%_>(i=lyBXkcFq`ZLGdO%>NnGPUBno$fKjp)aY9Rt&tX1(geGrJ%!85Nb_ zoQan48~Q`12B1U-^2+WLBB0V$9+DN5LH~0%pmx7edXm!KA@PI&jXqQ|;$9qciyl!+ z$>84};RmLbM#}^tf-?7G2;x3cwURQ!A=k8({3vz@cOmJ#=}<_&7odC}k2|0#zZ*;y=#+rZUY%9*& z-WHm?tb4GR*4@S1E3Fg|Yhz(K`|2aOQ)U3e@Pk7C%omtK_oiF*${P$vRpuM7;B*e> z8CZwI1|ms)+s>itYgtyV!Yko?1_V;eHrWI==x;B}#Gai4^u9S%__9gbEuhx4m=z_z zAanixhp$%=8!>cyYg??{c=Bw0`W%$jrbDYcQRyj-{EH$mZN#Fdb{cqlzSSSS z6)Os*^<+YuDA6=t)N=Mw`~H#3(*x~$R#hrBnZQ8vjYF`I&^FH_=NNZqy#L&{ThEwC z>bw!yA^Q9q-@~lTRB*YC;Ni;ZX!$c>?3KM>A`m*R(&#a*{8vt3kUmsO_XS~}ooYvI z0eRn$h_r1~R8-T7Wh2#UV+Vua$m7~9v8)=?WkJyw&nC<1fMn|V%VW5Wgt#BwqVH(i z{|bob`+DwfnS*uFHvUBp$JP7yge@ZmPc1`>-p6gb*I~rt=VsT^l>Z*Z%}0VG4N2#l z73=OO=(~Yh$FFmO{DvXFlLsY`Zd|Y6AB`yX&!-H22#i$y#0kKx>h)n%g=PMUak*dO zJ#i-D-Po+MQ58#Cxe_?{JmL`D7x54o(hvyw@9f5`J+4UZzdJe|>qRHr#jqJL5u zU}{lfz1||*j_{$jYi8#Q1?T`(yS~I^_2}p?*isz-|KB5x?^9?yfBfbanleW7+HZf5 zMB)M{x*MxZqUA`yf+sb<+&)jlB0@Q%j>Kd+A~Q34hF6sKod%rA%%GudASO4(Ke{S_>+FR@UnOWqHfw&JMPY1=rUqvc*D-g(S`1=Mm z<_p2I=m);RLSmJV{{-WbO-AsvC-|LBW*1ta5#Sd?{1VD)66cX3^%BaXVo}~K8PryH z?rIX5|3k)q@PC;0&-D8OgO3LJX6=|=-?qkmO>XelCCdD*X} zdHF!F3VvfvJfeBTq0QZLss!v&B9~Vbj$<_zgINBI=Xw5jvfqvrC56o}aboo1Zk56m zY&H{0r+4N-#rWV6t~PPMC}TSoJ(WOjS!ME{j2bKJXuef8Iz;evC*g=fW4X~aHm9fu zuk;dQ?-l}|2_TaR!eiQmE`TG*RR||0Q{A%%=4%bcMl3Y7$c%JQs zY!mjR!x}BDuMWjjro3^yOUWH{2)vox9|E^H(Gs$}AUyvjXplgN|NRIRL4EFMRCwJQ ztS-~y0x81KQmaQR1Cwu>AKNEUZ_)Mnqb^&hn@qXT+V?Dl67`zY0>!$NbA;~;y*tc%=?cfRl1Zue|5SC?YUEwr(k*%+_^=F1xr?!knJgdS3iTk>WzmP2_Jo9gNP%UWjAcKiF=mF{nsPi00doIGl?zBlq-S54VBZ+%AUr&~v6A;zdDF$k(AyMXLa zT*MAF#K5CC(&i`G;&dz+@_NF^M?RIHpMjBgV?=*+F54~Uipiz@$SvyH#}VDOwP+!| z7@@0_nUZS*DlW)iGbBZ!8k0yh*8N5U`UezXY-CYg3qog-_h*oa#^vjy{(%08m0Rb? zCFycV0QTtyb6wQ*-y@+TcG5%1Rv4!j2_u&S<-B~8lV}Rq%!7S%Ta>=?MIMNz;RcDz z7&J49zI}}o1;wgA#Tc{iZn+z}EKDPJARF=! z^*@bMixg_<#sh8ji5B$5g5K zYO!(SS_9M2s5*{~@3=&CE*Thn60N(Y1}OX@!>Cli|G;Zt2j&>3~Y~R1Xlq zo8)U*-d9RKxP+fn89FR)EkI`1?^mnUD@*Pi??pJSCAFvSwGJM$Rv-#<>v%YA`8FEb zB*-C|+NPsfUX9|s0mw2mx~?~Wv-z3~ zA6qj-&dv4Ih{0aGC5h9~)MB?Xy&=NWj795^Xx1uel-nX=iQ!4cqx^k4_r($4Xd&`N z5D$2bP{eFk*AS>=V3t%916pm2ojdSbrFrXlBw={f768<gzgI;YT6`oZ7f{hSL$aAqo!%g;zUK!<-+4!%PI-d@xwiJpAM8v=;(X=8- z|AykyGqc|NwiA(TB`3Z}4`v`IDFbm96sLR?mQ5HWjX?g3TEqT|$q;g5>$RS#X+2(A z5FVEEwgjhAdMuh9yCt4CuE_W&&Th8)**p*< zgcN%WGtGosggxO$NQRvvu1Y*rJ%mZ6KHUPxB0a=@qL97_XZ|27K8y2)5sE9KuBuF$ z7F;h3l2#0iBCNO2C(}<7pcwvg#2*5ntQzMgU2lw9&bRQVZ{+0~AHNU8-y%_o=;<%FLbop01 zQL~7KLsOGA3=-)ptKm2EiT$JadnHjaYL-lV8}X(IjwgK!^Q*lVcN`HB7N6y*aJs%k z7*B6#ZW@?xXieu`#M-}jKT1jtv-M7i9BBx3c?g)GV@##>>Q|hO>$Z%8^l{K;9cXk_ z*MfJEGrd&;H>G22Nhm%QG*qAF~%IKtW{7J@gaJJMo5Q z1`N-}gQYr6lm(CW#i!z^%in+$N}2cd-Yt%!P63E={4 zM2+zc8aiy_+2XuDdK-sr*A*%3#;?1}zOIK)%<;eDt>Q1|;wMpqtvE||Umh&jig@lN z?0sHSv1k|JwPe znEw&)NQqRq6e8VlsT6+zyX_{4EQze+!eX;;yW^)VCE7baI+XC_ww*kf+;Lmyw44*l zBxZ>)ShW*$_~c1REgumX{cNdz0H|wd@MaKn!>0(gH9l$G?mZ&sED&+?g?ACnVlpKB5S0yIr0l+ic6eiV^1R4G~4aw8qdR~qt zrPmNNRZ?rJQzD*NQPBIk$)K4Mk-{8|g+-|Ng*y!Aujh=*E8dS~9=xh#mfIEy_z6|9 zyqQRh5I64m%w>rhDM~u8q5k+@&7@-hV_Yf= z_#Cd0^)kev&-CSQZ;Owc3|%UVC90!BuGyDrF_!kbW&4L##kq4~ud+7hZ=zpYWFi(o z1AXo_7o{Z`gcMDmQsqd2nqOYe^bl0-^}w&F|?0^N~A(0xu*@E}Wws@_uj)frENfgcd*b)yMpbJd?@4 zMlY>nI~HPoW;5{(_4_k^`1qe4-fHLDrOs@t;w%HhSe^q_-5A@+Iut)(aTYsV%u;7D z{A>tI{WB6OYzi)_q;n{{*cWpaJ@MWeO5GW!@A&i;Klwvm!X2=^`K>Gt3W!v$i8JP~ zy(wdWw?nopO-!f%A}0u}nKQ$g+)WW}24>@7r>E2wKFDaW{d!iRpPs{R-d{*^skYbF zgreFw{hCB#@|jH2B!2GWW{hC*WK%)A+5CY``lWIzy?FJ4NOUkxZX^@1HtNh_kHBd> zz@QgTLiBSV=jg}}p}o>L*Kuy+Bj|X@%fAY*+(gor8LWxDZ;NRLuGi_dmHtYVjS0a#^iLHU9ABOHEny7$r6tP&G( zkce=J0R>f5)o%vB8*0MQ0$$6>yk*WlP`t^D6Be?(0Gxi*l6U0-44Ivv=Cc+vfRuQA zN_e`+7T0XQ?tRibdhA=Y`1(e|G<=-6Pu;;kvc>8%YlvlUgAEByd~>pP(pn1*$Xz*{ zmU5kvmXRI~Y7VYK-Uk<99N3=qRDvRfl03FRW;h5($q-s+OiXhhQ?XNO1^{y$g4bFe z7)$H*>FQus)4pjlDP<y36Oy8@bkvl9Wve5i$M?e<}WA~^v9MLKg{{-S3bb`>ES$M zCaDkBx8YHLJjwwiif?9G@z0x;fBS_?h~=nEF4_8mZgH+!7{j8=6gZ^G*Jta; z36Gq;FyYI87B}@!4;|B?g4Xt6@m-dDr#Fkhz4&ILXu`H0K`$1__o>f3#hxdRk&#c* zymH4Vq;(a{1bo?A&<7r*XZOK?i{O$Cyqz{OEMN3j`QMx<5(Hr0$~93olePF-P6D!Q zwV)xVVV5Zl=+$=sWcOV^19-7im`Osf8HIr~r}9R-tDtp&%;jDQD)IOxi!8Vc?*D=w zMa1$Rx%7NZ4xo;&_9{40-o{};hUYcn1Smi@Ad^!d3v*b-7^D7Ar@GU zs4Yw^{$gS*WR}kz3l^jVi{1U%v*!7^>8zVU%R|#U(#eiOFuj?eN9r2;QxMoyvlm-` zgo~R~Ud^Oc0DcuvIpFxwz*$*sO$29&x@uI3#EXWVax3j`G6!5Vt4z_hCwo_ZrACkb z(9{wB_sEGEk-MxffEDyHUkXJe-@_G}e0#_K#~GW~FJ^dj^zC*OZ#p$DgPEYH4nS)D zhc%*i?>kiQ#^Of6!;^9l_4Rg85a;LjM|$!`GIO0jjcLiyI!-e~WC{}>zsDj6qn+G# zvW%>WEw3^@qnk-(M~3i?4mmkBH;+fx`QW2X1v{%+CLp#)J+;gUFHs7!9bgZr zQFS-U<>?8ZFnFo)+Tp@Pg8@AuU|br>HfCQJtxu-3Z)`X4UwIc6#Bbr`#J5D}>~K50 z3WWkf=$l|+4uIVs(7t)UgElU{fIIT?9xw}_MwdKulAeK#Y}u z6Y;~G9wUSV3ee=4)gPn0e0|ap2dGDGmQ=LA8{zGUY`8W55q88`crp`49Q7Xq$aK^rk6OTvew|}H8WFErjKkKuS0rfL zM6qAZNp|!I&a-hO5(Xq*sc*l@k^4p2!+w~GW#VEkJdo}}Xp}Gbn=RWzY+M|Oe=#zY zk*V?Sz4IilurLtD`TKCQn{2iPu^5C{pvp?u>sXK(RfaRx%>u*bimb>r5?l=)h=md} zq6I4R#h#0L!9n%YDMCYm1{08#3vl|-@ z0J9+$R?gHu*8t{D<9nAG9MBa9N9)_oMuqa~ zVQ66VV5sG{Kr%iIeT=$^ojXDd?cKYlY>}ZC%RQf4DXVg^Bs0T(t}x^$h6RP8Tu)+5 zkq?_G@_bTChJoGaW(;1D-a=wGfj{0Qr9e^6W>+Oi`C@ zvL4s@V$>l$M=bNskh!S$PS3Za7L)=q)T$d&Emu1*fqtUz46fEV&aaJM!DMZyZ ze(Bv~J`aKju@)DDytmy3XfrH6uvjKfO@=pmfoQ8N7f;U&q5}Vjk?hfgekc>f6hl+DNetJv$URlaWDgVNbs>iBojP?&LaLd|7!M08D$<)qFJwNK`D_w5 zS)m-V>}k84QFvm)shL&(!J3FhF8R55s?C zsOMztOv#lZg2M{eKMbMxo{+Zu)E*9oZV8=rS$ z>64H<_Q)}bp_xcC_s7tqFg`J?G6V7UTkgpUB78A?4MQ-0WccZSf~&m-*IctN1m%r4 z-cYW+_L>-WcXRjgA&f>Dw6U-2 zp0HgC~E}KQuG|~@m_kC>Ts!8He7#tX6NQ(vORvY z+_J2wn^w8$bj%M@`67sDlQCS5AJV74U|bJFnL7!FaO(Zfa!79US}1?yiC)rWi634R z@XYMmJyEW{=IXNV>b+6_QSafJdXD;E>-MW%AmDM#xuQH47Fa+ehbBh6Dya4X2(`SG z0#zO&WP18c^wuECDcdYp?u$~+1MX>d>4iD|*kjS=X+Ny;Has#CB86e4wP%L<>#W;+ z334HRCom+G-YAaIGNfg0_H2mo9TG+K7?Bq4h-X-?_G|(I{Imo%9uP@<=$7Z0^D%r? z@#e1r?robsA)Ywab;7E1?Py=5fqi4l=BMYtfdkENCu7W0<==edH=Dg@FZ}~UN8)YpO0!4+ zaWGVm`AgVK^h~j39+S+Ya@F3e<$tJr;*)<=7UmTni4CJh{u+CQQ#g#Qx@GBVmJ&t? z@uruhcvlg09GJ!A{=pWR%#TXt(`5;1u zhXz83y!tiYE8}>d49D&A*EZ-b)v?BTiiT|@NBdOI;lq!VqsNYvQ>RYISe%ctPlJ`T z%4ns`lpdu>=lQ7Tg|c(UPKmN@<*e%dvw!-Z%Zv@ zZn@=ooeXe^pMNe5|ah?F|i$lDM-U%NVZLTi*PpH%f^2E1VN$er`6>Og&L{^ceL^*oDYbdbiRHB`PoU(4#;br#;b* zt|{Ah>@L$Yv*k0NxueW4GF(viP)AWt7~>esYQt(bv;l@t-getd${XMK1La%ay1PuC zrrZ|d`9KWUo-qm-fgHz_eAN9`36uln#K}|T;C&C2!$%*{GeeJy>W}i)Jz?1ES&4-e z)Q$#~$3fNk_q^zZI#jx(xZgRm>T*bB&v%W; zPo^b$4Yb8L$5Cz!Yebyw-FsCTWJn0*@RRMG!sRE^p2yTDyJyZ!hq#O$ zJ%z~vCd@VDr3rP&?+SX7LoP;q>1gxhojH2+PNg7av4+Jc1LhCWQ%jFlrXi|0;>_Nw ze1@Sea>DnqcnQHbiDJZOa(5`FV1Gt&K6y zaWEm$ka;{XL@*2hV*^7NgM~No%y9_=d23G??TC!8pfyf$;@tD5arQFJgQT4-J*8 zl%A{h>@ItD?+UjK4(NrN$lAjL>y7#pPFc0T6tU=SkKrlwApQzuWXarD0Ae&<&16xVdD zE%Pf*oH!BU3el=mNBA-W!%_Ym=ddJtc_egX5Yq-Qrj_HeZEQ4#uEi=|BvARKS0@Zj zr8~t`8qbKtnVGZY*s({#FzxTh;2$bGcTL2~bu7zGe?#t5! zU;*(^2ZWCwghed5A1_$y?Vat7Hcy@}#DW>uUUPNy3@)+4&o5~utSob$hFscxkA7FMx*VShh-+Ln z#%y{lh>Y3nT&RE1ALlPSV|Qc_U;> z5u5Z#;i#`VJdJHn#9Li+PJYN&tE_YoqJ^P;&71#BV_c5B5Mebi>8ZdU@v+k0s_G46 zcgOhlGAIKzZ^}A|dsL5gGn7B|Mc%1D$~9k9 ztgCm9~MMcO8O= zUQM3;6m0U7MP-cH#N=NTW6UO}{zYfoxesZq+Eq zX{QJ4r!#F=1}1C2;;;X;^6Kw>WqIvuzPG&o^?$Rx`OR;P#R(Yp$D453JYiTd^pE$~ zG2~`7#USZnx#*)ukCo|ZJ_f3U>mR)uRR~qrHZWz-VqhV#w0&}{&vz{gIpXUKCXVw& zy$d6l3n_@wwQp>;Ju({C1hf`{BoCeWAP*d}U0GfV(N z)TznSDi8ehhM_tv!1Vuttn2p znBV9^B!^dBu3+yRh^-{!%(4kk9Ylt(J36HyVoiv6pQX52Q0q1gP zV4wUCMVq4yX0K<)8a+eoMVm`eN0_k$xc2DTs?TnEi5wVXHaQkV#&iw*b?5I$lZ~TGsrZ>Hz{N2C%_VN=y@jsM*_>=#j{G)&L56e&g)K8YT zzx}P{Hu=GDI(FRc3xZHQ&!E*TFhp~VpT7(o`M}!ONLl4E{FEH&a16$6Hk;ckv1;Nn+t5$yS3D`VgQD?(|#JH z^j2{PhUtRJ@@#yR7NJQn%o_rPQ7yZe69hV@hv3AClR77HBQeCVIYbdd=@w-$ccfBj z&>n3CL8N^QREB2q9h%*{cSqP5w~g;+yPiv(e-;xJnNLV_(4t4r2-Vj*+p!$&xFqPMh_7}iJqUOrFj`Y%n#t}_j6@_Zl;`_Ia8+3oR+aW zC8OkQjKP;OP{2f5x0NP6;rKOF9miJ=#29m(=FZN$Dbb8)Qw>N}6CvAo`GM7^f`lLr06D8?{MeR3fT+_N(?Ay5Wna1sZ8DYu+A zLJv`WvrZVy={Q$r&YlgC#9Mn-GFx0;jwQD-Qi&*j!FHV&RUvu zM?vKM&n>8-tfeS)Xw`Xh+|YR@wq!ew*k&jhQit2HTsrQ`1{*@4)?4o9O9Dg)&q@s= zg$TFQI*!u;&k4^5L)loCpJmr`s9bu&d)t3JVcK2@F+@*u49#RXXp?q?2!5`jP^o%i^WS6C-;!Hv+~b8q2b}-5O=iO7=EgYq?`7dLGXMwf=65YGJlYHL@5BX zcQle?jM?;95E;`g#2@ySMbePQM|E5H(mnGJWJsMq&)kD8WouuLjEw1WYVt&R^!U+o z^w`7Y@Zkr`v15nJiQ|u!smW8ZobQr^#;QaRa~3XKSXE3I6c|nldQG(TM5hpv5!O0? zWnumWd11o#S&20qa~5_@?1-KY3?B@oFu?S~a4>{Wq(#PQEd4E;Y4X&Rgwb3GB8+cd6Lk$^X z7{aOX!#)OPh)Vg!K;?(G@i~uVC5%*z=F^j><71ifs@of*ytzM&Y@LfChcc$AA3n;7 zvC79k5k(Ox-Y%7==cG7_3^m(JxJD@P(<*{EBbqFe^*rC4SmQQ8r>TP~h`54iM#E>n3iKU+Os05>R(V&)B?vhir|xd)Y&j@v@2C$b--(m!dx}K{OaE-?0G0 zio`PKNELB#KVcF#0;jeSLWwZdMxsYE(#AOnsI#-W&I=uezOnKgzms^js~_@+i~r&t zpsfuJv+82bQwon6Q(QO3Y;G)wjM?mg$Us{8sMzp)i@mg6`_Af4`sARj4c+6HF5FWW{K zyehi^8L;%MQDzrZMq#AND+X$$4r96HdeoMdnle2vF?}?8jv@~3kt4P+u){#jbm)JT z@nFli#$YB5$))nc`FibAex7ACLZ|ISE9uQ~KpE>;*Xr5WHpiWA4XqOwmq(n5|ME_L z(tq{{(py50AU!8k7Y_eX&+%a6vZb+IXjXU|9UWC$S%|ug>)ex`;{J$DfzcDg^76d2 z;5lT7E$8sW%M{uHiyLsv^M(*7{D5|nArV+?X@w;2r%^Iy_fqUVQi>0oqWm@h0WmC4Dea`x<88Q(r$#$+h+b~}5NWXvm{ z^=&m~RLn1G<@<@K`R**2PM3ti+7Npoj*>j?^j&G!@1@94$g_l@$}EobUrP{0p!tm{ zmQiMy6Rys`s6i7By=(LsQ5G?jN!R9PSy2vAbxwllaKwXHswpDQoYRp;EoH~Ob$$s; zhcl-o(^KzyJf4i7XB$~_EhE46EOhQyUroI$n;pI~+pTlWLAWO-hClKXVuGHP#aIDu zSkDK&Gt?&`hacJqbz37B)Ey#-l=Vxz#COG1&+R58&oz#EQm{%T_s+~r>pbl*<0n4S zfh@ydN<2T+&yy>cXuH&3tp{zh{qtc|dV?>-2bU41={GJ>JyBilmd=)*z~!hX z_L=*$y2?B;JnJ97AEHg={hUYSFief#9kXg95l3E(c2va?Z359un~UMB+9z(F-S)>` z^VwyH=Awidzk3j9_$4gD&NiB9W}le22IJ%7A&B^nQKq43`sg)%d9CiZvlo{+)a9|8{Jht<+Bs&c4T zI?}|jo2^@V!`NcQIX;rg5FX}Ba3A-i@g(2+FYhJ(r%F=>Ywp!S%h>I_(B4NIbY2N+ zvA0MgZ!LLO8n#XEjOvZFXU`s_QHbG)LCahodd3ii+!h971L4Fm24!=exAgQ7@vR!f z*38+Nm@~QVzwjm7UJ<4CSzemN8(ZQ(K8hQwjdejj&&qwq!s-C0H>0#CN=rN3E zBJUwSZVW**sOLy+jp3La*8oXR49(L$h#q>ISb{zMB=|vC$1U8>FI#(h%Rt{?>DxL``g;e;VDDfV?ALK0U$IXEhPT2DhYI6Fch&EJ3=fUU z-+<0xfoK!3)1)Jo2F5T(WXWKb~t{&?GhEL=M11P^EbS?}l zrAuiZ92$z%$}qxq?b=l)CU(ZKofzV${2=6bn@!#jJhJ4Ux$s$Lk!wnagUw@z8y0(Oz#+FMV-m;-GZYIWe_W@$c^q@ zSv_Co7nXFN+KB35Nk(&sBjS?3CP|7%WrjPixGro_TT>hoL;YKO%fj5e&Z$l)^YEAV zV3bE18zQN(ZBpM_&b`w`WZGq0^P6dDxt1SoV!xA)u%d89-L~jF?!3PvY+RH(WmaD_ z;Ie+&_1^Yh_geSIIc+1|Y^%E{x$?kAPS35J*WD6CgAyWY zLp{`)93f@A@*C*vdg3?vMzwqXjyiD`!U!sL1! zy*F}U9Fk5PX->zvFc6jA{K=jSOvVgtt;=*|dM?Oq?eC|{Atv`@(6izh-_St>?Z5V# z_%2cOhMl7)NU4%>M##*eh&W`>%`YyN+4=d{e)+DuWH_yq?c+OQ4iR%E$ll7iWuJms`WepFuX0rSF35n~qVnolRt}a`i`ps;%d`#MJwCC!OwZ1j$*Gw#JI9bqzAu!M z<0H>X3%x+A%d2HoW!kq@LR;-_bZDdu^s3&JotfxGY1;Pss;%!|A{H z^VaD&2YBAdWx2JFp>8XL(L~Y;vxZyu>v1PF%qG01-gp)-sKm}+;G0Ym-OSVLQ(0eF zY1$IchU%demF{WXtN&a3P1<>G1j6Eip4;=N0i}~R5IIBCAmX`Cm$Ixb#PdL}3c`hj z3szYYT|v#ComZWlFS~Z^D!sZ7Q9^s>QD0_`k&a?Hb%|C)$-?4txW&blGN-y$fKku1 zapnTC=n89_3`huVQ5)H@V=SJN=!MpEN4)4IerH@*y$~;65Xj5)^r$`U+q*mBFY-^0 z=&j7Q)T=yhRXF@cDP?MQrc6#xl{prM+1gWu^xR?f3<1JAcwr_w-PhKC2s zu*6Vb@78!(!jka43X`yT4w~XN#%yBvZE1|z%!JX@7)-d95mlW|;k1k4f)SkFFgSTj z%Q0tVkjucr6}+{dsjjI`^n+h2C=nus^VEFi&fLBtkfVtG{tz6`M~EDj;3 zVu*PX^b$=?ory3RYD0Ld3M+ew&X>7azP*F6$#iDyold8#!;5ydY$3N21u}%0qlHM3 zE|7sN@z&3h)fkQl2+FJ@w9c}qXDKsfm7#rDeB=Q!$Txrp1AiEZd@E{kNk*^o$~{qB zx)x6Lo9!WgsB^R!bHe%&L__^yyl-VVr9>PqdO9K>jaZEUWn@Yi&o5vsBko9_l8KWa z0!6&h-WZmMAR_rAgToR;edU})5@M(}177s!%l;-^6_Th8E@>iZwZHW=z6o^Ao$HS` zqK4Vw;uiKh=?JHFsh*RIOyOw%X`uHgbG>SZI2HlHCqg|}Ut4o`P4_C#n3jz!VmR(Azr2^Y=+(` zy`wy%dOj%^UR=aQ{!sw@u9CXq6~w&S`q_m!ZIupMVw90Q%Eho?(x7ri457ey_89`q zx5eUx1L;M8Yc~tU7_-^o*MTu+)59P2`iH$^A44Lj=QcWST==aH>h?<08BgQZ$Gs-q zxy9buh#b}?qew;|`xsvAGvS)yG5hxIjn(E@X^vlrm}G>CLBza;m`9;|cw@|jZj7es z>6vos)MN}1+PQN=2A;yj2$ca!TIQQ2ha;p`x(Ky#85#i8$AGY3#;U$Gmc{`@MYw$`A9RFsca?gA_xXk6CWT7L0A3+wr(iz{=F>%8JUO zuMCfj%8<-ezX&(yd!#{|h9qDNBcfKz-26gWn9unc#2dM8;$_GsyNFSSEg}F$ShPZd zj-HFvn2XX1^eGUrH09mtpxH*S>(5`xU0G^<((2e(5i0KpBkG8yu6yG;VngP8)G6m` z{pMCq{!2Zted;^Yn}6bIhh#H~Q2(v3Z=Mf&Oi2-fnaj-kVP!vreJrXFf~mGg;v-$z zrihNP5k#|db7f{GKgP>BuAK{i+|oQ@3Wwg8y?gg++ZXkli!SgS$V+TlHk*292wuJj zV3Cb}`6sO*o^%gS1XLEm!LC@*8Y{IhTRbt)bz%-eLZ`yw8K3e z_vQZ;89p*}Qeg0A8iNjl`+Q8go}Zs9qa!0_&sBS3n{VP*!ykrztcrz|DyoW~QB~D-8KZ45jFySB0UNA$}ES2nq7gs%u0KLMZpMuI1L$ zKkZ#X%TdnfRuT0IPsg!UxD4~e)j5EaKVlSEz<}Xv3P$Zazx~9^f>_W(Cqwj-231_V zG*EzqNfA*`e6Q=&CcxLwQ+ZS=M_(5$G_*d)^KF=eNKCTbz z8Li*{YD3s5zIf)y`~2KunLeZTCQ)==`B%%7zowlMzWha7(+^^cCAUf2d@QIyD^Fn< zf=KC;H)G5uCw~JPV>UVUFFM;!2XzbUuU7|kE5guxy6B8|1GmP=ZC?Ql91NZ?dgPDu zIfp@~u$V-=6_(Y+&@VpXczSB8Y#-ZRMr8EmhiR9>-ymPE9~zXQxK&0a^NVuG5`qE) zi*FK5oo4y&-ZC~eUPgvT6}J3Jys(epXs2!iM?RWz%w8e=LRQ%Q1A{Ua2X%I9EZ#6T zznCuOWTf%T+$`qeEHh7w?TWT?v2D&XOl?kvA@e!V8@v%mAe~!9psY%0kpJwl!9dJ( z!TK#^*#UcqqM@PTa?RD(#QkB6%AiCLF#(=?!*JFQ*Fq4@oQ<9X0*JbZ`XLTn29mu2 z*&8&vZ8V1bhM`|I76gZxuw2vyqD`SZDS^|H!$Np(cs zA&#~(mr8!9<90ot>!^RVhvxjM+8=FiEA3QujtEKtkRpayX~T6M7a$Z^L`6F-5r9{g z&gWyPERBs&=Okhw;5kyggvjEYj!Em8>FILf#0jN``D^stWKH2>{!(*0^X_);+^PCL zF99>JbmyWh(L>V|HT8~QYHle*gM+aQdxS%yu2*O~(HEuN5JU@QW;z8C&m(19+aj*E zJHn?IcudbfXIL38dMhKGObahZj4_)Z3nF8>hWdv+je$g4Y>F_<8&~%`&t2r69xzl8 zG8pa|Prlhr*BNi;HTL7q%uC&G9HvkhOc-a{##I?P81SnSIuAeekOW9y*|TR)^mxDu z^NZx4c?CEG)cG*fo8d$<9_MD~%dumRmLo@w>As1Gi^V7~5HUCrIJij1M&%piKI!87 zCrc7Q7;qTKgAyF0+xS@Igbc@BWngevqHV0~-m|w{cm0iJ|MfSN>#n<@?7!|t9c#;R zJui2?_HVlBmU7bzZZ0?8_=0l1{O-N#>T=ap`^xTJSC#GC$0HunQ|Dl`$}`fqo-{r& zoEMZT$K>Pg+ZA=+`$$jlk&pg#5l(&#StIZxgV3Z3Qs1uGfayfIp%Uj zk3}Sjn=&0wOqOlS#ciGE+HEIXl!10T&#iG+9>f8n2SFoA5<-}I9v$5-5yFtcLDl*8 zvPX4x?X}l;)H7Svd({8hdXIDa50q=J*{{0ZTXyfhs_ff$b=kFRx5{-S+9#r)mjQeu z3R2MI7GV*cB0U!*QfQCM5>7ozSAPg4?vLIcRS3nEk|&=h!Z()BJ^BW9T;L zI$d1v*tV$q^?c{GD+F;i@x~7ZdMh1`TYub~OA)2R*7;@+JExaB zy*4F=3(`}BI6`_-#++|zF!C0?Pdc}_uvix4qE~`)Y3hw1!i?S_Rx#6U6TA36)Igq- zK+2(A5H~jN$w)O)M`n|g2dA2{?-x$nOF%LDg6AhCbAoKQH-b)!d!9=F<)7ehKb^F;fO z28&2g+9(Q@|LQrGNoO9B>KUO=ozP$!0Tj1tn?uX^p3p*>o|y?T6m3h_Lp)W#Izc$} z0LFQRg|FOK?p4>ZALsI(+(@8F1TnmgwvjzV#7p@2ZeDmOqLt-yYHuqscP)mD>RkM= zjrK@fad!-JMVN8#(js%F&c*MC7+xC@XPFpdHaA>FdAB5!>2TbjLRFU&ci zSK*svj0E;2PmA%1C3P`svfB%YzR-R31Kj zxEwontQ$>B?8~vO?(oA$!&p9Y_(*y5(MRJ0rwG2Wv29@l@-{!;s%M>2 z>QJ|xdx?(2A9b=#M(tR6_~FALbXJsJik|j`!ApLD@`&Y>xu|~_n&geE#94cP;={SB zScWOyc;kVxZ|_xw<pVuOV1ngbiOUI!LYMP zSJYEd%YpOkV=y!M|9Q{5LG^Y*dCd=wLd+>6bixqPwjwr#Ksa*r#Ic~nM?(#=JSM zkyd(&AOvmfl?Wq-oked_JgAvhQT-r>uD|};a?RCy%GA_knOFM;(n8#nTfLWZ;hBkV zhz$k%*ODo*yg$Vf9y3@73bEo_8cD5a|jcRAQ@U1vlv@AuJTdVnd#{;3in-gRoS_N z`9Sn~AWmf5$v}!>L@f0yN0?zW%TS^Rht;ewO8fgHG`4M*k+n4pZH(hIkTdmbxj6OA z>%oQKQ^NQ*4+i{>ofAsaL=2^3eo-u{5aBkCeT1VN-(0%T?6Vpf_Y4jU#cFd11bPZc z-_YPlh|K;zdL)#iF!(kiuI6q-uDo}l@U0ev&fdNIB3%rX!`SbakcJRix-|`b=3%iw z#A*sgonITJ4tkjTA_H}JsN8VFff&ZP6sw%Eh{MI@wK3ISEpxeur{n%;SIz$8(YmkG zU0Eo11V*fQDDjKXryY$9Z&Te3DN5C)>aD-2!&=WO)wa{|1=V$}cU*i7S#2R+eki~6 z;xVs{g$%OpRzh?~Z>K_m7%HapL{ZbVssae1BO$u5IA69&L?fml#6HhcQ!mjQM1|^* z4f*1QM23=ZJ@)nNFkEhI`}XKbqK<1KB3xa^BZ4N{3g=ZYq<3LqzUu67fuOEN?nS_>7K@#+D@TyekpW-a<6#WGvGi;TmH$GyFyT zio?kO05DBSL_t(F#&iw*+3(ywMKC6xRtP^`>n9A@Cf=}p@@FmW_rtj#7Ec_7fu%E5 zpwxLPE6XdfKaOEGeWsk1aTdKwGLXi%k7+v+q9{IYiczj$>YO5MFbsT*D-8Z`-TSRD zHt984T3QZ6GgGuaov_ilgs?~h#ux@9!}jQX;kz#M8nBoGac3CmGPl+7re62PwkQ3| z$R?c(%c>vCWdeH!#P?h z=MYD6kpION!O51Par9)c3_1oci(JGce`Pg>R*{)YQG-*S)^h3cetb5%?>h}^V`!VX zY8nQ)>Q8ydYN34Tfn<@7oLAPW_jnevertWV>K$XBHmUjmhKxmfl#$Qv2o>rr>V`rk zxV+N%QK+0IibkMv4?Uqn5;46JsoX=`%$_~ckb(ure%!Bmj71oN8UuMC{GJfa48fb8 zo-T_LgQN*Z8_Im9e^$aH9`572Nrb4YRMqC?ia6U>io?1`eZ|H|X^) z+5m)68he?p+{-gh1kq9-lnuk2Sh}3ycSA!1@qHM+^v^1Dv=M|O>5Cp7ZCgX3bewt5 zD$aomJeVIO~aUy}~vk?6=Fk@(?M_RKKk3qg_X5<$JC^r^j2@7WF- z@!q69zWEc7j;3DaXQMjD;g5Jj7$`lIKfR7grknJVpW3Dn9(0*BBU-kN zj+B1Y1t$q5KIY3l<)q`<%L06WmHMl7O1t1gs^M3j2!~Z15kv?!>VT*z!N z`-dJPhWibxjWDDavE0W;i}@IE{0`H7iXh6c*=D|!XQhj6mYsGKF7vAP?b{d6GjrVd zokMzwPXR`LREn*98Dlmt{EjfjYZE(|1$ zMI{;Ivl^nDUtM7ptu0~TGvDIcYp*GTL#%#xw z08@@Kr4B1;6U`#^tx7`>DyB8K2H%_#!nILe!E zE9I(jQO}XsDh^qSIVal_2Vt|?AHph(Z{@0%U((KHYpXJ;yXiGcqu!R~AV=Jd%ks!S zg()gjX7Wc}#C>uZQ@b2FA882>xlb7Fo;I$r%`_7(_mcN8xSO`kwRW4PuJVNd<)n?a ze5f{GK=6}Xs@|LPItT%&04Q_ft#L#-D?I8ZX!650(m)<`NLwdR+9hGpQyCvG)%{$E za1|!|v@z05{gVQO5A}Oa^)64DA2LK-a_l2&7_P}s!Ifx(gdyQ1Q5|I;{+Q{!RbE6bC?Txyj%z)>_7_<4Q zzrBqyn-u=YFE6pe*L*mJom68VgENdxS*8dFj9HeR<%6YMtHuk)1pC~#va%HZ(%`tV z$R=tTau|XbQ!yc5#!2)zC>{BxS<&kpJv;O`;P|5cdE9v&U&tl0$vf%9xJe@iBQycT17}e%gofOW7b|C})gIu8{`PO5CxH<4jvUraT5^n6j7xL!sz# zqWw`m7{ietZ86LVTajf#o&f5Au*qYjS!Gc38^a#;!_Y03lSY7Hj8mRGA4|)8e~0C; zRX^GiPPUmQ@Jhtdb~S1A#u6S50YY1Afj2qwf`NZt`MS`Q$HlJJyUL*Dn&Wl#9WKtN zP$A8f8|kWLKpx_`(w1J#7`_;3B7N%}US$KfK*#C>Imf zdAo`+fkA?igfYWh0SrdwZ%ph;F+eW~Z%|oG0OJ>f9wP#mZ;G!lvOAd9gV97B7*shy zAA>|r=P;BJEr>PJtgJ;I^e?uY>+Qv1^vd|tHiQp?h#n@1AHqgxX%ogGMk8QwGbd*D z>`asod89`OLp{rFDAGiEVuSlCgB<6I{J3t+#@t(pnM8^}7LO1f(EQmokgiV>_Fm|V>r^?LCnVdhSI%l{f^@M2U z*`N(zxN~pZ*R-W@{16~0Ni}W!aDuvK-VNo-KJnq3VP!m1v?u1!(4L|PQ02IBy?2&b zmSM}OTsCr~l_8&fq+RtuUFbB4jC7Dk#Q)+Vb(p;~YvCBjP1;__xR_UmU_}5UI965` z%VP7Ag|b7uk!IQkWxB91E3v0G(zJP=MZ^*!g!Cyp7sb5M8K~t+ot~OJ8R0RPsQRWy zwmzq{Z`wL(!C#bJ)7DyTQI2xK|BfBw%3}&g%8qiMqC#a(jfvc;xT9uHKd)Pa~PJK;~0TRS;dN7ArLY>k*+wVygAowb&OEp{t)ilMq+tz z!p*W-jq9~X?(tDN6)g2lU6M!20Rg+Xv=HqXs>m4{9?Ta5Di4Gy_w=i6<7ndqMjPR| zz(KU7rtyaaQuyh}5BbA~%2yQ~-)Cz40*e{&ELNd}7*%1Z-Y>4hOFOmgOE}^uEtK2x zvhu5T$uVh17)ITz&Z%$OWt1mLCQqGCBB$IhK z)^rQcA3ago?t4S@RpD0!8o!H3QEEtbsg za5|T5t?jZW3voIaY2g{J^%$v9Mmp=x7_+&tATnl?!youMtb`#XyfqJlH4Fr-Ay#wZ zR{?VzQVbygFg7qOVr;$)91KY81I|4iZ%#2i7_vg|O&BIJ;t&lnbV^%{D0(_DurTPu zR#CdzMve@bMhLaeE1aAcf@=&MT_XK49EN;g0O@p03fB&+&GGR^Ryt!i4Ms1$B9tEj zjQjA9amibF-b`bN(cAFw;fKoo58M~&#J~d*9fb_MHw{VUywMFLkO*&qnEFVo9o)gz@%K$|9ZDE7{Uk!+6)HwnKP%u zI2|7!(`||~+7^Z=VKixMrL`XGTAX8>LK{I8J(Jo_t1K5{4pH_Pst}_6VHiIts88C7 z(n#Jy%qkq(H{z2z4RMd5E70P3yI>)UkvnS!|J+xIEsUx4{f%r%QB8armHZK;!@(?13^L5L7A(oe) zDdS_KWn$-cRhiPQG8$C-A5>e|s`6nFVu(A{YoGGnPq|8O;g=zSRowUMWS{DBRnJVj zz#gA?-t-?oXV1>Yi4nCGL|2H_$S-XLk(JL;wy!MT*zY`+L##0mi86?x#LaL|(nNeQ z_bDG*V@wy|r`?#%4#tEwgE3TYIOa^mJc_;?wv`64Oa&P@u>gUL6^uiAVi?|o;lwaI z-t1zyGfxBqq7F5?vS3tV*rnk{FAHhJD4v@;tGMUO)S0P>pLB;!!&+A-c z_+)q(H_C5g;KV`$G7y!CmZ62A%BpD$eIwre*X}R-_wSb>EyGe_M32HCZ^Vb93`i4U zvt_;sL%tq(;Qn&YJ$LKea+Eh>2yvN1j8bf_N&sP~BbWwM&Xje3KX2DbzYN%xt9e3% z$dSkOuI9JX={(uQ5a#Xo(C~ob>5cj$KFVt~-l#8zF`09H5FJ@w)B%1jCVL9_m@9LW z;;p?B#xTQcuHIV?9JoG)F_9kxVC{vf4gpE}B5lfFZVC573_rwxC(ZapyyRs3W-)^1 z?f<2R_N@nDL%mau*}K5-OX5T1@Nre`z)?AMt4qq$wW{Z9_U=_d=vkRn`KSz+7&fP8a~T24 zixkC?B1mms?R{~6HrzS2ITnN;R@!jcqeaLyzDt9ETwbQPcsX8J)OkcP>`(%lXAL1u z8(;GrF-)}Xw~o`%JIL@%+8V3qF(i*USWxE~(gsyvan2aCxyj#j#+XeD#u?-8G1B{F zcxP`=8osTazMG|QuARwJk5(Okk z=%9%7k|5oL5&|h_GxMM4oQrdHZqCJ-TtNY0IA z?~v)Yc{K32Ke-9VB8>dxE3G!QdAQ>RJ1qj%?3T z8REs_tZAk6ree?3eK;2m@h(iv_;y_pE{2cqH(1Z~(aT#hv2e?KFJ!)d7&zDbjUpA` z8UHWBxlF{gpc(apM$K0Jh^@|x`-_=6aqNld0zN4r5l1IB?)C)WDByAX`S`azwP<>C z|5*#(9LDkB1@p-~H^UZbz}<&F3l1ZoGM(psLFH@EK6c#B9hO1b4)l#E=e@YzS7@HC z6sV38%RGm?TxNUdS`)hWTG=l`g%R;mkp9R#&N0ym4$v*htiZoopYel!O;tYiqHWJ~ z98%5o{rJX7gZ&K&`*daYZxo-=>m2%Q*}ofU@oChB7-l54;T`uB>aRj%=89w8B@&l# z&W+3~tT8l?qyC&V^{~hC$HGFIPFsn5Ujjrf!>b(@nugjA3z@vo{onz9kzBh%nXWs;)OKhFDA-EJ;Qa(_Tp@UGq; z_gg^ku|J$op7cm=qff_x6{=2DZ^#UtuaI{Hp*j<&V`_}nw_mwBHM7}zvZpv-10MSl ze>c13h0Q_f_?7e=`+mZhppX%BqcJ}qi!5?-o|;%$fV0n!bZY~0kr2LQoOP6tYuftU z(;)bd8m_?3!BkN z*j0~uoF%NAZCU`5Uun8KqDE{6S_SO)@bHuhH$2ObH^gOq3y4`IPPtCqO|SR_DYzEPce(AAzyVu4JMnrG zh@b!S6Q?7WBmK?49X>aaDIF^(9U2xLBbrq3hgEn**VUmi_H|U8~XDL@ZGKH zUoAe`P-mNKsg>w0o&p({R6QiP1xzA6f_V*du(Lu^5Z-D^8b+;CJp~QscwEBz#%T!l zIRY*fdo3km;p%}R{RcPmJ^lUdT@j{-)v}f1DJ2EAE%CT>2P}I^>=Qp}etpS$FqlEE z(X{@$Pp4A~7i)_1^N?*j@0o0UIyh;gheY6K8Ucc$H9 z-@n21CIgYwH3=Y7uM#;Qan|TSzh3`vFVn`(B+GgbGph`BoOtebdq^u!R9a2{pz$Gp zDa${m)kL|X_DyPQ*pH3XZBd+uu1-hPp);L1KJsG_iIJBAq49UVQ60l1+9myxgn<0V zoPJ7m_)ZWJY;5Hkm1^UrL`*6dAH0S+^65|Aaqy(a$Gla?J0o|0NV$pzw1s)HH%%t^ zWQOE4K(4eqkSLH)#M>)Z2C5FFdX|IkMmzbuc%cpX*J%h;$R$Gn^m8Z>yA#~?>5_;D z68E6%bF>3mNiVyk`UPfZ-;L12Pa?s78}ceg@9cvgX7~D&i4v^Q%FPG{Nszoz{YZ~> z`wxpt#W>Lk6ILxTaPZH2!&dj3hDM%)?4!FYGBVNkIrBUq?jHZ>kdY`#0Mh3Y^ z-0_uS_I?_ZqnY`n<^1mOU>ANq>AGqJR`)`7O~{{@gnJ`86mZfsxt40|*dg7{*f?q{fDTl9oDwMf`It&+GNuT*^RYN^**fTisea*6JUo7@4nq2~^<3H^+OLdr(O%gzh2u!OUip=y@q@8; zWj~Lf4_AGsU|6k{M9&7>_iW4v=&q;1839TSIS|(`-6opRKfkPL!zA3B7^8W$Qao`C zrwRmc3^5QWWg>uZ$082j(e9|8Ehiq9w%hgoMwYwI7`{BK$Q9UsRTlE5J{z+A@!DHx zIp~00chYHJJyhAxl%kpX)wm@0xe>PEguh$gXGr8@u3Kx|w;{%l{Lp)LLR2jLX9^WV z{a}AakjVd4)ZZ)em~lo*#v#;0$7ZeSwaHk}Pdds8M5LaZ7)xw=C~HJHJLtIddbK8b z7%{|KVa$~pxC<`BS>9LRvDc3$GjeOIMOKt3mm+4pOG!yQMX{EhKZ9-JI_5NotFK1Q z`96QS$!xFcYde$ib~j&9pjF@zbRAFb-+TsKA8qdCGYuA6~jV7+eOryxj)iMNg)j0joq@I z^-b^S()Z_H(NJv^e`t))q?pl3i%S<>PQXY_fsaQF^x9pS>unoESg5kw|IuN~pKF{_G~N zsU|t%*i6scNN-zlf)dFLt9Es{`sQMpn$_i)X$ShVl8^#Q`fy&LRH%C5bSkf_vFxg@ zr>u5CslS?~%s_wstx?o{_1dvox8+mDA1s0en;-du??LocVmhc09l{%luM>od#`UYo5g`|xW2^|9kplZ(^Ylam^r~J)#?JcSUG!^W0IQH-je@(~mMc5{ooO-#6>VUb` zs5ClMby4;r-vUErwz4PAH_Vh9!1NGOQ=wJ_zez1P08;XAqVfL_{cHUG8Pk7Q>M!Z}N22~wDF5iw|0{Dc5IFVW>9KC28cm+@ zrmm@AL<7*yI34a>l3u0(&_C~!!T%TTyxIG7Kc9-`E-?SABWr?zx!;=(mo|h!H~NQD zn>}(Q*vW=2;j`vhgIG!<)Q-z3VP4`pBSETScagR^w5iU3-Ck}ef_%%k+ainQhpuD~ zCZmWt4G}2bZYPQJB8&1!2S(hOKwCh+z6uXT7_$g2yy<}Tt0PS$D7z-Xv1v;9g7LtD8foj+%18na(53~(2D4Mykd3=9_c~} zqh1N*dd?l=kyV4+SoqG5&uA@gX5y)J;YH46yg5rg3M%lEs9V=y%>M{LU{)W~DIek$ z(r=jUs8XlU>_@DfM4lUh?1Q{HiMexsmE+E;K{Gc4mdwixnXG_fLR}^A%bJp3BPWeY zGccYOuo1rBIhRwOYRKJ|rP!L$2=N(m;O8SZM3hxSxxa9RlaMnr3<#4vL{T-^f3OCdRNM;c+azT>09ntfWDHe2Dn;+@EF zI$GXvYlb#=+E;mP=K~)FNpxx7*=|4@gPb#+Cz+O1m%Vv9wlKWwTeCUY9!^~|p=o}8 z($;r!{7HBZW0ndgE_GAWv{sy@qt7x}#UU8<)<>|dJS=lMBGHNa_LKovTG_KsAZQl zJYo$=>18jjVf9uslq$Y`>*F$Zz?`CZ5Ob9Gxsl>ko}@=9LP8y(TQ6K5u5uo*A`Nw{ z?hlN9S`PO@^p5%|HU=%R`&BWMocXoxIQAOSkCm3p^U%4P@1}*V<3`r`-u-Dvw#$?^ zT_seF(do$;mmKdo=+76EsxD6;w)cOG?mlPK){$2aEi0=cYuc7s&jQ$G=9tObI-IU@ z?mgDdXQy9%x8Dq>)e#|&9mjT3)|BcdA^8d!@*!xGU>4CyW*W|Aq2=)L+Pj?-wt(1f zME^Pr$U}(u9$+WrzDqUcT{WUjH&Sv=CVm_bp%bS2ITgy(->7HGU)*(N&e>Ad*z3s{ zbB?{ntHo(ON@4gewsURlVg~u77Ist*iGgjeG8#l^re0>_o9HwF_EsSUOB~;}c5>Ms zqTejLv-KT}xJB^)m!3ul)*Q7hFbqo6V?5(kq2_L8L=(k*75xxq%oCh&R$nj2m6bNh zU?6AbpOT|-tE<-6feRqljy*&T%l#PH9mHU7}CsWUv9S7 zwIc2y#m5oyFbmjYj@@#01J4kv`f0+!jDsd;5!6O0Wuva}lL7FI@Rs0Gk@)r|2f9*1qw^*1|M^M9v?3n#$=ituQGy zvOC-(FHm{QPgVZb1xg-1F8la)5F$u{+3tSD7FO$~9diGI)~SnF8m&@MTDcL%o?xtn z&uXbYUL%#NeU0gSEd2WuGYtzE%Xm%2kZFj1&;DLs-aW6#)P$*g4$|2qBt~_+>!_!- zyjfRWSYlp00iSATL?=Db9e2dzn?pT<-Zd#P0T)g`a?jK2()ipE$2Gs^CmnG>5qEIj zMx|n4B;|Fvs<6wq4xgisNjdCU0rdN(c|I2lUm{e*#xA8-k#76w$-Ab?k(JT!%dr>f zLApHZ#rAagZ`>O11hrlnH34c|`UA1=O20X0xcEF)iJV1a;z9bj-9GZ^-rma-jFafb zG2NtkH;X89?Bvdu8pQ4ZeIvxat2eb=vr$=?A7dWWR+Y2MnpDDjH32pPL34y@eO}dS`5|F$<{L-rA*ATUsBse2haR_ zU_|&avlVxZTnO~v)+T-;wd=TZluqupkAXdZSdnrpG^AQgPOG7OY-e$-bh&{OMm10p z8J8%hu2cKy_eXw+!z?FiJh5m=#nyNEvKXuij<1@>H|dypa2lsO$)g1Xjy2v%LO0H~ zzDL7E^1eC3wwRZ8OaMknhl}sI=IaTJ5eAv5*}k)Co61B@jZ>9XeTB{HxfiKqU|BSZ zIZ3~C3$V`>sGW&#w}?;POB`|5u<;GsRZR_H2eU@Q0tpw0a-|T|9s_n~K?#It$`U<789~YB6~o^=M7Db2#~{-zm-` z1dlJgxM`(Et1haaD?%!3T3I8Nqkf=yR7Ri|w8slj<{7zr4UR=JfnLX!bGQ5uH>=6Z^!?yN%aXURxeWLc^sCApb5PTd^76ffibp;I~pGs(h|(EXKTb;PAe zYN6Kh5eK;#D6^oF0ra8vm2{Bf7IR+}5L2Iw*;B ze2@nX%z47)Sz@jbIhhmg&kt(MvPH)p!PpvpP>1Pwq-(Ee~CDXZPZD?yPcKz!(>M>1Z6X zno=kosd$V!wBJP;{j(fk5r4)BMN8Cd6*Wn9%$fg;?TFF>EJ{$Z?K;RpmXEX%Lmi$V zJr#{e!K;$!@cV-G`?FERj>pIdYfPqM-Onu}NNDG|r z)iMQMw<|=1dx&1wA-bOJ20YIrU}oD5fUbMQKcOQN2&g^czjGH!yaL(k(*Rm6Yn_zj z9ujj?5dds$*)Mw?bvb7a0}q}w*wB*YZi%|7>{;QmUy`AWYe30MOs4eSTP-{z>9AJ- z695GS+ewNTyw*&ej*)pjX1Rxb7mUzu+m5Z15^h~-IeYSOX)=KjvD~<`$jB9Ge!H=? zc@Yk1>~uF6xs{& f4Hl#_c>C`-AGxUihvk!BfZz42W>?CL?ne9vR`pxq diff --git a/web/model-manager.js b/web/model-manager.js index ef310d2..e99ae12 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -1755,12 +1755,13 @@ class ModelGrid { const widgetIndex = ModelGrid.modelWidgetIndex(nodeType); const target = selectedNode?.widgets[widgetIndex]?.element; if (target && target.type === "textarea") { + // TODO: If the node has >1 textareas, the textarea element must be selected target.value = ModelGrid.insertEmbeddingIntoText(target.value, embeddingFile, removeEmbeddingExtension); success = true; } } if (!success) { - console.warn("Try selecting a node before adding the embedding."); + window.alert("No selected nodes have a text area!"); } event.stopPropagation(); } @@ -1898,10 +1899,10 @@ class ModelGrid { // TODO: separate text and model logic; getting too messy // TODO: fallback on button failure to copy text? const canShowButtons = modelNodeType[modelType] !== undefined; + const shouldShowTryOpenModelUrl = canShowButtons && settingsElements["model-show-open-model-url-button"].checked; + const showLoadWorkflowButton = canShowButtons && settingsElements["model-show-load-workflow-button"].checked; const showAddButton = canShowButtons && settingsElements["model-show-add-button"].checked; const showCopyButton = canShowButtons && settingsElements["model-show-copy-button"].checked; - const showLoadWorkflowButton = canShowButtons && settingsElements["model-show-load-workflow-button"].checked; - const shouldShowTryOpenModelUrl = canShowButtons && settingsElements["model-show-open-model-url-button"].checked; const strictDragToAdd = settingsElements["model-add-drag-strict-on-field"].checked; const addOffset = parseInt(settingsElements["model-add-offset"].value); const showModelExtension = settingsElements["model-show-label-extensions"].checked; @@ -1925,35 +1926,20 @@ class ModelGrid { const searchPath = item.path; const path = SearchPath.systemPath(searchPath, searchSeparator, systemSeparator); let actionButtons = []; - if (showAddButton && !(modelType === "embeddings" && !navigator.clipboard)) { + if (shouldShowTryOpenModelUrl) { actionButtons.push( new ComfyButton({ - icon: "content-copy", - tooltip: "Copy model to clipboard", + icon: "open-in-new", + tooltip: "Attempt to open model url page in a new tab.", classList: "comfyui-button icon-button model-button", - action: (e) => ModelGrid.#copyModelToClipboard( - e, - modelType, - path, - removeEmbeddingExtension, - ), - }).element, - ); - } - if (showCopyButton) { - actionButtons.push( - new ComfyButton({ - icon: "plus-box-outline", - tooltip: "Add model to node grid", - classList: "comfyui-button icon-button model-button", - action: (e) => ModelGrid.#addModel( - e, - modelType, - path, - removeEmbeddingExtension, - addOffset, - ), - }).element, + action: async (e) => { + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const success = await tryOpenModelUrl(searchPath); + comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); + button.disabled = false; + }, + }).element ); } if (showLoadWorkflowButton) { @@ -1974,20 +1960,35 @@ class ModelGrid { }).element, ); } - if (shouldShowTryOpenModelUrl) { + if (showAddButton) { actionButtons.push( new ComfyButton({ - icon: "open-in-new", - tooltip: "Attempt to open model url page in a new tab.", + icon: "plus-box-outline", + tooltip: "Add model to node grid", classList: "comfyui-button icon-button model-button", - action: async (e) => { - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const success = await tryOpenModelUrl(searchPath); - comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); - button.disabled = false; - }, - }).element + action: (e) => ModelGrid.#addModel( + e, + modelType, + path, + removeEmbeddingExtension, + addOffset, + ), + }).element, + ); + } + if (showCopyButton && !(modelType === "embeddings" && !navigator.clipboard)) { + actionButtons.push( + new ComfyButton({ + icon: "content-copy", + tooltip: "Copy model to clipboard", + classList: "comfyui-button icon-button model-button", + action: (e) => ModelGrid.#copyModelToClipboard( + e, + modelType, + path, + removeEmbeddingExtension, + ), + }).element, ); } const infoButtons = [ From 84b1e60df0757482eb5b9136c351aff0293b201c Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 17:08:44 -0400 Subject: [PATCH 09/59] Added check for missing preview uri. --- __init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/__init__.py b/__init__.py index b8e1da4..f548707 100644 --- a/__init__.py +++ b/__init__.py @@ -417,6 +417,8 @@ def get_auto_thumbnail_format(original_format): @server.PromptServer.instance.routes.get("/model-manager/preview/get") async def get_model_preview(request): uri = request.query.get("uri") + if uri is None: + raise ValueError("Missing uri path!") quality = 75 response_image_format = request.query.get("image-format", None) if isinstance(response_image_format, str): From b9e6d3af0b2cb0910f3da5316a6781ff897fe2de Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 17:18:31 -0400 Subject: [PATCH 10/59] Added debug in JS for preview. --- __init__.py | 4 +--- web/model-manager.js | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/__init__.py b/__init__.py index f548707..a265d54 100644 --- a/__init__.py +++ b/__init__.py @@ -416,9 +416,7 @@ def get_auto_thumbnail_format(original_format): @server.PromptServer.instance.routes.get("/model-manager/preview/get") async def get_model_preview(request): - uri = request.query.get("uri") - if uri is None: - raise ValueError("Missing uri path!") + uri = request.query.get("uri", "no-preview") # BUG: reported that uri is None quality = 75 response_image_format = request.query.get("image-format", None) if isinstance(response_image_format, str): diff --git a/web/model-manager.js b/web/model-manager.js index e99ae12..fbead3b 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -277,6 +277,7 @@ function imageUri(imageSearchPath = undefined, dateImageModified = undefined, wi return uri; } const PREVIEW_NONE_URI = imageUri(); +console.log(PREVIEW_NONE_URI); const PREVIEW_THUMBNAIL_WIDTH = 320; const PREVIEW_THUMBNAIL_HEIGHT = 480; From 7c5a4869b76b627ce90e7ed85948071f5d548f6e Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 17:21:35 -0400 Subject: [PATCH 11/59] Tweak --- web/model-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index fbead3b..35330f1 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -277,7 +277,7 @@ function imageUri(imageSearchPath = undefined, dateImageModified = undefined, wi return uri; } const PREVIEW_NONE_URI = imageUri(); -console.log(PREVIEW_NONE_URI); +console.log(`PREVIEW_NONE_URI: ${PREVIEW_NONE_URI}`); const PREVIEW_THUMBNAIL_WIDTH = 320; const PREVIEW_THUMBNAIL_HEIGHT = 480; From d503dbb510a62259318d34de7e26bcdbab1788a0 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 17:47:25 -0400 Subject: [PATCH 12/59] Fix URI model path requests for opening model url. --- web/model-manager.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index 35330f1..d5bd037 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -140,11 +140,13 @@ async function loadWorkflow(url) { } /** - * @param {string} modelPath + * @param {string} modelSearchPath * @returns {Promise} */ -async function tryOpenModelUrl(modelPath) { - const webUrlResponse = await comfyRequest(`/model-manager/model/info/web-url?path=${modelPath}`); +async function tryOpenModelUrl(modelSearchPath) { + const encodedPath = encodeURIComponent(modelSearchPath); + const requestUrl = `/model-manager/model/info/web-url?path=${encodedPath}`; + const webUrlResponse = await comfyRequest(requestUrl); try { const modelUrl = new URL(webUrlResponse["url"]); window.open(modelUrl, '_blank').focus(); @@ -2546,7 +2548,7 @@ class ModelInfo { action: async (e) => { const [button, icon, span] = comfyButtonDisambiguate(e.target); button.disabled = true; - const success = await tryOpenModelUrl(path); + const success = await tryOpenModelUrl(searchPath); comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); button.disabled = false; }, From 632e02a83d8149716c6f4da63a58065daae81d69 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 19:10:04 -0400 Subject: [PATCH 13/59] Disable info button while awaiting. --- web/model-manager.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index d5bd037..2c6e9b2 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -1999,7 +1999,12 @@ class ModelGrid { icon: "information-outline", tooltip: "View model information", classList: "comfyui-button icon-button model-button", - action: async() => { await showModelInfo(searchPath) }, + action: async(e) => { + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + await showModelInfo(searchPath); + button.disabled = false; + }, }).element, ]; const dragAdd = (e) => ModelGrid.#dragAddModel( From 032b7052e01ad7d8e6a0f709948f2d27231c134c Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 19:19:53 -0400 Subject: [PATCH 14/59] Remove debug. --- web/model-manager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index 2c6e9b2..386fa4e 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -279,7 +279,6 @@ function imageUri(imageSearchPath = undefined, dateImageModified = undefined, wi return uri; } const PREVIEW_NONE_URI = imageUri(); -console.log(`PREVIEW_NONE_URI: ${PREVIEW_NONE_URI}`); const PREVIEW_THUMBNAIL_WIDTH = 320; const PREVIEW_THUMBNAIL_HEIGHT = 480; From b16c2e853fdbb4f20b7b5b6b149172ef8d005973 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 19:48:28 -0400 Subject: [PATCH 15/59] Debug statement for invalid preview. --- __init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index a265d54..778ec6a 100644 --- a/__init__.py +++ b/__init__.py @@ -416,7 +416,10 @@ def get_auto_thumbnail_format(original_format): @server.PromptServer.instance.routes.get("/model-manager/preview/get") async def get_model_preview(request): - uri = request.query.get("uri", "no-preview") # BUG: reported that uri is None + uri = request.query.get("uri", None) + if uri is None: # This should never happen + print(f"Invalid uri! Request url: {request.url}") + uri = "no-preview" quality = 75 response_image_format = request.query.get("image-format", None) if isinstance(response_image_format, str): From 944071e966e4defb5713489cf7c2a8a390976e1b Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 20:46:27 -0400 Subject: [PATCH 16/59] Tweak path. --- __init__.py | 11 ++++++++--- web/model-manager.js | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/__init__.py b/__init__.py index 778ec6a..cd733ac 100644 --- a/__init__.py +++ b/__init__.py @@ -25,7 +25,7 @@ import folder_paths comfyui_model_uri = folder_paths.models_dir -extension_uri = os.path.dirname(__file__) +extension_uri = os.path.dirname(os.path.abspath(__file__)) config_loader_path = os.path.join(extension_uri, 'config_loader.py') config_loader_spec = importlib.util.spec_from_file_location('config_loader', config_loader_path) @@ -414,11 +414,16 @@ def get_auto_thumbnail_format(original_format): return "JPEG" # default fallback +invalid_url_tracker = False + + @server.PromptServer.instance.routes.get("/model-manager/preview/get") async def get_model_preview(request): uri = request.query.get("uri", None) - if uri is None: # This should never happen - print(f"Invalid uri! Request url: {request.url}") + if uri is None: # BUG: this should never happen + if not invalid_url_tracker: + print(f"Invalid uri! Request url: {request.url}") + invalid_url_tracker = True uri = "no-preview" quality = 75 response_image_format = request.query.get("image-format", None) diff --git a/web/model-manager.js b/web/model-manager.js index 386fa4e..80105cf 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -665,7 +665,8 @@ class ImageSelect { case this.#PREVIEW_NONE: return PREVIEW_NONE_URI; } - return ""; + console.warn(`Invalid preview select type: ${value}`); + return PREVIEW_NONE_URI; } /** @returns {void} */ From b6562851e1f5765b3e7f20f788c6237e12a7a5f9 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 20:47:20 -0400 Subject: [PATCH 17/59] Undo --- __init__.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/__init__.py b/__init__.py index cd733ac..a1fb5e8 100644 --- a/__init__.py +++ b/__init__.py @@ -414,16 +414,11 @@ def get_auto_thumbnail_format(original_format): return "JPEG" # default fallback -invalid_url_tracker = False - - @server.PromptServer.instance.routes.get("/model-manager/preview/get") async def get_model_preview(request): uri = request.query.get("uri", None) if uri is None: # BUG: this should never happen - if not invalid_url_tracker: - print(f"Invalid uri! Request url: {request.url}") - invalid_url_tracker = True + #print(f"Invalid uri! Request url: {request.url}") uri = "no-preview" quality = 75 response_image_format = request.query.get("image-format", None) From 1c83e1e028ae46a46a1640b5875c75c3b4237552 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:00:15 -0400 Subject: [PATCH 18/59] Remove type hint --- __init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index a1fb5e8..b2d125b 100644 --- a/__init__.py +++ b/__init__.py @@ -243,7 +243,7 @@ def get_def_headers(url=""): return def_headers -def civitai_get_model_info(sha256_hash: str): +def civitai_get_model_info(sha256_hash): url_api_hash = r"https://civitai.com/api/v1/model-versions/by-hash/" + sha256_hash hash_response = requests.get(url_api_hash) if hash_response.status_code != 200: From ccff0ba7cae06934fe7ccdb8cecb922e73457160 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sun, 8 Sep 2024 03:25:28 -0400 Subject: [PATCH 19/59] Added shallow copy to path --- web/model-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index 80105cf..195f596 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -1926,7 +1926,7 @@ class ModelGrid { ), draggable: false, }); - const searchPath = item.path; + const searchPath = item.path.slice(); // shallow copy const path = SearchPath.systemPath(searchPath, searchSeparator, systemSeparator); let actionButtons = []; if (shouldShowTryOpenModelUrl) { From 4831a4374bcf44b3c33744a03729fcfb0ea0d953 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sun, 8 Sep 2024 04:36:00 -0400 Subject: [PATCH 20/59] Added raise error on get web-url when path is empty. --- __init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index b2d125b..a5a2fde 100644 --- a/__init__.py +++ b/__init__.py @@ -1101,12 +1101,12 @@ async def get_model_info(request): async def get_model_web_url(request): model_path = request.query.get("path", None) if model_path is None: - web.json_response({ "url": "" }) + raise ValueError("Missing model path!") model_path = urllib.parse.unquote(model_path) abs_path, model_type = search_path_to_system_path(model_path) if abs_path is None: - web.json_response({ "url": "" }) + raise ValueError("Invalid model path!") sha256_hash = hash_file(abs_path) url = search_web_for_model_url(sha256_hash) From ce93156460ea0daf8056677c41f664128161e100 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sun, 8 Sep 2024 04:37:41 -0400 Subject: [PATCH 21/59] Enable debug statement. --- __init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index a5a2fde..25dd39e 100644 --- a/__init__.py +++ b/__init__.py @@ -418,7 +418,7 @@ def get_auto_thumbnail_format(original_format): async def get_model_preview(request): uri = request.query.get("uri", None) if uri is None: # BUG: this should never happen - #print(f"Invalid uri! Request url: {request.url}") + print(f"Invalid uri! Request url: {request.url}") uri = "no-preview" quality = 75 response_image_format = request.query.get("image-format", None) From cff4c96ef37bd0375c301dce9be735b41b9acb3f Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Mon, 9 Sep 2024 02:17:39 -0400 Subject: [PATCH 22/59] Added fallback for open model url to deal with popup block or ad-blockers. - Moved Model Manager z-index from 2000 to 99 (1 below modals). --- web/model-manager.css | 2 +- web/model-manager.js | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/web/model-manager.css b/web/model-manager.css index a205b26..787758f 100644 --- a/web/model-manager.css +++ b/web/model-manager.css @@ -10,7 +10,7 @@ position: fixed; overflow: hidden; width: 100%; - z-index: 2000; + z-index: 99; /*needs to be below dialog modal*/ /*override comfy-modal settings*/ border-radius: 0; diff --git a/web/model-manager.js b/web/model-manager.js index 195f596..2913314 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -15,9 +15,16 @@ function clamp(x, min, max) { function comfyRequest(url, options = undefined) { return new Promise((resolve, reject) => { api.fetchApi(url, options) - .then((response) => response.json()) - .then(resolve) - .catch(reject); + .then((response) => { + if (!response.ok) { + reject(new Error(`HTTP error ${response.status}: ${response.statusText}`)); + } else { + response.json() + .then(resolve) + .catch(error => reject(new Error(`Failed to parse JSON: ${error.message}`))); + } + }) + .catch(error => reject(new Error(`Request error: ${error.message}`))); }); } @@ -147,13 +154,35 @@ async function tryOpenModelUrl(modelSearchPath) { const encodedPath = encodeURIComponent(modelSearchPath); const requestUrl = `/model-manager/model/info/web-url?path=${encodedPath}`; const webUrlResponse = await comfyRequest(requestUrl); + let modelUrl; try { - const modelUrl = new URL(webUrlResponse["url"]); - window.open(modelUrl, '_blank').focus(); + modelUrl = new URL(webUrlResponse["url"]); } catch (exception) { return false; } + try { + window.open(modelUrl, '_blank').focus(); + } + catch (exception) { + // browser or ad-blocker blocking opening new window + app.ui.dialog.show($el("span", + [ + $el("p", { + style: { color: "var(--input-text)" }, + }, [modelSearchPath]), + $el("a", { + href: modelUrl, + target: "_blank", + }, [ + $el("span", [ + modelUrl, + $el("i.mdi.mdi-open-in-new"), + ]) + ]), + ] + )); + } return true; } From 5521e696e50d31a64efd96739dc2a42b7cd2628f Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Mon, 9 Sep 2024 03:01:09 -0400 Subject: [PATCH 23/59] Fixed modal `z-index` for old and beta menu. --- web/model-manager.css | 6 +++++- web/model-manager.js | 11 +++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/web/model-manager.css b/web/model-manager.css index 787758f..913f286 100644 --- a/web/model-manager.css +++ b/web/model-manager.css @@ -10,7 +10,7 @@ position: fixed; overflow: hidden; width: 100%; - z-index: 99; /*needs to be below dialog modal*/ + z-index: 2000; /*needs to be below the dialog modal element*/ /*override comfy-modal settings*/ border-radius: 0; @@ -23,6 +23,10 @@ touch-action: manipulation; } +.model-manager .model-manager-dialog { + z-index: 2001; /*needs to be above the model manager element*/ +} + .model-manager .comfy-modal-content { width: 100%; gap: 16px; diff --git a/web/model-manager.js b/web/model-manager.js index 2913314..e452285 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -164,9 +164,9 @@ async function tryOpenModelUrl(modelSearchPath) { try { window.open(modelUrl, '_blank').focus(); } - catch (exception) { + catch (exception) { // browser or ad-blocker blocking opening new window - app.ui.dialog.show($el("span", + modelManagerDialog.show($el("span", [ $el("p", { style: { color: "var(--input-text)" }, @@ -4951,12 +4951,19 @@ class ModelManager extends ComfyDialog { /** @type {ModelManager | undefined} */ let instance; +/** @type {ComfyDialog | undefined} */ +let modelManagerDialog; + /** * @returns {ModelManager} */ function getInstance() { if (!instance) { instance = new ModelManager(); + + modelManagerDialog = new ComfyDialog(); + modelManagerDialog.element.classList.add("model-manager-dialog"); + instance.element.appendChild(modelManagerDialog.element); } return instance; } From 35878d85147c374821098188b76aa1efff8927d8 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Tue, 10 Sep 2024 00:30:44 -0400 Subject: [PATCH 24/59] Added dynamic routing to REST API: `preview/get/{path}` and `model/info/{path}`. - Fixed issue interacting with Imagus stripping out query parameters and getting invalid preview url. Fixed by using dynamic routing. - Changed return format of preview string to no longer encode the uri on the server. There were issues with how python's urllib.parse.quote and .quote_plus functions interacted with slash and space characters. --- __init__.py | 33 ++++++++++++++++++--------------- web/model-manager.js | 41 ++++++++++++++++++++++------------------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/__init__.py b/__init__.py index 25dd39e..a98f30e 100644 --- a/__init__.py +++ b/__init__.py @@ -414,9 +414,9 @@ def get_auto_thumbnail_format(original_format): return "JPEG" # default fallback -@server.PromptServer.instance.routes.get("/model-manager/preview/get") +@server.PromptServer.instance.routes.get("/model-manager/preview/get/{uri}") async def get_model_preview(request): - uri = request.query.get("uri", None) + uri = request.match_info["uri"] if uri is None: # BUG: this should never happen print(f"Invalid uri! Request url: {request.url}") uri = "no-preview" @@ -800,8 +800,8 @@ async def get_model_list(request): if image is not None: raw_post = os.path.join(model_type, str(base_path_index), rel_path, image) item["preview"] = { - "path": urllib.parse.quote_plus(raw_post), - "dateModified": urllib.parse.quote_plus(str(image_modified)), + "path": raw_post, + "dateModified": str(image_modified), } model_items.append(item) @@ -975,13 +975,13 @@ def bytes_to_size(total_bytes): return "{:.2f}".format(total_bytes / (1 << (i * 10))) + " " + units[i] -@server.PromptServer.instance.routes.get("/model-manager/model/info") +@server.PromptServer.instance.routes.get("/model-manager/model/info/{path}") async def get_model_info(request): result = { "success": False } - model_path = request.query.get("path", None) + model_path = request.match_info["path"] if model_path is None: - result["alert"] = "Missing model path!" + result["alert"] = "Invalid model path!" return web.json_response(result) model_path = urllib.parse.unquote(model_path) @@ -1010,8 +1010,8 @@ async def get_model_info(request): preview_path, _ = split_valid_ext(model_path, model_extensions) preview_modified = pathlib.Path(maybe_preview).stat().st_mtime_ns info["Preview"] = { - "path": urllib.parse.quote_plus(preview_path + extension), - "dateModified": urllib.parse.quote_plus(str(preview_modified)), + "path": preview_path + extension, + "dateModified": str(preview_modified), } break @@ -1096,22 +1096,25 @@ async def get_model_info(request): result["notes"] = notes return web.json_response(result) +@server.PromptServer.instance.routes.get("/model-manager/model/web-url") +async def get_model_info(request): + result = { "success": False } -@server.PromptServer.instance.routes.get("/model-manager/model/info/web-url") -async def get_model_web_url(request): model_path = request.query.get("path", None) if model_path is None: - raise ValueError("Missing model path!") + result["alert"] = "Invalid model path!" + return web.json_response(result) model_path = urllib.parse.unquote(model_path) abs_path, model_type = search_path_to_system_path(model_path) if abs_path is None: - raise ValueError("Invalid model path!") + result["alert"] = "Invalid model path!" + return web.json_response(result) sha256_hash = hash_file(abs_path) - url = search_web_for_model_url(sha256_hash) + web_url = search_web_for_model_url(sha256_hash) - return web.json_response({ "url": url }) + return web.json_response({ "url": web_url }) @server.PromptServer.instance.routes.get("/model-manager/system-separator") diff --git a/web/model-manager.js b/web/model-manager.js index e452285..b6a8d02 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -137,9 +137,8 @@ function elementFromDragEvent(event) { * @param {string} url */ async function loadWorkflow(url) { - const uri = (new URL(url)).searchParams.get("uri"); - const fileNameIndex = Math.max(uri.lastIndexOf("/"), uri.lastIndexOf("\\")) + 1; - const fileName = uri.substring(fileNameIndex); + const fileNameIndex = Math.max(url.lastIndexOf("/"), url.lastIndexOf("\\")) + 1; + const fileName = url.substring(fileNameIndex); const response = await fetch(url); const data = await response.blob(); const file = new File([data], fileName, { type: data.type }); @@ -152,7 +151,7 @@ async function loadWorkflow(url) { */ async function tryOpenModelUrl(modelSearchPath) { const encodedPath = encodeURIComponent(modelSearchPath); - const requestUrl = `/model-manager/model/info/web-url?path=${encodedPath}`; + const requestUrl = `/model-manager/model/web-url?path=${encodedPath}`; const webUrlResponse = await comfyRequest(requestUrl); let modelUrl; try { @@ -282,28 +281,32 @@ class SearchPath { } /** - * @param {string | undefined} [searchPath=undefined] + * @param {string | undefined} [imageUriSearchPath=undefined] * @param {string | undefined} [dateImageModified=undefined] * @param {string | undefined} [width=undefined] * @param {string | undefined} [height=undefined] * @param {string | undefined} [imageFormat=undefined] * @returns {string} */ -function imageUri(imageSearchPath = undefined, dateImageModified = undefined, width = undefined, height = undefined, imageFormat = undefined) { - const path = imageSearchPath ?? "no-preview"; - const date = dateImageModified; - let uri = `/model-manager/preview/get?uri=${path}`; +function imageUri(imageUriSearchPath = undefined, dateImageModified = undefined, width = undefined, height = undefined, imageFormat = undefined) { + const params = []; if (width !== undefined && width !== null) { - uri += `&width=${width}`; + params.push(`width=${width}`); } if (height !== undefined && height !== null) { - uri += `&height=${height}`; + params.push(`height=${height}`); } - if (date !== undefined && date !== null) { - uri += `&v=${date}`; + if (dateImageModified !== undefined && dateImageModified !== null) { + params.push(`v=${dateImageModified}`); } if (imageFormat !== undefined && imageFormat !== null) { - uri += `&image-format=${imageFormat}`; + params.push(`image-format=${imageFormat}`); + } + + const path = imageUriSearchPath ?? "no-preview"; + const uri = `/model-manager/preview/get/${path}`; + if (params.length > 0) { + return uri + '?' + params.join('&'); } return uri; } @@ -1947,8 +1950,8 @@ class ModelGrid { const previewThumbnail = $el("img.model-preview", { loading: "lazy", /* `loading` BEFORE `src`; Known bug in Firefox 124.0.2 and Safari for iOS 17.4.1 (https://stackoverflow.com/a/76252772) */ src: imageUri( - previewInfo?.path, - previewInfo?.dateModified, + previewInfo?.path ? encodeURIComponent(previewInfo.path) : undefined, + previewInfo?.dateModified ? encodeURIComponent(previewInfo.dateModified) : undefined, PREVIEW_THUMBNAIL_WIDTH, PREVIEW_THUMBNAIL_HEIGHT, previewThumbnailFormat, @@ -2440,7 +2443,7 @@ class ModelInfo { */ async update(searchPath, updateModels, searchSeparator) { const path = encodeURIComponent(searchPath); - const [info, metadata, tags, noteText] = await comfyRequest(`/model-manager/model/info?path=${path}`) + const [info, metadata, tags, noteText] = await comfyRequest(`/model-manager/model/info/${path}`) .then((result) => { const success = result["success"]; const message = result["alert"]; @@ -2552,8 +2555,8 @@ class ModelInfo { const previewSelect = this.previewSelect; const defaultUrl = previewSelect.elements.defaultUrl; if (info["Preview"]) { - const imagePath = info["Preview"]["path"]; - const imageDateModified = info["Preview"]["dateModified"]; + const imagePath = encodeURIComponent(info["Preview"]["path"]); + const imageDateModified = encodeURIComponent(info["Preview"]["dateModified"]); defaultUrl.dataset.noimage = imageUri(imagePath, imageDateModified); } else { From f15c5f907172a44f9d283aac05a0822915f4a2d8 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:34:29 -0400 Subject: [PATCH 25/59] Save model info in `json` file beside model. --- __init__.py | 39 +++++++++++++++++++++++++++++++++------ web/model-manager.js | 3 +++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/__init__.py b/__init__.py index a98f30e..e82f400 100644 --- a/__init__.py +++ b/__init__.py @@ -60,7 +60,8 @@ preview_extensions = ( # TODO: JavaScript does not know about this (x2 states) image_extensions + # order matters stable_diffusion_webui_civitai_helper_image_extensions ) -model_info_extension = ".txt" +model_notes_extension = ".txt" +model_info_extension = ".json" #video_extensions = (".avi", ".mp4", ".webm") # TODO: Requires ffmpeg or cv2. Cache preview frame? def split_valid_ext(s, *arg_exts): @@ -260,6 +261,15 @@ def civitai_get_model_info(sha256_hash): return model_response.json() +def search_web_for_model_info(sha256_hash): + model_info = civitai_get_model_info(sha256_hash) + if len(model_info) > 0: return model_info + + # TODO: search other websites + + return {} + + def search_web_for_model_url(sha256_hash): model_info = civitai_get_model_info(sha256_hash) if len(model_info) > 0: @@ -1046,10 +1056,10 @@ async def get_model_info(request): training_comment if training_comment != "None" else "" ).strip() - info_text_file = abs_name + model_info_extension + notes_file = abs_name + model_notes_extension notes = "" - if os.path.isfile(info_text_file): - with open(info_text_file, 'r', encoding="utf-8") as f: + if os.path.isfile(notes_file): + with open(notes_file, 'r', encoding="utf-8") as f: notes = f.read() if metadata is not None: @@ -1136,6 +1146,7 @@ async def download_model(request): result["alert"] = "Invalid save path!" return web.json_response(result) + # download model download_uri = formdata.get("download") if download_uri is None: result["alert"] = "Invalid download url!" @@ -1159,6 +1170,21 @@ async def download_model(request): result["alert"] = "Failed to download model!\n\n" + str(e) return web.json_response(result) + # download model info + sha256_hash = formdata.get("sha256", None) + if sha256_hash is not None: + model_info = search_web_for_model_info(sha256_hash) + if len(model_info) > 0: + info_path = os.path.splitext(file_name)[0] + ".json" + try: + with open(info_path, "w", encoding="utf-8") as f: + json.dump(model_info, f, indent=4) + print("Saved file: " + info_path) + except ValueError as e: + print(e, file=sys.stderr, flush=True) + result["alert"] = "Failed to save model info!\n\n" + str(e) # TODO: >1 alert? concat? + + # save image as model preview image = formdata.get("image") if image is not None and image != "": try: @@ -1232,7 +1258,7 @@ async def move_model(request): return web.json_response(result) # TODO: this could overwrite existing files in destination; do a check beforehand? - for extension in preview_extensions + (model_info_extension,): + for extension in preview_extensions + (model_notes_extension,) + (model_info_extension,): old_file = old_file_without_extension + extension if os.path.isfile(old_file): new_file = new_file_without_extension + extension @@ -1286,6 +1312,7 @@ async def delete_model(request): print("Deleted file: " + model_path) delete_same_name_files(path_and_name, preview_extensions) + delete_same_name_files(path_and_name, (model_notes_extension,)) delete_same_name_files(path_and_name, (model_info_extension,)) return web.json_response(result) @@ -1310,7 +1337,7 @@ async def set_notes(request): model_path, model_type = search_path_to_system_path(model_path) model_extensions = folder_paths_get_supported_pt_extensions(model_type) file_path_without_extension, _ = split_valid_ext(model_path, model_extensions) - filename = os.path.normpath(file_path_without_extension + model_info_extension) + filename = os.path.normpath(file_path_without_extension + model_notes_extension) if dt_epoch is not None and os.path.exists(filename) and os.path.getmtime(filename) > dt_epoch: # discard late save diff --git a/web/model-manager.js b/web/model-manager.js index b6a8d02..d58c4ad 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -3333,6 +3333,7 @@ async function getModelInfos(urlText) { "fp": file["fp"], "quant": file["size"], "fileFormat": file["format"], + "sha256": file["hashes"]["SHA256"], }, }); }); @@ -3353,6 +3354,7 @@ async function getModelInfos(urlText) { const infos = hfInfo["modelFiles"].map((file) => { const indexSep = file.lastIndexOf("/"); const filename = file.substring(indexSep + 1); + // TODO: get sha256 of each HuggingFace model file return { "images": hfInfo["images"], "fileName": filename, @@ -3655,6 +3657,7 @@ class DownloadView { formData.append("download", info["downloadUrl"]); formData.append("path", pathDirectory); formData.append("name", modelName); + formData.append("sha256", info["details"]["sha256"]); const image = await downloadPreviewSelect.getImage(); formData.append("image", image === PREVIEW_NONE_URI ? "" : image); formData.append("overwrite", this.elements.overwrite.checked); From fa5e7dfcdc647f3a3e4ba5bd64069055282ccca6 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:55:48 -0400 Subject: [PATCH 26/59] Download `json` file with only relevant model info. - Simplified web search to avoid extra query. --- __init__.py | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/__init__.py b/__init__.py index e82f400..5746ea0 100644 --- a/__init__.py +++ b/__init__.py @@ -244,16 +244,14 @@ def get_def_headers(url=""): return def_headers -def civitai_get_model_info(sha256_hash): +def civitai_get_model_version_info_by_hash(sha256_hash): url_api_hash = r"https://civitai.com/api/v1/model-versions/by-hash/" + sha256_hash hash_response = requests.get(url_api_hash) if hash_response.status_code != 200: return {} - hash_info = hash_response.json() - if len(hash_info) == 0: - return {} - model_id = hash_info["modelId"] + return hash_response.json() +def civitai_get_model_info_by_model_id(model_id): url_api_model = r"https://civitai.com/api/v1/models/" + str(model_id) model_response = requests.get(url_api_model) if model_response.status_code != 200: @@ -262,7 +260,7 @@ def civitai_get_model_info(sha256_hash): def search_web_for_model_info(sha256_hash): - model_info = civitai_get_model_info(sha256_hash) + model_info = civitai_get_model_version_info_by_hash(sha256_hash) if len(model_info) > 0: return model_info # TODO: search other websites @@ -271,16 +269,10 @@ def search_web_for_model_info(sha256_hash): def search_web_for_model_url(sha256_hash): - model_info = civitai_get_model_info(sha256_hash) + model_info = civitai_get_model_version_info_by_hash(sha256_hash) if len(model_info) > 0: - model_id = model_info["id"] - version_id = None - for model_version in model_info["modelVersions"]: - for files in model_version["files"]: - if files["hashes"]["SHA256"].lower() == sha256_hash.lower(): - version_id = model_version["id"] - break - if version_id is not None: break + model_id = model_info["modelId"] + version_id = model_info["id"] return f"https://civitai.com/models/{model_id}?modelVersionId={version_id}" # TODO: search other websites @@ -289,7 +281,8 @@ def search_web_for_model_url(sha256_hash): def search_web_for_model_notes(sha256_hash): - model_info = civitai_get_model_info(sha256_hash) + model_info = civitai_get_model_version_info_by_hash(sha256_hash) + model_info = civitai_get_model_info_by_model_id(model_info["modelId"]) if len(model_info) > 0: model_description = model_info.get("description", "") model_version_description = "" From 408f5887cd9d7f5d38599f368f033e12d99e2958 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:42:13 -0400 Subject: [PATCH 27/59] Added cache and use of model metadata in `json` file. (First load will be slow.) --- __init__.py | 229 +++++++++++++++++++------------ web/model-manager.js | 313 ++++++++++++++++++++++--------------------- 2 files changed, 302 insertions(+), 240 deletions(-) diff --git a/__init__.py b/__init__.py index 5746ea0..417ec92 100644 --- a/__init__.py +++ b/__init__.py @@ -244,56 +244,63 @@ def get_def_headers(url=""): return def_headers -def civitai_get_model_version_info_by_hash(sha256_hash): - url_api_hash = r"https://civitai.com/api/v1/model-versions/by-hash/" + sha256_hash - hash_response = requests.get(url_api_hash) - if hash_response.status_code != 200: - return {} - return hash_response.json() - -def civitai_get_model_info_by_model_id(model_id): - url_api_model = r"https://civitai.com/api/v1/models/" + str(model_id) - model_response = requests.get(url_api_model) - if model_response.status_code != 200: - return {} - return model_response.json() +def hash_file(path, buffer_size=1024*1024): + sha256 = hashlib.sha256() + with open(path, 'rb') as f: + while True: + data = f.read(buffer_size) + if not data: break + sha256.update(data) + return sha256.hexdigest() -def search_web_for_model_info(sha256_hash): - model_info = civitai_get_model_version_info_by_hash(sha256_hash) - if len(model_info) > 0: return model_info +class Civitai: + @staticmethod + def search_by_hash(sha256_hash): + url_api_hash = r"https://civitai.com/api/v1/model-versions/by-hash/" + sha256_hash + hash_response = requests.get(url_api_hash) + if hash_response.status_code != 200: + return {} + return hash_response.json() # model version info - # TODO: search other websites + @staticmethod + def search_by_model_id(model_id): + url_api_model = r"https://civitai.com/api/v1/models/" + str(model_id) + model_response = requests.get(url_api_model) + if model_response.status_code != 200: + return {} + return model_response.json() # model group info - return {} + @staticmethod + def get_model_url(model_version_info): + if len(model_version_info) == 0: return "" + model_id = model_version_info.get("modelId") + if model_id is None: + # there can be incomplete model info, so don't throw just in case + return "" + url = f"https://civitai.com/models/{model_id}" + version_id = model_version_info.get("id") + if version_id is not None: + url += f"?modelVersionId={version_id}" + return url + @staticmethod + def search_notes(model_version_info): + model_id = model_version_info.get("modelId") + model_version_id = model_version_info.get("id") -def search_web_for_model_url(sha256_hash): - model_info = civitai_get_model_version_info_by_hash(sha256_hash) - if len(model_info) > 0: - model_id = model_info["modelId"] - version_id = model_info["id"] - return f"https://civitai.com/models/{model_id}?modelVersionId={version_id}" + assert(model_id is not None) + assert(model_version_id is not None) - # TODO: search other websites - - return "" - - -def search_web_for_model_notes(sha256_hash): - model_info = civitai_get_model_version_info_by_hash(sha256_hash) - model_info = civitai_get_model_info_by_model_id(model_info["modelId"]) - if len(model_info) > 0: - model_description = model_info.get("description", "") model_version_description = "" model_trigger_words = [] + model_info = Civitai.search_by_model_id(model_id) + model_description = model_info.get("description", "") for model_version in model_info["modelVersions"]: - for files in model_version["files"]: - if files["hashes"]["SHA256"].lower() == sha256_hash.lower(): - model_version_description = model_version.get("description", "") - model_trigger_words = model_version.get("trainedWords", "") - break - if model_version_description != "": break + if model_version["id"] == model_version_id: + model_version_description = model_version.get("description", "") + model_trigger_words = model_version.get("trainedWords", []) + break notes = "" if len(model_trigger_words) > 0: @@ -313,24 +320,76 @@ def search_web_for_model_notes(sha256_hash): notes += markdownify.markdownify(model_version_description) if model_description != "": if len(notes) > 0: notes += "\n\n" - notes += "# " + model_info.get("name", str(model_info["id"])) + "\n\n" + notes += "# " + model_info.get("name", str(model_id)) + "\n\n" notes += markdownify.markdownify(model_description) - notes = notes.strip() + return notes.strip() + + +class ModelInfo: + @staticmethod + def search_by_hash(sha256_hash): + model_info = Civitai.search_by_hash(sha256_hash) + if len(model_info) > 0: return model_info + # TODO: search other websites + return {} + + @staticmethod + def try_load_cached(model_path): + model_info_path = os.path.splitext(model_path)[0] + model_info_extension + if os.path.isfile(model_info_path): + with open(model_info_path, "r", encoding="utf-8") as f: + model_info = json.load(f) + return model_info + return {} + + @staticmethod + def get_hash(model_info): + model_info = Civitai.get_hash(model_info) + if len(model_info) > 0: return model_info + # TODO: search other websites + return {} + + @staticmethod + def search_info(model_path, cache=True, use_cached=True): + model_info = ModelInfo.try_load_cached(model_path) + if use_cached and len(model_info) > 0: + return model_info + + sha256_hash = hash_file(model_path) + model_info = ModelInfo.search_by_hash(sha256_hash) + if cache and len(model_info) > 0: + model_info_path = os.path.splitext(model_path)[0] + model_info_extension + with open(model_info_path, "w", encoding="utf-8") as f: + json.dump(model_info, f, indent=4) + print("Saved file: " + model_info_path) + + return model_info + + @staticmethod + def get_url(model_info): + if len(model_info) == 0: return "" + model_url = Civitai.get_model_url(model_info) + if model_url != "": return model_url + + # TODO: huggingface has / formats + + # TODO: support other websites + return "" + + @staticmethod + def search_notes(model_path): + notes = "" + + model_info = ModelInfo.search_info(model_path, cache=True, use_cached=True) # assume cached is correct; re-download elsewhere + if len(model_info) > 0: + notes = Civitai.search_notes(model_info) + + # TODO: support other websites return notes - # TODO: search other websites + # TODO: search other websites - return "" - - -def hash_file(path, buffer_size=1024*1024): - sha256 = hashlib.sha256() - with open(path, 'rb') as f: - while True: - data = f.read(buffer_size) - if not data: break - sha256.update(data) - return sha256.hexdigest() + return "" @server.PromptServer.instance.routes.get("/model-manager/timestamp") @@ -979,7 +1038,7 @@ def bytes_to_size(total_bytes): @server.PromptServer.instance.routes.get("/model-manager/model/info/{path}") -async def get_model_info(request): +async def get_model_metadata(request): result = { "success": False } model_path = request.match_info["path"] @@ -993,16 +1052,16 @@ async def get_model_info(request): result["alert"] = "Invalid model path!" return web.json_response(result) - info = {} + data = {} comfyui_directory, name = os.path.split(model_path) - info["File Name"] = name - info["File Directory"] = comfyui_directory - info["File Size"] = bytes_to_size(os.path.getsize(abs_path)) + data["File Name"] = name + data["File Directory"] = comfyui_directory + data["File Size"] = bytes_to_size(os.path.getsize(abs_path)) stats = pathlib.Path(abs_path).stat() date_format = "%Y-%m-%d %H:%M:%S" date_modified = datetime.fromtimestamp(stats.st_mtime).strftime(date_format) - #info["Date Modified"] = date_modified - #info["Date Created"] = datetime.fromtimestamp(stats.st_ctime).strftime(date_format) + #data["Date Modified"] = date_modified + #data["Date Created"] = datetime.fromtimestamp(stats.st_ctime).strftime(date_format) model_extensions = folder_paths_get_supported_pt_extensions(model_type) abs_name , _ = split_valid_ext(abs_path, model_extensions) @@ -1012,7 +1071,7 @@ async def get_model_info(request): if os.path.isfile(maybe_preview): preview_path, _ = split_valid_ext(model_path, model_extensions) preview_modified = pathlib.Path(maybe_preview).stat().st_mtime_ns - info["Preview"] = { + data["Preview"] = { "path": preview_path + extension, "dateModified": str(preview_modified), } @@ -1021,27 +1080,27 @@ async def get_model_info(request): header = get_safetensor_header(abs_path) metadata = header.get("__metadata__", None) - if metadata is not None and info.get("Preview", None) is None: + if metadata is not None and data.get("Preview", None) is None: thumbnail = metadata.get("modelspec.thumbnail") if thumbnail is not None: i0 = thumbnail.find("/") + 1 i1 = thumbnail.find(";", i0) thumbnail_extension = "." + thumbnail[i0:i1] if thumbnail_extension in image_extensions: - info["Preview"] = { + data["Preview"] = { "path": request.query["path"] + thumbnail_extension, "dateModified": date_modified, } if metadata is not None: - info["Base Training Model"] = metadata.get("ss_sd_model_name", "") - info["Base Model Version"] = metadata.get("ss_base_model_version", "") - info["Network Dimension"] = metadata.get("ss_network_dim", "") - info["Network Alpha"] = metadata.get("ss_network_alpha", "") + data["Base Training Model"] = metadata.get("ss_sd_model_name", "") + data["Base Model Version"] = metadata.get("ss_base_model_version", "") + data["Network Dimension"] = metadata.get("ss_network_dim", "") + data["Network Alpha"] = metadata.get("ss_network_alpha", "") if metadata is not None: training_comment = metadata.get("ss_training_comment", "") - info["Description"] = ( + data["Description"] = ( metadata.get("modelspec.description", "") + "\n\n" + metadata.get("modelspec.usage_hint", "") + @@ -1076,7 +1135,7 @@ async def get_model_info(request): resolutions[str(x) + "x" + str(y)] = count resolutions = list(resolutions.items()) resolutions.sort(key=lambda x: x[1], reverse=True) - info["Bucket Resolutions"] = resolutions + data["Bucket Resolutions"] = resolutions tags = None if metadata is not None: @@ -1091,7 +1150,7 @@ async def get_model_info(request): tags.sort(key=lambda x: x[1], reverse=True) result["success"] = True - result["info"] = info + result["info"] = data if metadata is not None: result["metadata"] = metadata if tags is not None: @@ -1099,8 +1158,9 @@ async def get_model_info(request): result["notes"] = notes return web.json_response(result) + @server.PromptServer.instance.routes.get("/model-manager/model/web-url") -async def get_model_info(request): +async def get_model_web_url(request): result = { "success": False } model_path = request.query.get("path", None) @@ -1114,9 +1174,14 @@ async def get_model_info(request): result["alert"] = "Invalid model path!" return web.json_response(result) - sha256_hash = hash_file(abs_path) - web_url = search_web_for_model_url(sha256_hash) + model_info = ModelInfo.search_info(abs_path) + if len(model_info) == 0: + result["alert"] = "Unable to find model info!" + return web.json_response(result) + web_url = ModelInfo.get_url(model_info) + if web_url != "": + result["success"] = True return web.json_response({ "url": web_url }) @@ -1164,18 +1229,7 @@ async def download_model(request): return web.json_response(result) # download model info - sha256_hash = formdata.get("sha256", None) - if sha256_hash is not None: - model_info = search_web_for_model_info(sha256_hash) - if len(model_info) > 0: - info_path = os.path.splitext(file_name)[0] + ".json" - try: - with open(info_path, "w", encoding="utf-8") as f: - json.dump(model_info, f, indent=4) - print("Saved file: " + info_path) - except ValueError as e: - print(e, file=sys.stderr, flush=True) - result["alert"] = "Failed to save model info!\n\n" + str(e) # TODO: >1 alert? concat? + _ = ModelInfo.search_info(file_name, cache=True) # save json # save image as model preview image = formdata.get("image") @@ -1379,8 +1433,7 @@ async def try_download_notes(request): result["alert"] = "Notes already exist!" return web.json_response(result) - sha256_hash = hash_file(abs_path) - notes = search_web_for_model_notes(sha256_hash) + notes = ModelInfo.search_notes(abs_path) if not notes.isspace() and notes != "": try: with open(notes_path, "w", encoding="utf-8") as f: diff --git a/web/model-manager.js b/web/model-manager.js index d58c4ad..a498cc6 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2370,9 +2370,9 @@ class ModelInfo { [this.elements.tabButtons, this.elements.tabContents] = GenerateTabGroup([ { name: "Overview", icon: "information-box-outline", tabContent: this.element }, - { name: "Metadata", icon: "file-document-outline", tabContent: $el("div", ["Metadata"]) }, - { name: "Tags", icon: "tag-outline", tabContent: $el("div", ["Tags"]) }, { name: "Notes", icon: "pencil-outline", tabContent: $el("div", ["Notes"]) }, + { name: "Tags", icon: "tag-outline", tabContent: $el("div", ["Tags"]) }, + { name: "Metadata", icon: "file-document-outline", tabContent: $el("div", ["Metadata"]) }, ]); } @@ -2457,7 +2457,7 @@ class ModelInfo { result["info"], result["metadata"], result["tags"], - result["notes"] + result["notes"], ]; }) .catch((err) => { @@ -2642,33 +2642,137 @@ class ModelInfo { infoHtml.append.apply(infoHtml, innerHtml); // TODO: set default value of dropdown and value to model type? - /** @type {HTMLDivElement} */ - const metadataElement = this.elements.tabContents[1]; // TODO: remove magic value - const isMetadata = typeof metadata === 'object' && metadata !== null && Object.keys(metadata).length > 0; - metadataElement.innerHTML = ""; - metadataElement.append.apply(metadataElement, [ - $el("h1", ["Metadata"]), - $el("div", (() => { - const tableRows = []; - if (isMetadata) { - for (const [key, value] of Object.entries(metadata)) { - if (value === undefined || value === null) { - continue; - } - if (value !== "") { - tableRows.push($el("tr", [ - $el("th.model-metadata-key", [key]), - $el("th.model-metadata-value", [value]), - ])); - } - } + // + // NOTES + // + + const saveIcon = "content-save"; + const savingIcon = "cloud-upload-outline"; + + const saveNotesButton = new ComfyButton({ + icon: saveIcon, + tooltip: "Save note", + classList: "comfyui-button icon-button", + action: async (e) => { + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const saved = await this.trySave(false); + comfyButtonAlert(e.target, saved); + button.disabled = false; + }, + }).element; + + const downloadNotesButton = new ComfyButton({ + icon: "earth-arrow-down", + tooltip: "Attempt to download model info from the internet.", + classList: "comfyui-button icon-button", + action: async (e) => { + if (this.#savedNotesValue !== "") { + const overwriteNoteConfirmation = window.confirm("Overwrite note?"); + if (!overwriteNoteConfirmation) { + comfyButtonAlert(e.target, false, "mdi-check-bold", "mdi-close-thick"); + return; } - return $el("table.model-metadata", tableRows); - })(), - ), - ]); - const metadataButton = this.elements.tabButtons[1]; // TODO: remove magic value - metadataButton.style.display = isMetadata ? "" : "none"; + } + + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const [success, downloadedNotesValue] = await comfyRequest( + `/model-manager/notes/download?path=${path}&overwrite=True`, + { + method: "POST", + body: {}, + } + ).then((data) => { + const success = data["success"]; + const message = data["alert"]; + if (message !== undefined) { + window.alert(message); + } + return [success, data["notes"]]; + }).catch((err) => { + return [false, ""]; + }); + if (success) { + this.#savedNotesValue = downloadedNotesValue; + this.elements.notes.value = downloadedNotesValue; + } + comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); + button.disabled = false; + }, + }).element; + + const saveDebounce = debounce(async() => { + const saveIconClass = "mdi-" + saveIcon; + const savingIconClass = "mdi-" + savingIcon; + const iconElement = saveNotesButton.getElementsByTagName("i")[0]; + iconElement.classList.remove(saveIconClass); + iconElement.classList.add(savingIconClass); + const saved = await this.trySave(false); + iconElement.classList.remove(savingIconClass); + iconElement.classList.add(saveIconClass); + }, 1000); + + /** @type {HTMLDivElement} */ + const notesElement = this.elements.tabContents[1]; // TODO: remove magic value + notesElement.innerHTML = ""; + notesElement.append.apply(notesElement, + (() => { + const notes = $el("textarea.comfy-multiline-input", { + name: "model notes", + value: noteText, + oninput: (e) => { + if (this.#settingsElements["model-info-autosave-notes"].checked) { + saveDebounce(); + } + }, + }); + + if (navigator.userAgent.includes("Mac")) { + new KeyComboListener( + ["MetaLeft", "KeyS"], + saveDebounce, + notes, + ); + new KeyComboListener( + ["MetaRight", "KeyS"], + saveDebounce, + notes, + ); + } + else { + new KeyComboListener( + ["ControlLeft", "KeyS"], + saveDebounce, + notes, + ); + new KeyComboListener( + ["ControlRight", "KeyS"], + saveDebounce, + notes, + ); + } + + this.elements.notes = notes; + this.#savedNotesValue = noteText; + return [ + $el("div.row", { + style: { "align-items": "center" }, + }, [ + $el("h1", ["Notes"]), + saveNotesButton, + downloadNotesButton, + ]), + $el("div", { + style: { "display": "flex", "height": "100%", "min-height": "60px" }, + }, notes), + ]; + })() + ); + + // + // Tags + // /** @type {HTMLDivElement} */ const tagsElement = this.elements.tabContents[2]; // TODO: remove magic value @@ -2762,129 +2866,37 @@ class ModelInfo { const tagButton = this.elements.tabButtons[2]; // TODO: remove magic value tagButton.style.display = isTags ? "" : "none"; - const saveIcon = "content-save"; - const savingIcon = "cloud-upload-outline"; - - const saveNotesButton = new ComfyButton({ - icon: saveIcon, - tooltip: "Save note", - classList: "comfyui-button icon-button", - action: async (e) => { - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const saved = await this.trySave(false); - comfyButtonAlert(e.target, saved); - button.disabled = false; - }, - }).element; - - const downloadNotesButton = new ComfyButton({ - icon: "earth-arrow-down", - tooltip: "Attempt to download model info from the internet.", - classList: "comfyui-button icon-button", - action: async (e) => { - if (this.#savedNotesValue !== "") { - const overwriteNoteConfirmation = window.confirm("Overwrite note?"); - if (!overwriteNoteConfirmation) { - comfyButtonAlert(e.target, false, "mdi-check-bold", "mdi-close-thick"); - return; - } - } - - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const [success, downloadedNotesValue] = await comfyRequest( - `/model-manager/notes/download?path=${path}&overwrite=True`, - { - method: "POST", - body: {}, - } - ).then((data) => { - const success = data["success"]; - const message = data["alert"]; - if (message !== undefined) { - window.alert(message); - } - return [success, data["notes"]]; - }).catch((err) => { - return [false, ""]; - }); - if (success) { - this.#savedNotesValue = downloadedNotesValue; - this.elements.notes.value = downloadedNotesValue; - } - comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); - button.disabled = false; - }, - }).element; - - const saveDebounce = debounce(async() => { - const saveIconClass = "mdi-" + saveIcon; - const savingIconClass = "mdi-" + savingIcon; - const iconElement = saveNotesButton.getElementsByTagName("i")[0]; - iconElement.classList.remove(saveIconClass); - iconElement.classList.add(savingIconClass); - const saved = await this.trySave(false); - iconElement.classList.remove(savingIconClass); - iconElement.classList.add(saveIconClass); - }, 1000); + // + // Metadata + // /** @type {HTMLDivElement} */ - const notesElement = this.elements.tabContents[3]; // TODO: remove magic value - notesElement.innerHTML = ""; - notesElement.append.apply(notesElement, - (() => { - const notes = $el("textarea.comfy-multiline-input", { - name: "model notes", - value: noteText, - oninput: (e) => { - if (this.#settingsElements["model-info-autosave-notes"].checked) { - saveDebounce(); + const metadataElement = this.elements.tabContents[3]; // TODO: remove magic value + const isMetadata = typeof metadata === 'object' && metadata !== null && Object.keys(metadata).length > 0; + metadataElement.innerHTML = ""; + metadataElement.append.apply(metadataElement, [ + $el("h1", ["Metadata"]), + $el("div", (() => { + const tableRows = []; + if (isMetadata) { + for (const [key, value] of Object.entries(metadata)) { + if (value === undefined || value === null) { + continue; + } + if (value !== "") { + tableRows.push($el("tr", [ + $el("th.model-metadata-key", [key]), + $el("th.model-metadata-value", [value]), + ])); + } } - }, - }); - - if (navigator.userAgent.includes("Mac")) { - new KeyComboListener( - ["MetaLeft", "KeyS"], - saveDebounce, - notes, - ); - new KeyComboListener( - ["MetaRight", "KeyS"], - saveDebounce, - notes, - ); - } - else { - new KeyComboListener( - ["ControlLeft", "KeyS"], - saveDebounce, - notes, - ); - new KeyComboListener( - ["ControlRight", "KeyS"], - saveDebounce, - notes, - ); - } - - this.elements.notes = notes; - this.#savedNotesValue = noteText; - return [ - $el("div.row", { - style: { "align-items": "center" }, - }, [ - $el("h1", ["Notes"]), - saveNotesButton, - downloadNotesButton, - ]), - $el("div", { - style: { "display": "flex", "height": "100%", "min-height": "60px" }, - }, notes), - ]; - })() - ); + } + return $el("table.model-metadata", tableRows); + })(), + ), + ]); + const metadataButton = this.elements.tabButtons[3]; // TODO: remove magic value + metadataButton.style.display = isMetadata ? "" : "none"; } static UniformTagSampling(tagsAndCounts, sampleCount, frequencyThreshold = 0) { @@ -3333,7 +3345,6 @@ async function getModelInfos(urlText) { "fp": file["fp"], "quant": file["size"], "fileFormat": file["format"], - "sha256": file["hashes"]["SHA256"], }, }); }); @@ -3354,7 +3365,6 @@ async function getModelInfos(urlText) { const infos = hfInfo["modelFiles"].map((file) => { const indexSep = file.lastIndexOf("/"); const filename = file.substring(indexSep + 1); - // TODO: get sha256 of each HuggingFace model file return { "images": hfInfo["images"], "fileName": filename, @@ -3657,7 +3667,6 @@ class DownloadView { formData.append("download", info["downloadUrl"]); formData.append("path", pathDirectory); formData.append("name", modelName); - formData.append("sha256", info["details"]["sha256"]); const image = await downloadPreviewSelect.getImage(); formData.append("image", image === PREVIEW_NONE_URI ? "" : image); formData.append("overwrite", this.elements.overwrite.checked); From 76c0ce817bffb1e8ee5abbc2f68a82ef31d32e47 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Thu, 12 Sep 2024 04:32:51 -0400 Subject: [PATCH 28/59] Save model webpage links beside model. --- __init__.py | 34 +++++++++++++++++++++++++++++++++- web/model-manager.js | 43 ++++++++++++++++++++++++++++++------------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/__init__.py b/__init__.py index 417ec92..06d4e2f 100644 --- a/__init__.py +++ b/__init__.py @@ -244,6 +244,20 @@ def get_def_headers(url=""): return def_headers +def save_web_url(path, url): + with open(path, "w", encoding="utf-8") as f: + f.write(f"[InternetShortcut]\nURL={url}\n") + + +def try_load_web_url(path): + with open(path, "r", encoding="utf-8") as f: + if f.readline() != "[InternetShortcut]\n": return "" + url = f.readline() + if not url.startswith("URL="): return "" + if not url.endswith("\n"): return "" + return url[4:len(url)-1] + + def hash_file(path, buffer_size=1024*1024): sha256 = hashlib.sha256() with open(path, 'rb') as f: @@ -1114,6 +1128,11 @@ async def get_model_metadata(request): with open(notes_file, 'r', encoding="utf-8") as f: notes = f.read() + web_url_file = abs_name + ".url" + web_url = "" + if os.path.isfile(web_url_file): + web_url = try_load_web_url(web_url_file) + if metadata is not None: img_buckets = metadata.get("ss_bucket_info", None) datasets = metadata.get("ss_datasets", None) @@ -1156,6 +1175,7 @@ async def get_model_metadata(request): if tags is not None: result["tags"] = tags result["notes"] = notes + result["url"] = web_url return web.json_response(result) @@ -1174,14 +1194,22 @@ async def get_model_web_url(request): result["alert"] = "Invalid model path!" return web.json_response(result) + url_path = os.path.splitext(abs_path)[0] + ".url" + if os.path.isfile(url_path): + web_url = try_load_web_url(url_path) + if web_url != "": + result["success"] = True + return web.json_response({ "url": web_url }) + model_info = ModelInfo.search_info(abs_path) if len(model_info) == 0: result["alert"] = "Unable to find model info!" return web.json_response(result) - web_url = ModelInfo.get_url(model_info) if web_url != "": + save_web_url(url_path, web_url) result["success"] = True + return web.json_response({ "url": web_url }) @@ -1231,6 +1259,10 @@ async def download_model(request): # download model info _ = ModelInfo.search_info(file_name, cache=True) # save json + # save url + url_file_path = os.path.splitext(file_name)[0] + ".url" + save_web_url(url_file_path, download_uri) + # save image as model preview image = formdata.get("image") if image is not None and image != "": diff --git a/web/model-manager.js b/web/model-manager.js index a498cc6..2c06bbd 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -147,21 +147,29 @@ async function loadWorkflow(url) { /** * @param {string} modelSearchPath - * @returns {Promise} + * @returns {Promise} */ -async function tryOpenModelUrl(modelSearchPath) { +async function tryGetModelWebUrl(modelSearchPath) { const encodedPath = encodeURIComponent(modelSearchPath); - const requestUrl = `/model-manager/model/web-url?path=${encodedPath}`; - const webUrlResponse = await comfyRequest(requestUrl); - let modelUrl; + const response = await comfyRequest(`/model-manager/model/web-url?path=${encodedPath}`); + const url = response.url; + return url !== undefined && url !== "" ? url : undefined; +} + +/** + * @param {string} url + * @param {string} name + * @returns {boolean} + */ +function tryOpenUrl(url, name="Url") { try { - modelUrl = new URL(webUrlResponse["url"]); + new URL(url); } catch (exception) { return false; } try { - window.open(modelUrl, '_blank').focus(); + window.open(url, '_blank').focus(); } catch (exception) { // browser or ad-blocker blocking opening new window @@ -169,13 +177,13 @@ async function tryOpenModelUrl(modelSearchPath) { [ $el("p", { style: { color: "var(--input-text)" }, - }, [modelSearchPath]), + }, [name]), $el("a", { - href: modelUrl, + href: url, target: "_blank", }, [ $el("span", [ - modelUrl, + url, $el("i.mdi.mdi-open-in-new"), ]) ]), @@ -1970,7 +1978,8 @@ class ModelGrid { action: async (e) => { const [button, icon, span] = comfyButtonDisambiguate(e.target); button.disabled = true; - const success = await tryOpenModelUrl(searchPath); + const webUrl = await tryGetModelWebUrl(searchPath); + const success = tryOpenUrl(webUrl, searchPath); comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); button.disabled = false; }, @@ -2443,7 +2452,7 @@ class ModelInfo { */ async update(searchPath, updateModels, searchSeparator) { const path = encodeURIComponent(searchPath); - const [info, metadata, tags, noteText] = await comfyRequest(`/model-manager/model/info/${path}`) + const [info, metadata, tags, noteText, url] = await comfyRequest(`/model-manager/model/info/${path}`) .then((result) => { const success = result["success"]; const message = result["alert"]; @@ -2458,6 +2467,7 @@ class ModelInfo { result["metadata"], result["tags"], result["notes"], + result["url"], ]; }) .catch((err) => { @@ -2585,7 +2595,14 @@ class ModelInfo { action: async (e) => { const [button, icon, span] = comfyButtonDisambiguate(e.target); button.disabled = true; - const success = await tryOpenModelUrl(searchPath); + let webUrl; + if (url !== undefined && url !== "") { + webUrl = url; + } + else { + webUrl = await tryGetModelWebUrl(searchPath); + } + const success = tryOpenUrl(webUrl, searchPath); comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); button.disabled = false; }, From 15946599fb58de7ce41e68bbbb5869ab39ef5686 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:26:29 -0400 Subject: [PATCH 29/59] Fixed bug where model download link was saved instead of model page link. --- __init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 06d4e2f..a64cc42 100644 --- a/__init__.py +++ b/__init__.py @@ -1257,11 +1257,12 @@ async def download_model(request): return web.json_response(result) # download model info - _ = ModelInfo.search_info(file_name, cache=True) # save json + model_info = ModelInfo.search_info(file_name, cache=True) # save json # save url url_file_path = os.path.splitext(file_name)[0] + ".url" - save_web_url(url_file_path, download_uri) + url = ModelInfo.get_url(url) + save_web_url(url_file_path, url) # save image as model preview image = formdata.get("image") From c87183f98b8f3059d3d510a99464838fcf771641 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:41:29 -0400 Subject: [PATCH 30/59] Added a bit more safety checks before saving url. --- __init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index a64cc42..d8cc035 100644 --- a/__init__.py +++ b/__init__.py @@ -1206,7 +1206,7 @@ async def get_model_web_url(request): result["alert"] = "Unable to find model info!" return web.json_response(result) web_url = ModelInfo.get_url(model_info) - if web_url != "": + if web_url != "" and web_url is not None: save_web_url(url_path, web_url) result["success"] = True @@ -1262,7 +1262,8 @@ async def download_model(request): # save url url_file_path = os.path.splitext(file_name)[0] + ".url" url = ModelInfo.get_url(url) - save_web_url(url_file_path, url) + if url != "" and url is not None: + save_web_url(url_file_path, url) # save image as model preview image = formdata.get("image") From 5dcf90ca9a034edd343af65dc72865f845dad479 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:51:55 -0400 Subject: [PATCH 31/59] Fixed bug. --- __init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index d8cc035..69e6a92 100644 --- a/__init__.py +++ b/__init__.py @@ -1261,7 +1261,7 @@ async def download_model(request): # save url url_file_path = os.path.splitext(file_name)[0] + ".url" - url = ModelInfo.get_url(url) + url = ModelInfo.get_url(model_info) if url != "" and url is not None: save_web_url(url_file_path, url) From ab5532c8e6d42046d4294c4f594466d1dd341e6c Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Thu, 19 Sep 2024 11:47:34 +0300 Subject: [PATCH 32/59] upd --- __init__.py | 1 + web/model-manager.css | 20 ++++++++++++++------ web/model-manager.js | 33 +++++++++++++++++++++++++-------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/__init__.py b/__init__.py index 6aadb9b..09af7e3 100644 --- a/__init__.py +++ b/__init__.py @@ -200,6 +200,7 @@ def ui_rules(): Rule("sidebar-control-always-compact", False, bool), Rule("sidebar-default-width", 0.5, float, 0.0, 1.0), Rule("sidebar-default-height", 0.5, float, 0.0, 1.0), + Rule("sidebar-default-state", "left", str), Rule("text-input-always-hide-search-button", False, bool), Rule("text-input-always-hide-clear-button", False, bool), diff --git a/web/model-manager.css b/web/model-manager.css index 305ced2..33fcd14 100644 --- a/web/model-manager.css +++ b/web/model-manager.css @@ -10,7 +10,7 @@ position: fixed; overflow: hidden; width: 100%; - z-index: 2000; + z-index: 1100; /*override comfy-modal settings*/ border-radius: 0; @@ -87,6 +87,7 @@ overflow: hidden; color: var(--input-text); display: flex; + gap: 2px; flex-direction: row-reverse; flex-wrap: wrap; } @@ -148,7 +149,7 @@ width: 100%; } -.model-manager button { +.model-manager button, .model-manager .model-manager-head .topbar-right select { margin: 0; border: 2px solid var(--border-color); } @@ -168,6 +169,11 @@ cursor: not-allowed; } +.model-manager select:hover{ + filter: brightness(1.2); + cursor: pointer; +} + .model-manager button.block { width: 100%; } @@ -248,7 +254,7 @@ .model-manager .model-tab-group { display: flex; gap: 4px; - height: 40px; + height: 44px; } .model-manager .model-tab-group .tab-button { @@ -264,6 +270,7 @@ .model-manager .model-tab-group .tab-button.active { background-color: var(--bg-color); + margin-bottom: -2px; cursor: default; position: relative; z-index: 1; @@ -451,7 +458,7 @@ } .model-manager .comfy-grid .model-label { - background-color: rgb(from var(--content-hover-bg) r g b / 0.5); + background-color: rgb(from var(--content-hover-bg) r g b / 0.6); width: 100%; height: 2.2rem; position: absolute; @@ -589,7 +596,8 @@ position: relative; top: 0; bottom: 0; - font-size: 24px; + font-size: 20px; + text-align-last: center; -o-appearance: none; -ms-appearance: none; -webkit-appearance: none; @@ -690,7 +698,7 @@ .model-manager .model-manager-settings input[type="number"], .model-manager .tag-generator-settings input[type="number"]{ - width: 50px; + width: 60px; } .model-manager .search-settings-text { diff --git a/web/model-manager.js b/web/model-manager.js index fd55c67..714613f 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2095,10 +2095,7 @@ class ModelGrid { systemSeparator, ); let actionButtons = []; - if ( - showAddButton && - !(modelType === 'embeddings' && !navigator.clipboard) - ) { + if (showCopyButton) { actionButtons.push( new ComfyButton({ icon: 'content-copy', @@ -2114,7 +2111,7 @@ class ModelGrid { }).element, ); } - if (showCopyButton) { + if (showAddButton && !(modelType === 'embeddings' && !navigator.clipboard)) { actionButtons.push( new ComfyButton({ icon: 'plus-box-outline', @@ -4394,6 +4391,9 @@ class SettingsView { /** @return {() => Promise} */ #updateModels = () => {}; + /** @return {() => void} */ + #updateSidebarSettings = () => {}; + /** * @param {Object} settingsData * @param {boolean} updateModels @@ -4427,6 +4427,8 @@ class SettingsView { } } + this.#updateSidebarSettings(settings); + if (updateModels) { await this.#updateModels(); // Is this slow? } @@ -4491,9 +4493,11 @@ class SettingsView { /** * @param {() => Promise} updateModels * @param {() => void} updateSidebarButtons + * @param {(settings: Object) => void} updateSidebarSettings */ - constructor(updateModels, updateSidebarButtons) { + constructor(updateModels, updateSidebarButtons, updateSidebarSettings) { this.#updateModels = updateModels; + this.#updateSidebarSettings = updateSidebarSettings; const settings = this.elements.settings; const sidebarControl = $checkbox({ @@ -4569,6 +4573,7 @@ class SettingsView { { style: { color: 'var(--fg-color)' }, href: 'https://github.com/hayden-fr/ComfyUI-Model-Manager/issues/', + target: '_blank', }, ['File bugs and issues here.'], ), @@ -4604,6 +4609,11 @@ class SettingsView { 'vae_approx', ], }), + $select({ + $: (el) => (settings['sidebar-default-state'] = el), + textContent: 'Default model manager position', + options: ['left', 'right', 'top', 'bottom', 'none'], + }), $checkbox({ $: (el) => (settings['model-real-time-search'] = el), textContent: 'Real-time search', @@ -4833,6 +4843,7 @@ function GenerateSidebarToggleRadioAndSelect(labels, activationCallbacks = []) { 'select', { name: 'sidebar-select', + classList: 'icon-button', onchange: (event) => { const select = event.target; const children = select.children; @@ -4970,6 +4981,7 @@ class ModelManager extends ComfyDialog { this.#settingsView = new SettingsView(this.#refreshModels, () => this.#updateSidebarButtons(), + this.#updateSidebarSettings, ); this.#modelInfo = new ModelInfo( @@ -5350,9 +5362,13 @@ class ModelManager extends ComfyDialog { async #init() { await this.#settingsView.reload(false); await this.#refreshModels(); + } - const settings = this.#settingsView.elements.settings; - + /** + * @param {settings: Object} + * @return {void} + */ + #updateSidebarSettings = (settings) => { { // initialize buttons' visibility state const hideSearchButtons = @@ -5374,6 +5390,7 @@ class ModelManager extends ComfyDialog { const xDecimal = settings['sidebar-default-width'].value; const yDecimal = settings['sidebar-default-height'].value; + this.element.dataset['sidebarState'] = settings['sidebar-default-state'].value; this.element.dataset['sidebarLeftWidthDecimal'] = xDecimal; this.element.dataset['sidebarRightWidthDecimal'] = xDecimal; this.element.dataset['sidebarTopHeightDecimal'] = yDecimal; From 844f286f24ed8e992f442ec1de55296aa2799002 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Thu, 19 Sep 2024 15:04:50 +0300 Subject: [PATCH 33/59] buttons are updated when default position is changed --- __init__.py | 2 +- web/model-manager.js | 31 ++++++++++++++++++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/__init__.py b/__init__.py index 09af7e3..5258cd5 100644 --- a/__init__.py +++ b/__init__.py @@ -200,7 +200,7 @@ def ui_rules(): Rule("sidebar-control-always-compact", False, bool), Rule("sidebar-default-width", 0.5, float, 0.0, 1.0), Rule("sidebar-default-height", 0.5, float, 0.0, 1.0), - Rule("sidebar-default-state", "left", str), + Rule("sidebar-default-state", "Left", str), Rule("text-input-always-hide-search-button", False, bool), Rule("text-input-always-hide-clear-button", False, bool), diff --git a/web/model-manager.js b/web/model-manager.js index 714613f..c7caea4 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -4612,7 +4612,7 @@ class SettingsView { $select({ $: (el) => (settings['sidebar-default-state'] = el), textContent: 'Default model manager position', - options: ['left', 'right', 'top', 'bottom', 'none'], + options: ['Left', 'Right', 'Top', 'Bottom', 'None'], }), $checkbox({ $: (el) => (settings['model-real-time-search'] = el), @@ -4922,9 +4922,7 @@ function GenerateSidebarToggleRadioAndSelect(labels, activationCallbacks = []) { ); } radioButtonGroup.append.apply(radioButtonGroup, buttons); - buttons[0].click(); buttons[0].style.display = 'none'; - return [radioButtonGroup, select]; } @@ -5031,11 +5029,7 @@ class ModelManager extends ComfyDialog { ['◼', '◨', '⬒', '⬓', '◧'], [ () => { - const element = this.element; - if (element) { - // callback on initialization as default state - element.dataset['sidebarState'] = 'none'; - } + this.element.dataset['sidebarState'] = 'none'; }, () => { this.element.dataset['sidebarState'] = 'right'; @@ -5364,11 +5358,23 @@ class ModelManager extends ComfyDialog { await this.#refreshModels(); } - /** - * @param {settings: Object} - * @return {void} - */ #updateSidebarSettings = (settings) => { + + const newSidebarState = settings['sidebar-default-state'].value; + let buttonNumb = 0; + if (newSidebarState === 'Left') { + buttonNumb = 4; + } else if (newSidebarState === 'Right') { + buttonNumb = 1; + } else if (newSidebarState === 'Top') { + buttonNumb = 2; + } else if (newSidebarState === 'Bottom') { + buttonNumb = 3; + } + if(!this.#sidebarButtonGroup.children[buttonNumb].classList.contains('radio-button-group-active')){ + this.#sidebarButtonGroup.children[buttonNumb].click(); + } + { // initialize buttons' visibility state const hideSearchButtons = @@ -5390,7 +5396,6 @@ class ModelManager extends ComfyDialog { const xDecimal = settings['sidebar-default-width'].value; const yDecimal = settings['sidebar-default-height'].value; - this.element.dataset['sidebarState'] = settings['sidebar-default-state'].value; this.element.dataset['sidebarLeftWidthDecimal'] = xDecimal; this.element.dataset['sidebarRightWidthDecimal'] = xDecimal; this.element.dataset['sidebarTopHeightDecimal'] = yDecimal; From 7a5d19eeec65426472760946532779ce08fafb10 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Fri, 20 Sep 2024 03:30:11 +0300 Subject: [PATCH 34/59] defauls state is None, state and sizes are not updated when Save or Reload is pressed --- __init__.py | 2 +- web/model-manager.js | 65 ++++++++++++++++++++++++-------------------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/__init__.py b/__init__.py index 5258cd5..111e564 100644 --- a/__init__.py +++ b/__init__.py @@ -200,7 +200,7 @@ def ui_rules(): Rule("sidebar-control-always-compact", False, bool), Rule("sidebar-default-width", 0.5, float, 0.0, 1.0), Rule("sidebar-default-height", 0.5, float, 0.0, 1.0), - Rule("sidebar-default-state", "Left", str), + Rule("sidebar-default-state", "None", str), Rule("text-input-always-hide-search-button", False, bool), Rule("text-input-always-hide-clear-button", False, bool), diff --git a/web/model-manager.js b/web/model-manager.js index c7caea4..b23e06d 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -4611,7 +4611,7 @@ class SettingsView { }), $select({ $: (el) => (settings['sidebar-default-state'] = el), - textContent: 'Default model manager position', + textContent: 'Default model manager position (on start up)', options: ['Left', 'Right', 'Top', 'Bottom', 'None'], }), $checkbox({ @@ -5356,37 +5356,27 @@ class ModelManager extends ComfyDialog { async #init() { await this.#settingsView.reload(false); await this.#refreshModels(); - } - #updateSidebarSettings = (settings) => { - - const newSidebarState = settings['sidebar-default-state'].value; - let buttonNumb = 0; - if (newSidebarState === 'Left') { - buttonNumb = 4; - } else if (newSidebarState === 'Right') { - buttonNumb = 1; - } else if (newSidebarState === 'Top') { - buttonNumb = 2; - } else if (newSidebarState === 'Bottom') { - buttonNumb = 3; - } - if(!this.#sidebarButtonGroup.children[buttonNumb].classList.contains('radio-button-group-active')){ - this.#sidebarButtonGroup.children[buttonNumb].click(); - } - + const settings = this.#settingsView.elements.settings; + { - // initialize buttons' visibility state - const hideSearchButtons = - settings['text-input-always-hide-search-button'].checked; - const hideClearSearchButtons = - settings['text-input-always-hide-clear-button'].checked; - this.#downloadView.elements.searchButton.style.display = hideSearchButtons - ? 'none' - : ''; - this.#downloadView.elements.clearSearchButton.style.display = - hideClearSearchButtons ? 'none' : ''; - } + // set initial sidebar state + const newSidebarState = settings['sidebar-default-state'].value; + let buttonNumb = 0; + if (newSidebarState === 'Right') { + buttonNumb = 1; + } else if (newSidebarState === 'Top') { + buttonNumb = 2; + } else if (newSidebarState === 'Bottom') { + buttonNumb = 3; + } else if (newSidebarState === 'Left') { + buttonNumb = 4; + } + const button = this.#sidebarButtonGroup.children[buttonNumb]; + if(!button.classList.contains('radio-button-group-active')){ + button.click(); + } + } { // set initial sidebar widths & heights @@ -5430,6 +5420,21 @@ class ModelManager extends ComfyDialog { } } + #updateSidebarSettings = (settings) => { + { + // update buttons' visibility state + const hideSearchButtons = + settings['text-input-always-hide-search-button'].checked; + const hideClearSearchButtons = + settings['text-input-always-hide-clear-button'].checked; + this.#downloadView.elements.searchButton.style.display = hideSearchButtons + ? 'none' + : ''; + this.#downloadView.elements.clearSearchButton.style.display = + hideClearSearchButtons ? 'none' : ''; + } + } + #resetManagerContentsScroll = () => { this.#tabManagerContents.scrollTop = 0; }; From 5abbd0ccb893a20cbab85f8c0052ad32cc3ef320 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Fri, 20 Sep 2024 03:35:02 +0300 Subject: [PATCH 35/59] Update model-manager.js --- web/model-manager.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index b23e06d..a95c940 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -5372,10 +5372,7 @@ class ModelManager extends ComfyDialog { } else if (newSidebarState === 'Left') { buttonNumb = 4; } - const button = this.#sidebarButtonGroup.children[buttonNumb]; - if(!button.classList.contains('radio-button-group-active')){ - button.click(); - } + this.#sidebarButtonGroup.children[buttonNumb].click(); } { From 81739c6d219cdfaf3a51ec522bb91d7cb00394e7 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Fri, 20 Sep 2024 03:37:45 +0300 Subject: [PATCH 36/59] Update model-manager.js --- web/model-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index a95c940..1e391b7 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -5373,7 +5373,7 @@ class ModelManager extends ComfyDialog { buttonNumb = 4; } this.#sidebarButtonGroup.children[buttonNumb].click(); - } + } { // set initial sidebar widths & heights From 20f933029271d526c56b949035fca7e641a85f50 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Fri, 20 Sep 2024 15:48:34 +0300 Subject: [PATCH 37/59] use "drop" event instead of "dragend" in firefox --- web/model-manager.js | 100 ++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 48 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index fd55c67..ea66954 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -97,35 +97,8 @@ class KeyComboListener { } } -/** - * Handles Firefox's drag event, which returns different coordinates and then fails when calling `elementFromPoint`. - * @param {DragEvent} event - * @returns {[Number, Number, HTMLElement]} [clientX, clientY, targetElement] - */ -function elementFromDragEvent(event) { - let clientX = null; - let clientY = null; - let target; - const userAgentString = navigator.userAgent; - if (userAgentString.indexOf('Firefox') > -1) { - clientX = event.clientX; - clientY = event.clientY; - const screenOffsetX = window.screenLeft; - if (clientX >= screenOffsetX) { - clientX = clientX - screenOffsetX; - } - const screenOffsetY = window.screenTop; - if (clientY >= screenOffsetY) { - clientY = clientY - screenOffsetY; - } - target = document.elementFromPoint(clientX, clientY); - } else { - clientX = event.clientX; - clientY = event.clientY; - target = document.elementFromPoint(event.clientX, event.clientY); - } - return [clientX, clientY, target]; -} +// This is used in Firefox to bypass the ‘dragend’ event because it returns incorrect ‘screenX’ and ‘screenY’ +const IS_FIREFOX = navigator.userAgent.indexOf('Firefox') > -1; /** * @param {string} url @@ -1895,20 +1868,16 @@ class ModelGrid { * @param {boolean} removeEmbeddingExtension * @param {boolean} strictlyOnWidget */ - static #dragAddModel( + static dragAddModel( event, modelType, path, removeEmbeddingExtension, strictlyOnWidget, ) { - const [clientX, clientY, target] = elementFromDragEvent(event); + const target = document.elementFromPoint(event.x, event.y); if (modelType !== 'embeddings' && target.id === 'graph-canvas') { - //const pos = app.canvas.convertEventToCanvasOffset(event); - const pos = app.canvas.convertEventToCanvasOffset({ - clientX: clientX, - clientY: clientY, - }); + const pos = app.canvas.convertEventToCanvasOffset(event); const node = app.graph.getNodeOnPos( pos[0], @@ -2164,20 +2133,41 @@ class ModelGrid { }, }).element, ]; - const dragAdd = (e) => - ModelGrid.#dragAddModel( - e, - modelType, - path, - removeEmbeddingExtension, - strictDragToAdd, - ); + + const overlay = (() => { + if(IS_FIREFOX){ + const dragAdd = (e) =>{ + const data = { + modelType: modelType, + path: path, + removeEmbeddingExtension: removeEmbeddingExtension, + strictDragToAdd: strictDragToAdd, + }; + e.dataTransfer.setData('manager-model', JSON.stringify(data)); + } + return $el('div.model-preview-overlay', { + ondragstart: (e) => dragAdd(e), + draggable: true, + }); + } else { + const dragAdd = (e) => + ModelGrid.dragAddModel( + e, + modelType, + path, + removeEmbeddingExtension, + strictDragToAdd, + ); + return $el('div.model-preview-overlay', { + ondragend: (e) => dragAdd(e), + draggable: true, + }); + } + })(); + return $el('div.item', {}, [ previewThumbnail, - $el('div.model-preview-overlay', { - ondragend: (e) => dragAdd(e), - draggable: true, - }), + overlay, $el( 'div.model-preview-top-right', { @@ -5344,6 +5334,20 @@ class ModelManager extends ComfyDialog { updateDragSidebar(e, e.touches[0].clientX, e.touches[0].clientY), ); + if(IS_FIREFOX){ + app.canvasEl.addEventListener('drop', (e) => { + if (e.dataTransfer.types.includes('manager-model')){ + const data = JSON.parse(e.dataTransfer.getData('manager-model')); + ModelGrid.dragAddModel( + e, + data.modelType, + data.path, + data.removeEmbeddingExtension, + data.strictDragToAdd, + ); + } + }); + } this.#init(); } From 8df9cee9304aae9d9285be1a61e180e26923b787 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Fri, 20 Sep 2024 16:22:50 +0300 Subject: [PATCH 38/59] Update model-manager.js --- web/model-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index ea66954..939d41c 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -97,7 +97,7 @@ class KeyComboListener { } } -// This is used in Firefox to bypass the ‘dragend’ event because it returns incorrect ‘screenX’ and ‘screenY’ +// This is used in Firefox to bypass the ‘dragend’ event because it returns incorrect ‘clientX’ and ‘clientY’ const IS_FIREFOX = navigator.userAgent.indexOf('Firefox') > -1; /** From c180d1b38047309469773544945a4afb86b9f332 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Fri, 20 Sep 2024 16:28:25 +0300 Subject: [PATCH 39/59] Update model-manager.js --- web/model-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index 939d41c..52e0855 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -1875,7 +1875,7 @@ class ModelGrid { removeEmbeddingExtension, strictlyOnWidget, ) { - const target = document.elementFromPoint(event.x, event.y); + const target = document.elementFromPoint(event.clientX, event.clientY); if (modelType !== 'embeddings' && target.id === 'graph-canvas') { const pos = app.canvas.convertEventToCanvasOffset(event); From 42a5180dc969e2ae2d9fc722c9a7d88a6e410225 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Fri, 20 Sep 2024 18:44:53 +0300 Subject: [PATCH 40/59] Update model-manager.js --- web/model-manager.js | 82 ++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index 52e0855..c478ec9 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2043,6 +2043,47 @@ class ModelGrid { const previewThumbnailFormat = settingsElements['model-preview-thumbnail-type'].value; if (models.length > 0) { + + const $overlay = IS_FIREFOX + ? (( + modelType, + path, + removeEmbeddingExtension, + strictDragToAdd, + ) => { + return $el('div.model-preview-overlay', { + ondragstart: (e) =>{ + const data = { + modelType: modelType, + path: path, + removeEmbeddingExtension: removeEmbeddingExtension, + strictDragToAdd: strictDragToAdd, + }; + e.dataTransfer.setData('manager-model', JSON.stringify(data)); + e.dataTransfer.setData('text/plain', ''); + }, + draggable: true, + }); + }) + : (( + modelType, + path, + removeEmbeddingExtension, + strictDragToAdd, + ) => { + return $el('div.model-preview-overlay', { + ondragend: (e) => + ModelGrid.dragAddModel( + e, + modelType, + path, + removeEmbeddingExtension, + strictDragToAdd, + ), + draggable: true, + }); + }); + return models.map((item) => { const previewInfo = item.preview; const previewThumbnail = $el('img.model-preview', { @@ -2133,41 +2174,14 @@ class ModelGrid { }, }).element, ]; - - const overlay = (() => { - if(IS_FIREFOX){ - const dragAdd = (e) =>{ - const data = { - modelType: modelType, - path: path, - removeEmbeddingExtension: removeEmbeddingExtension, - strictDragToAdd: strictDragToAdd, - }; - e.dataTransfer.setData('manager-model', JSON.stringify(data)); - } - return $el('div.model-preview-overlay', { - ondragstart: (e) => dragAdd(e), - draggable: true, - }); - } else { - const dragAdd = (e) => - ModelGrid.dragAddModel( - e, - modelType, - path, - removeEmbeddingExtension, - strictDragToAdd, - ); - return $el('div.model-preview-overlay', { - ondragend: (e) => dragAdd(e), - draggable: true, - }); - } - })(); - return $el('div.item', {}, [ previewThumbnail, - overlay, + $overlay( + modelType, + path, + removeEmbeddingExtension, + strictDragToAdd, + ), $el( 'div.model-preview-top-right', { @@ -5335,7 +5349,7 @@ class ModelManager extends ComfyDialog { ); if(IS_FIREFOX){ - app.canvasEl.addEventListener('drop', (e) => { + app.canvasContainer.addEventListener('drop', (e) => { if (e.dataTransfer.types.includes('manager-model')){ const data = JSON.parse(e.dataTransfer.getData('manager-model')); ModelGrid.dragAddModel( From e05c83e5f9afda200336bf080d992f6f8e66d92e Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Fri, 20 Sep 2024 18:59:31 +0300 Subject: [PATCH 41/59] Update model-manager.js --- web/model-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index c478ec9..e5a2a3e 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2060,7 +2060,7 @@ class ModelGrid { strictDragToAdd: strictDragToAdd, }; e.dataTransfer.setData('manager-model', JSON.stringify(data)); - e.dataTransfer.setData('text/plain', ''); + e.dataTransfer.setData('text/plain', ''); }, draggable: true, }); From 4757978164d4c6e07dc69606d1c8ec6d64f2ccdf Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 21 Sep 2024 18:05:14 -0400 Subject: [PATCH 42/59] Added model info scan. - Tries to download and save model info, notes and url files. --- __init__.py | 154 ++++++++++++++++++++++++++++++++----------- web/model-manager.js | 39 ++++++++++- 2 files changed, 153 insertions(+), 40 deletions(-) diff --git a/__init__.py b/__init__.py index 69e6a92..6e0c59a 100644 --- a/__init__.py +++ b/__init__.py @@ -74,6 +74,7 @@ def split_valid_ext(s, *arg_exts): _folder_names_and_paths = None # dict[str, tuple[list[str], list[str]]] def folder_paths_folder_names_and_paths(refresh = False): + # TODO: "diffusers" extension whitelist is ["folder"] global _folder_names_and_paths if refresh or _folder_names_and_paths is None: _folder_names_and_paths = {} @@ -300,21 +301,41 @@ class Civitai: @staticmethod def search_notes(model_version_info): - model_id = model_version_info.get("modelId") - model_version_id = model_version_info.get("id") + if len(model_version_info) == 0: + return "" + model_name = None + if "modelId" in model_version_info and "id" in model_version_info: + model_id = model_version_info.get("modelId") + model_version_id = model_version_info.get("id") - assert(model_id is not None) - assert(model_version_id is not None) - - model_version_description = "" - model_trigger_words = [] - model_info = Civitai.search_by_model_id(model_id) - model_description = model_info.get("description", "") - for model_version in model_info["modelVersions"]: - if model_version["id"] == model_version_id: - model_version_description = model_version.get("description", "") - model_trigger_words = model_version.get("trainedWords", []) - break + model_version_description = "" + model_trigger_words = [] + model_info = Civitai.search_by_model_id(model_id) + if len(model_info) == 0: # can happen if model download is disabled + print("Model Manager WARNING: Unable to find Civitai 'modelId' " + str(model_id)) + return "" + model_name = model_info.get("name") + model_description = model_info.get("description") + for model_version in model_info["modelVersions"]: + if model_version["id"] == model_version_id: + model_version_description = model_version.get("description") + model_trigger_words = model_version.get("trainedWords") + break + elif "description" in model_version_info and "activation text" in model_version_info and "notes" in model_version_info: + # {'description': str, 'sd version': str, 'activation text': str, 'preferred weight': int, 'notes': str} + model_description = model_version_info.get("description") + model_trigger_words = model_version_info.get("activation text") + if type(model_trigger_words) is str: + model_trigger_words = [model_trigger_words] + else: + model_trigger_words = [] + model_version_description = model_version_info.get("notes") + else: + return "" + model_description = model_description if type(model_description) is str else "" + model_trigger_words = model_trigger_words if model_trigger_words is not None else [] + model_version_description = model_version_description if type(model_version_description) is str else "" + model_name = model_name if type(model_name) is str else "Model Description" notes = "" if len(model_trigger_words) > 0: @@ -334,7 +355,7 @@ class Civitai: notes += markdownify.markdownify(model_version_description) if model_description != "": if len(notes) > 0: notes += "\n\n" - notes += "# " + model_info.get("name", str(model_id)) + "\n\n" + notes += "# " + model_name + "\n\n" notes += markdownify.markdownify(model_description) return notes.strip() @@ -381,28 +402,25 @@ class ModelInfo: @staticmethod def get_url(model_info): - if len(model_info) == 0: return "" + if len(model_info) == 0: + return "" model_url = Civitai.get_model_url(model_info) - if model_url != "": return model_url - + if model_url != "": + return model_url # TODO: huggingface has / formats - # TODO: support other websites return "" @staticmethod def search_notes(model_path): - notes = "" - + assert(os.path.isfile(model_path)) model_info = ModelInfo.search_info(model_path, cache=True, use_cached=True) # assume cached is correct; re-download elsewhere - if len(model_info) > 0: - notes = Civitai.search_notes(model_info) - - # TODO: support other websites - return notes - + if len(model_info) == 0: + return "" + notes = Civitai.search_notes(model_info) + if len(notes) > 0 and not notes.isspace(): + return notes # TODO: search other websites - return "" @@ -945,6 +963,65 @@ async def get_directory_list(request): return web.json_response(dir_list) +@server.PromptServer.instance.routes.post("/model-manager/models/scan-download") +async def try_scan_download(request): + refresh = request.query.get("refresh", None) is not None + response = { + "success": False, + "infoCount": 0, + "notesCount": 0, + "urlCount": 0, + } + model_paths = folder_paths_folder_names_and_paths(refresh) + for _, (model_dirs, model_extension_whitelist) in model_paths.items(): + for root_dir in model_dirs: + for root, dirs, files in os.walk(root_dir): + for file in files: + file_name, file_extension = os.path.splitext(file) + if file_extension not in model_extension_whitelist: + continue + model_file_path = root + os.path.sep + file + + model_info_path = root + os.path.sep + file_name + model_info_extension + model_notes_path = root + os.path.sep + file_name + model_notes_extension + model_url_path = root + os.path.sep + file_name + ".url" + if os.path.exists(model_info_path) and os.path.exists(model_notes_path) and os.path.exists(model_url_path): + continue + print("Scanning " + model_file_path) + + model_info = {} + model_info = ModelInfo.search_info(model_file_path, cache=True, use_cached=True) + if len(model_info) == 0: + continue + response["infoCount"] += 1 + + if not os.path.exists(model_notes_path): + notes = ModelInfo.search_notes(model_file_path) + if not notes.isspace() and notes != "": + try: + with open(model_notes_path, "w", encoding="utf-8") as f: + f.write(notes) + print("Saved file: " + model_notes_path) + response["notesCount"] += 1 + except Exception as e: + print(f"Failed to save {model_notes_path}!") + print(e, file=sys.stderr, flush=True) + + if not os.path.exists(model_url_path): + web_url = ModelInfo.get_url(model_info) + if web_url is not None and web_url != "": + try: + save_web_url(model_url_path, web_url) + print("Saved file: " + model_url_path) + response["urlCount"] += 1 + except Exception as e: + print(f"Failed to save {model_url_path}!") + print(e, file=sys.stderr, flush=True) + + response["success"] = True + return web.json_response(response) + + def download_file(url, filename, overwrite): if not overwrite and os.path.isfile(filename): raise ValueError("File already exists!") @@ -1468,15 +1545,18 @@ async def try_download_notes(request): return web.json_response(result) notes = ModelInfo.search_notes(abs_path) - if not notes.isspace() and notes != "": - try: - with open(notes_path, "w", encoding="utf-8") as f: - f.write(notes) - result["success"] = True - except ValueError as e: - print(e, file=sys.stderr, flush=True) - result["alert"] = "Failed to save notes!\n\n" + str(e) - return web.json_response(result) + if notes.isspace() or notes == "": + result["alert"] = "No notes found!" + return web.json_response(result) + + try: + with open(notes_path, "w", encoding="utf-8") as f: + f.write(notes) + result["success"] = True + except ValueError as e: + print(e, file=sys.stderr, flush=True) + result["alert"] = "Failed to save notes!\n\n" + str(e) + return web.json_response(result) result["notes"] = notes return web.json_response(result) diff --git a/web/model-manager.js b/web/model-manager.js index 2fa224d..b5cec13 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2918,7 +2918,7 @@ class ModelInfo { infoHtml.append.apply(infoHtml, innerHtml); // TODO: set default value of dropdown and value to model type? -// + // // NOTES // @@ -4545,7 +4545,7 @@ class SettingsView { }; /** @return {() => Promise} */ - #updateModels = () => {}; + #updateModels = async () => {}; /** * @param {Object} settingsData @@ -4709,6 +4709,38 @@ class SettingsView { }, }).element; + const scanDownloadModelInfosButton = new ComfyButton({ + content: 'Download Scan Model Info', + tooltip: 'Scans all model files and tries to download and save model info, notes and urls.', + action: async (e) => { + const confirmation = window.confirm( + 'WARNING: This may take a while and generate MANY server requests!\nUSE AT YOUR OWN RISK!', + ); + if (!confirmation) { + return; + } + + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const data = await comfyRequest('/model-manager/models/scan-download', { + method: 'POST', + body: JSON.stringify({}), + }).catch((err) => { + return { success: false }; + }); + const successMessage = data['success'] ? "Scan Finished!" : "Scan Failed!"; + const infoCount = data['infoCount']; + const notesCount = data['notesCount']; + const urlCount = data['urlCount']; + window.alert(`${successMessage}\n\nInfo Count: ${infoCount}\nNotes Count: ${notesCount}\nUrl Count: ${urlCount}`); + comfyButtonAlert(e.target, success); + if (infoCount > 0 || notesCount > 0 || urlCount > 0) { + await this.reload(true); + } + button.disabled = false; + }, + }).element; + $el( 'div.model-manager-settings', { @@ -4862,8 +4894,9 @@ class SettingsView { $: (el) => (settings['text-input-always-hide-clear-button'] = el), textContent: 'Always hide "Clear Search" buttons.', }), - $el('h2', ['Model Preview Images']), + $el('h2', ['Scan Files']), $el('div', [correctPreviewsButton]), + $el('div', [scanDownloadModelInfosButton]), $el('h2', ['Random Tag Generator']), $select({ $: (el) => (settings['tag-generator-sampler-method'] = el), From 7a49b548a20c891d4ec5b12e703cc164364cbc78 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 21 Sep 2024 18:33:52 -0400 Subject: [PATCH 43/59] Fixed note parse bug. - Avoid adding empty string to list of activation text. --- __init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/__init__.py b/__init__.py index 6e0c59a..64198cf 100644 --- a/__init__.py +++ b/__init__.py @@ -324,18 +324,18 @@ class Civitai: elif "description" in model_version_info and "activation text" in model_version_info and "notes" in model_version_info: # {'description': str, 'sd version': str, 'activation text': str, 'preferred weight': int, 'notes': str} model_description = model_version_info.get("description") - model_trigger_words = model_version_info.get("activation text") - if type(model_trigger_words) is str: - model_trigger_words = [model_trigger_words] + activation_text = model_version_info.get("activation text") + if activation_text != "": + model_trigger_words = [activation_text] else: model_trigger_words = [] model_version_description = model_version_info.get("notes") else: return "" - model_description = model_description if type(model_description) is str else "" + model_description = model_description if model_description is not None else "" model_trigger_words = model_trigger_words if model_trigger_words is not None else [] - model_version_description = model_version_description if type(model_version_description) is str else "" - model_name = model_name if type(model_name) is str else "Model Description" + model_version_description = model_version_description if model_version_description is not None else "" + model_name = model_name if model_name is not None else "Model Description" notes = "" if len(model_trigger_words) > 0: From fd1843cdee6f7194a5270c48ce000ca978274489 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:22:08 -0400 Subject: [PATCH 44/59] Fixed text overflow for code block in note markdown html. --- web/model-manager.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/model-manager.css b/web/model-manager.css index 8d66796..1e6c8bc 100644 --- a/web/model-manager.css +++ b/web/model-manager.css @@ -244,6 +244,10 @@ user-select: none; } +.model-manager code { + text-wrap: wrap; +} + /* main content */ .model-manager .model-manager-panel { color: var(--fg-color); From eb59ae93e006fd605a53669d301e290e33e02bc5 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:42:34 -0400 Subject: [PATCH 45/59] Console warning about fixing model info issue. --- __init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index 64198cf..bcdaf19 100644 --- a/__init__.py +++ b/__init__.py @@ -312,7 +312,7 @@ class Civitai: model_trigger_words = [] model_info = Civitai.search_by_model_id(model_id) if len(model_info) == 0: # can happen if model download is disabled - print("Model Manager WARNING: Unable to find Civitai 'modelId' " + str(model_id)) + print("Model Manager WARNING: Unable to find Civitai 'modelId' " + str(model_id) + ". Try deleting .json file and trying again later!") return "" model_name = model_info.get("name") model_description = model_info.get("description") From ef89bcf2db870f2f4a0bcc5ecc10ea94c88fb18e Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 21 Sep 2024 20:05:28 -0400 Subject: [PATCH 46/59] Adjusted button labels. --- web/model-manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index b5cec13..3fc36c0 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -4684,7 +4684,7 @@ class SettingsView { this.elements.saveButton = saveButton; const correctPreviewsButton = new ComfyButton({ - content: 'Fix Extensions', + content: 'Fix Preview Extensions', tooltip: 'Correct image file extensions in all model directories', action: async (e) => { const [button, icon, span] = comfyButtonDisambiguate(e.target); @@ -4710,7 +4710,7 @@ class SettingsView { }).element; const scanDownloadModelInfosButton = new ComfyButton({ - content: 'Download Scan Model Info', + content: 'Download Model Info', tooltip: 'Scans all model files and tries to download and save model info, notes and urls.', action: async (e) => { const confirmation = window.confirm( From 1ddba41cc00ae1d715ef3ebfd9911d08d17f801b Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sat, 21 Sep 2024 20:08:19 -0400 Subject: [PATCH 47/59] Adjusted settings labels. --- web/model-manager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index 3fc36c0..12e81bd 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -4900,11 +4900,11 @@ class SettingsView { $el('h2', ['Random Tag Generator']), $select({ $: (el) => (settings['tag-generator-sampler-method'] = el), - textContent: 'Default sampling method', + textContent: 'Sampling method', options: ['Frequency', 'Uniform'], }), $el('label', [ - 'Default count', + 'Generation count', $el('input', { $: (el) => (settings['tag-generator-count'] = el), type: 'number', @@ -4914,7 +4914,7 @@ class SettingsView { }), ]), $el('label', [ - 'Default minimum threshold', + 'Minimum frequency threshold', $el('input', { $: (el) => (settings['tag-generator-threshold'] = el), type: 'number', From 848663d78b9eba3a09ca1bf716e4b23894ab2009 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Sun, 22 Sep 2024 20:31:31 +0300 Subject: [PATCH 48/59] Update model-manager.js --- web/model-manager.js | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index fd55c67..bebf2fa 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2308,7 +2308,7 @@ class ModelInfo { /** * @param {ModelData} modelData - * @param {() => Promise} updateModels + * @param {(withoutComfyRefresh?: boolean) => Promise} updateModels * @param {any} settingsElements */ constructor(modelData, updateModels, settingsElements) { @@ -2385,7 +2385,7 @@ class ModelInfo { }); } if (updatedPreview) { - updateModels(); + updateModels(true); const previewSelect = this.previewSelect; previewSelect.elements.defaultUrl.dataset.noimage = PREVIEW_NONE_URI; @@ -2613,7 +2613,7 @@ class ModelInfo { /** * @param {string} searchPath - * @param {() => Promise} updateModels + * @param {(withoutComfyRefresh?: boolean) => Promise} updateModels * @param {string} searchSeparator */ async update(searchPath, updateModels, searchSeparator) { @@ -3632,13 +3632,13 @@ class DownloadView { /** @type {Object.} */ #settings = null; - /** @type {() => Promise} */ + /** @type {(withoutComfyRefresh?: boolean) => Promise} */ #updateModels = () => {}; /** * @param {ModelData} modelData * @param {Object.} settings - * @param {() => Promise} updateModels + * @param {(withoutComfyRefresh?: boolean) => Promise} updateModels */ constructor(modelData, settings, updateModels) { this.#domParser = new DOMParser(); @@ -4118,7 +4118,7 @@ class BrowseView { /** @type {ModelData} */ #modelData = null; - /** @type {@param {() => Promise}} */ + /** @type {(withoutComfyRefresh?: boolean) => Promise} */ #updateModels = null; /** */ @@ -4128,7 +4128,7 @@ class BrowseView { updateModelGrid = () => {}; /** - * @param {() => Promise} updateModels + * @param {(withoutComfyRefresh?: boolean) => Promise} updateModels * @param {ModelData} modelData * @param {(searchPath: string) => Promise} showModelInfo * @param {() => void} updateModelGridCallback @@ -4391,14 +4391,14 @@ class SettingsView { }, }; - /** @return {() => Promise} */ + /** @return {(withoutComfyRefresh?: boolean) => Promise} */ #updateModels = () => {}; /** * @param {Object} settingsData - * @param {boolean} updateModels + * @param {boolean} withoutComfyRefresh */ - async #setSettings(settingsData, updateModels) { + async #setSettings(settingsData, withoutComfyRefresh) { const settings = this.elements.settings; for (const [key, value] of Object.entries(settingsData)) { const setting = settings[key]; @@ -4427,19 +4427,17 @@ class SettingsView { } } - if (updateModels) { - await this.#updateModels(); // Is this slow? - } + await this.#updateModels(withoutComfyRefresh); } /** - * @param {boolean} updateModels + * @param {boolean} withoutComfyRefresh * @returns {Promise} */ - async reload(updateModels) { + async reload(withoutComfyRefresh) { const data = await comfyRequest('/model-manager/settings/load'); const settingsData = data['settings']; - await this.#setSettings(settingsData, updateModels); + await this.#setSettings(settingsData, withoutComfyRefresh); comfyButtonAlert(this.elements.reloadButton, true); } @@ -4489,7 +4487,7 @@ class SettingsView { } /** - * @param {() => Promise} updateModels + * @param {(withoutComfyRefresh?: boolean) => Promise} updateModels * @param {() => void} updateSidebarButtons */ constructor(updateModels, updateSidebarButtons) { @@ -5348,8 +5346,7 @@ class ModelManager extends ComfyDialog { } async #init() { - await this.#settingsView.reload(false); - await this.#refreshModels(); + await this.#settingsView.reload(true) const settings = this.#settingsView.elements.settings; @@ -5412,7 +5409,7 @@ class ModelManager extends ComfyDialog { this.#tabManagerContents.scrollTop = 0; }; - #refreshModels = async () => { + #refreshModels = async (withoutComfyRefresh = false) => { const modelData = this.#modelData; modelData.systemSeparator = await comfyRequest( '/model-manager/system-separator', @@ -5426,8 +5423,9 @@ class ModelManager extends ComfyDialog { this.#browseView.updateModelGrid(); await this.#tryHideModelInfo(false); - - document.getElementById('comfy-refresh-button')?.click(); + if (!withoutComfyRefresh){ + document.getElementById('comfy-refresh-button')?.click(); + } }; /** From 3b8735afef90658af37e79491e3d3db81215c31a Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Sun, 22 Sep 2024 21:13:54 -0400 Subject: [PATCH 49/59] Added "Download Model Info" button to model info view. - Always rehashes model (slow for big files). - Refactored model info download into function on server. --- __init__.py | 105 ++++++++++++++++++++++++++++--------------- web/model-manager.js | 31 ++++++++++++- 2 files changed, 97 insertions(+), 39 deletions(-) diff --git a/__init__.py b/__init__.py index bcdaf19..d996187 100644 --- a/__init__.py +++ b/__init__.py @@ -963,7 +963,48 @@ async def get_directory_list(request): return web.json_response(dir_list) -@server.PromptServer.instance.routes.post("/model-manager/models/scan-download") +def try_download_and_save_model_info(model_file_path): + success = (0, 0, 0) #info, notes, url + head, _ = os.path.splitext(model_file_path) + model_info_path = head + model_info_extension + model_notes_path = head + model_notes_extension + model_url_path = head + ".url" + if os.path.exists(model_info_path) and os.path.exists(model_notes_path) and os.path.exists(model_url_path): + return success + print("Scanning " + model_file_path) + + model_info = {} + model_info = ModelInfo.search_info(model_file_path, cache=True, use_cached=True) + if len(model_info) == 0: + return success + success[0] = 1 + + if not os.path.exists(model_notes_path): + notes = ModelInfo.search_notes(model_file_path) + if not notes.isspace() and notes != "": + try: + with open(model_notes_path, "w", encoding="utf-8") as f: + f.write(notes) + print("Saved file: " + model_notes_path) + success[1] = 1 + except Exception as e: + print(f"Failed to save {model_notes_path}!") + print(e, file=sys.stderr, flush=True) + + if not os.path.exists(model_url_path): + web_url = ModelInfo.get_url(model_info) + if web_url is not None and web_url != "": + try: + save_web_url(model_url_path, web_url) + print("Saved file: " + model_url_path) + success[2] = 1 + except Exception as e: + print(f"Failed to save {model_url_path}!") + print(e, file=sys.stderr, flush=True) + return success + + +@server.PromptServer.instance.routes.post("/model-manager/models/scan") async def try_scan_download(request): refresh = request.query.get("refresh", None) is not None response = { @@ -981,42 +1022,10 @@ async def try_scan_download(request): if file_extension not in model_extension_whitelist: continue model_file_path = root + os.path.sep + file - - model_info_path = root + os.path.sep + file_name + model_info_extension - model_notes_path = root + os.path.sep + file_name + model_notes_extension - model_url_path = root + os.path.sep + file_name + ".url" - if os.path.exists(model_info_path) and os.path.exists(model_notes_path) and os.path.exists(model_url_path): - continue - print("Scanning " + model_file_path) - - model_info = {} - model_info = ModelInfo.search_info(model_file_path, cache=True, use_cached=True) - if len(model_info) == 0: - continue - response["infoCount"] += 1 - - if not os.path.exists(model_notes_path): - notes = ModelInfo.search_notes(model_file_path) - if not notes.isspace() and notes != "": - try: - with open(model_notes_path, "w", encoding="utf-8") as f: - f.write(notes) - print("Saved file: " + model_notes_path) - response["notesCount"] += 1 - except Exception as e: - print(f"Failed to save {model_notes_path}!") - print(e, file=sys.stderr, flush=True) - - if not os.path.exists(model_url_path): - web_url = ModelInfo.get_url(model_info) - if web_url is not None and web_url != "": - try: - save_web_url(model_url_path, web_url) - print("Saved file: " + model_url_path) - response["urlCount"] += 1 - except Exception as e: - print(f"Failed to save {model_url_path}!") - print(e, file=sys.stderr, flush=True) + savedInfo, savedNotes, savedUrl = try_download_and_save_model_info(model_file_path) + response["infoCount"] += savedInfo + response["notesCount"] += savedNotes + response["urlCount"] += savedUrl response["success"] = True return web.json_response(response) @@ -1295,6 +1304,28 @@ async def get_system_separator(request): return web.json_response(os.path.sep) +@server.PromptServer.instance.routes.post("/model-manager/model/download/info") +async def download_model_info(request): + result = { "success": False } + + model_path = request.query.get("path", None) + if model_path is None: + result["alert"] = "Missing model path!" + return web.json_response(result) + model_path = urllib.parse.unquote(model_path) + + abs_path, model_type = search_path_to_system_path(model_path) + if abs_path is None: + result["alert"] = "Invalid model path!" + return web.json_response(result) + + model_info = ModelInfo.search_info(abs_path, cache=True, use_cached=False) + if len(model_info) > 0: + result["success"] = True + + return web.json_response(result) + + @server.PromptServer.instance.routes.post("/model-manager/model/download") async def download_model(request): formdata = await request.post() diff --git a/web/model-manager.js b/web/model-manager.js index 12e81bd..d0c270a 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2869,6 +2869,33 @@ class ModelInfo { button.disabled = false; }, }).element, + new ComfyButton({ + icon: 'earth-arrow-down', + tooltip: 'Try download model info.', + classList: 'comfyui-button icon-button', + action: async(e) => { + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const success = await comfyRequest( + `/model-manager/model/download/info?path=${path}`, + { + method: 'POST', + body: {}, + } + ).then((data) => { + const success = data['success']; + const message = data['alert']; + if (message !== undefined) { + window.alert(message); + } + return success; + }).catch((err) => { + return false; + }); + comfyButtonAlert(e.target, success, 'mdi-check-bold', 'mdi-close-thick'); + button.disabled = false; + }, + }).element, ]), $el('div.row.tab-header', [ $el('div.row.tab-header-flex-block', [ @@ -4722,7 +4749,7 @@ class SettingsView { const [button, icon, span] = comfyButtonDisambiguate(e.target); button.disabled = true; - const data = await comfyRequest('/model-manager/models/scan-download', { + const data = await comfyRequest('/model-manager/models/scan', { method: 'POST', body: JSON.stringify({}), }).catch((err) => { @@ -4732,7 +4759,7 @@ class SettingsView { const infoCount = data['infoCount']; const notesCount = data['notesCount']; const urlCount = data['urlCount']; - window.alert(`${successMessage}\n\nInfo Count: ${infoCount}\nNotes Count: ${notesCount}\nUrl Count: ${urlCount}`); + window.alert(`${successMessage}\nScanned: ${infoCount}\nSaved Notes: ${notesCount}\nSaved Url: ${urlCount}`); comfyButtonAlert(e.target, success); if (infoCount > 0 || notesCount > 0 || urlCount > 0) { await this.reload(true); From c35cb757faa985c4afa1a6ccfe544ea5ffec3c4e Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Mon, 23 Sep 2024 00:59:48 -0400 Subject: [PATCH 50/59] Set model previews from model info view. --- __init__.py | 20 +++++ web/model-manager.css | 13 +-- web/model-manager.js | 195 +++++++++++++++++++++++++++--------------- 3 files changed, 155 insertions(+), 73 deletions(-) diff --git a/__init__.py b/__init__.py index d996187..8500264 100644 --- a/__init__.py +++ b/__init__.py @@ -299,6 +299,13 @@ class Civitai: url += f"?modelVersionId={version_id}" return url + @staticmethod + def get_preview_urls(model_version_info): + images = model_version_info.get("images", None) + if images is None: + return [] + return [image_info["url"] for image_info in images] + @staticmethod def search_notes(model_version_info): if len(model_version_info) == 0: @@ -423,6 +430,15 @@ class ModelInfo: # TODO: search other websites return "" + @staticmethod + def get_web_preview_urls(model_info): + if len(model_info) == 0: + return [] + preview_urls = Civitai.get_preview_urls(model_info) + if len(preview_urls) > 0: + return preview_urls + # TODO: support other websites + return [] @server.PromptServer.instance.routes.get("/model-manager/timestamp") async def get_timestamp(request): @@ -1254,6 +1270,9 @@ async def get_model_metadata(request): tags = list(tags.items()) tags.sort(key=lambda x: x[1], reverse=True) + model_info = ModelInfo.try_load_cached(abs_path) + web_previews = ModelInfo.get_web_preview_urls(model_info) + result["success"] = True result["info"] = data if metadata is not None: @@ -1262,6 +1281,7 @@ async def get_model_metadata(request): result["tags"] = tags result["notes"] = notes result["url"] = web_url + result["webPreviews"] = web_previews return web.json_response(result) diff --git a/web/model-manager.css b/web/model-manager.css index 1e6c8bc..1543137 100644 --- a/web/model-manager.css +++ b/web/model-manager.css @@ -407,6 +407,11 @@ border-radius: 8px; } +.model-manager .model-info-container .item { + width: fit-content; + height: 50vh; +} + .model-manager .item img { width: 100%; height: 100%; @@ -414,15 +419,13 @@ border-radius: 8px; } -.model-manager .model-info-container .item { - width: auto; - height: auto; -} -.model-manager .model-info-container .item img { +.model-manager .model-info-container .item img, +.model-manager .model-preview-full { height: auto; width: auto; max-width: 100%; max-height: 50vh; + border-radius: 8px; } .model-manager .model-preview-button-left, diff --git a/web/model-manager.js b/web/model-manager.js index d0c270a..96ee8b8 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -673,6 +673,7 @@ class ImageSelect { /** @type {HTMLImageElement} */ defaultPreviewNoImage: null, /** @type {HTMLDivElement} */ defaultPreviews: null, /** @type {HTMLDivElement} */ defaultUrl: null, + /** @type {HTMLDivElement} */ previewButtons: null, /** @type {HTMLImageElement} */ customUrlPreview: null, /** @type {HTMLInputElement} */ customUrl: null, @@ -741,8 +742,11 @@ class ImageSelect { return PREVIEW_NONE_URI; } - /** @returns {void} */ - resetModelInfoPreview() { + /** + * @param {String[]} defaultPreviewUrls + * @returns {void} + */ + resetModelInfoPreview(defaultPreviewUrls = []) { let noimage = this.elements.defaultUrl.dataset.noimage; [ this.elements.defaultPreviewNoImage, @@ -761,6 +765,18 @@ class ImageSelect { el.src = PREVIEW_NONE_URI; } }); + const defaultPreviews = this.elements.defaultPreviews; + defaultPreviews.innerHTML = ''; + if (defaultPreviewUrls.length > 0) { + ImageSelect.generateDefaultPreviews(defaultPreviewUrls).forEach(previewElement => { + defaultPreviews.appendChild(previewElement); + }); + } + else { + const defaultImage = ImageSelect.generateDefaultPreviews([PREVIEW_NONE_URI]); + defaultPreviews.appendChild(defaultImage[0]); + } + this.elements.previewButtons.style.display = defaultPreviewUrls.length > 1 ? 'block' : 'none'; this.checkDefault(); this.elements.uploadFile.value = ''; this.elements.customUrl.value = ''; @@ -821,6 +837,28 @@ class ImageSelect { children[currentIndex].style.display = 'block'; } + /** + * @param {string[]|undefined} defaultPreviewUrls + * @returns {HTMLImageElement[]} + */ + static generateDefaultPreviews(defaultPreviewUrls) { + const imgs = defaultPreviewUrls.map((url) => { + return $el('img', { + loading: + 'lazy' /* `loading` BEFORE `src`; Known bug in Firefox 124.0.2 and Safari for iOS 17.4.1 (https://stackoverflow.com/a/76252772) */, + src: url, + style: { display: 'none' }, + onerror: (e) => { + e.target.src = PREVIEW_NONE_URI; + }, + }); + }); + if (imgs.length > 0) { + imgs[0].style.display = 'block'; + } + return imgs; + } + /** * @param {string} radioGroupName - Should be unique for every radio group. * @param {string[]|undefined} defaultPreviews @@ -858,23 +896,7 @@ class ImageSelect { height: '100%', }, }, - (() => { - const imgs = defaultPreviews.map((url) => { - return $el('img', { - loading: - 'lazy' /* `loading` BEFORE `src`; Known bug in Firefox 124.0.2 and Safari for iOS 17.4.1 (https://stackoverflow.com/a/76252772) */, - src: url, - style: { display: 'none' }, - onerror: (e) => { - e.target.src = el_defaultUri.dataset.noimage ?? PREVIEW_NONE_URI; - }, - }); - }); - if (imgs.length > 0) { - imgs[0].style.display = 'block'; - } - return imgs; - })(), + ImageSelect.generateDefaultPreviews(defaultPreviews), ); const el_uploadPreview = $el('img', { @@ -984,6 +1006,7 @@ class ImageSelect { const el_previewButtons = $el( 'div.model-preview-overlay', { + $: (el) => (this.elements.previewButtons = el), style: { display: el_defaultPreviews.children.length > 1 ? 'block' : 'none', }, @@ -2480,11 +2503,6 @@ class ModelInfo { }, }).element; this.elements.setPreviewButton = setPreviewButton; - previewSelect.elements.radioButtons.addEventListener('change', (e) => { - setPreviewButton.style.display = previewSelect.defaultIsChecked() - ? 'none' - : 'block'; - }); this.element = $el( 'div', @@ -2700,7 +2718,7 @@ class ModelInfo { */ async update(searchPath, updateModels, searchSeparator) { const path = encodeURIComponent(searchPath); - const [info, metadata, tags, noteText, url] = await comfyRequest( + const [info, metadata, tags, noteText, url, webPreviews] = await comfyRequest( `/model-manager/model/info/${path}`, ) .then((result) => { @@ -2716,8 +2734,9 @@ class ModelInfo { result['info'], result['metadata'], result['tags'], - result['notes'], - result['url'], + result['notes'], + result['url'], + result['webPreviews'], ]; }) .catch((err) => { @@ -2830,50 +2849,75 @@ class ModelInfo { } else { defaultUrl.dataset.noimage = PREVIEW_NONE_URI; } - previewSelect.resetModelInfoPreview(); - const setPreviewButton = this.elements.setPreviewButton; - setPreviewButton.style.display = previewSelect.defaultIsChecked() - ? 'none' - : 'block'; + previewSelect.resetModelInfoPreview(webPreviews); + const setPreviewDiv = $el('div.row.tab-header', { + style: { + display: "none" + } + }, [ + $el('div.row.tab-header-flex-block', [ + previewSelect.elements.radioGroup, + ]), + $el('div.row.tab-header-flex-block', [ + this.elements.setPreviewButton, + ]), + ]); + previewSelect.elements.previews.style.display = "none"; + + let previewUri; + if (info['Preview']) { + const imagePath = encodeURIComponent(info['Preview']['path']); + const imageDateModified = encodeURIComponent(info['Preview']['dateModified']); + previewUri = imageUri(imagePath, imageDateModified); + } else { + previewUri = PREVIEW_NONE_URI; + } + const previewImage = $el('img.model-preview-full', { + loading: + 'lazy' /* `loading` BEFORE `src`; Known bug in Firefox 124.0.2 and Safari for iOS 17.4.1 (https://stackoverflow.com/a/76252772) */, + src: previewUri, + }); innerHtml.push( $el('div', [ - previewSelect.elements.previews, $el('div.row.tab-header', { style: { "flex-direction": "row" } }, [ - new ComfyButton({ - icon: 'arrow-bottom-left-bold-box-outline', - tooltip: 'Attempt to load preview image workflow', - classList: 'comfyui-button icon-button', - action: async () => { - const urlString = - previewSelect.elements.defaultPreviews.children[0].src; - await loadWorkflow(urlString); - }, - }).element, - new ComfyButton({ - icon: 'open-in-new', - tooltip: 'Attempt to open model url page in a new tab.', - classList: 'comfyui-button icon-button', - action: async (e) => { - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - let webUrl; - if (url !== undefined && url !== "") { - webUrl = url; - } - else { - webUrl = await tryGetModelWebUrl(searchPath); - } - const success = tryOpenUrl(webUrl, searchPath); - comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); - button.disabled = false; - }, + new ComfyButton({ + icon: 'arrow-bottom-left-bold-box-outline', + tooltip: 'Attempt to load preview image workflow', + classList: 'comfyui-button icon-button', + action: async () => { + await loadWorkflow(previewImage.src); + }, + }).element, + new ComfyButton({ + icon: 'open-in-new', + tooltip: 'Attempt to open model url page in a new tab.', + classList: 'comfyui-button icon-button', + action: async (e) => { + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + let webUrl; + if (url !== undefined && url !== "") { + webUrl = url; + } + else { + webUrl = await tryGetModelWebUrl(searchPath); + } + const success = tryOpenUrl(webUrl, searchPath); + comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); + button.disabled = false; + }, }).element, new ComfyButton({ icon: 'earth-arrow-down', - tooltip: 'Try download model info.', + tooltip: 'Hash model and try to download model info.', classList: 'comfyui-button icon-button', action: async(e) => { + const confirm = window.confirm('Overwrite model info?'); + if (!confirm) { + comfyButtonAlert(e.target, false, 'mdi-check-bold', 'mdi-close-thick'); + return; + } const [button, icon, span] = comfyButtonDisambiguate(e.target); button.disabled = true; const success = await comfyRequest( @@ -2896,13 +2940,28 @@ class ModelInfo { button.disabled = false; }, }).element, + new ComfyButton({ + icon: 'image-edit-outline', + tooltip: 'Open preview edit dialog.', + classList: 'comfyui-button icon-button', + action: () => { + // TODO: toggle button border highlight + if (previewImage.style.display === "none") { + setPreviewDiv.style.display = "none"; + previewSelect.elements.previews.style.display = "none"; + previewImage.style.display = ""; + } + else { + previewImage.style.display = "none"; + previewSelect.elements.previews.style.display = ""; + setPreviewDiv.style.display = ""; + } + }, + }).element, ]), - $el('div.row.tab-header', [ - $el('div.row.tab-header-flex-block', [ - previewSelect.elements.radioGroup, - ]), - $el('div.row.tab-header-flex-block', [setPreviewButton]), - ]), + previewImage, + previewSelect.elements.previews, + setPreviewDiv, $el('h2', ['File Info:']), $el( 'div', From 3026717fd7815ef2218da2038dadcce731f54bbe Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:31:01 -0400 Subject: [PATCH 51/59] Added note about missing download previews. --- web/model-manager.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/model-manager.js b/web/model-manager.js index 96ee8b8..3666fba 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2955,6 +2955,9 @@ class ModelInfo { previewImage.style.display = "none"; previewSelect.elements.previews.style.display = ""; setPreviewDiv.style.display = ""; + if (previewSelect.elements.defaultPreviews.children[0].src.includes(PREVIEW_NONE_URI)) { + window.alert("No model previews found!\nTry downloading model info first!"); + } } }, }).element, From 91e5c882fc6bdfbdc832e0733be365772b992582 Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:47:14 -0400 Subject: [PATCH 52/59] Added closing of model info view after downloading model info. - Forces model info to be read from server. --- web/model-manager.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/web/model-manager.js b/web/model-manager.js index 3666fba..8f427e9 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2411,13 +2411,18 @@ class ModelInfo { /** @type {[HTMLElement][]} */ #settingsElements = null; + /** @type {() -> Promise} */ + #tryHideModelInfo = () => {}; + /** * @param {ModelData} modelData * @param {() => Promise} updateModels * @param {any} settingsElements + * @param {() => Promise} tryHideModelInfo */ - constructor(modelData, updateModels, settingsElements) { + constructor(modelData, updateModels, settingsElements, tryHideModelInfo) { this.#settingsElements = settingsElements; + this.#tryHideModelInfo = tryHideModelInfo; const moveDestinationInput = $el('input.search-text-area', { name: 'move directory', autocomplete: 'off', @@ -2936,6 +2941,9 @@ class ModelInfo { }).catch((err) => { return false; }); + if (success) { + this.#tryHideModelInfo(); + } comfyButtonAlert(e.target, success, 'mdi-check-bold', 'mdi-close-thick'); button.disabled = false; }, @@ -5254,6 +5262,7 @@ class ModelManager extends ComfyDialog { this.#modelData, this.#refreshModels, this.#settingsView.elements.settings, + () => this.#tryHideModelInfo(), ); this.#browseView = new BrowseView( From b0913a73e47ffe3f1af6bc6e1f88f977b3947e75 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Mon, 23 Sep 2024 15:42:33 +0300 Subject: [PATCH 53/59] Added preview size sliders to settings --- __init__.py | 2 ++ web/model-manager.css | 7 ++++-- web/model-manager.js | 58 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/__init__.py b/__init__.py index 111e564..a8c112b 100644 --- a/__init__.py +++ b/__init__.py @@ -183,6 +183,8 @@ def ui_rules(): Rule("model-preview-thumbnail-type", "AUTO", str), Rule("model-preview-fallback-search-safetensors-thumbnail", False, bool), + Rule("model-preview-thumbnail-width", 240, int, 150, 480), + Rule("model-preview-thumbnail-height", 360, int, 185, 480), Rule("model-show-label-extensions", False, bool), Rule("model-show-add-button", True, bool), Rule("model-show-copy-button", True, bool), diff --git a/web/model-manager.css b/web/model-manager.css index 33fcd14..7c222cd 100644 --- a/web/model-manager.css +++ b/web/model-manager.css @@ -51,6 +51,9 @@ --model-manager-sidebar-height-top: 50vh; --model-manager-sidebar-height-bottom: 50vh; + --model-manager-thumbnail-width: 240px; + --model-manager-thumbnail-height: 360px; + --model-manager-left: 0; --model-manager-right: 0; --model-manager-top: 0; @@ -399,8 +402,8 @@ /* preview image */ .model-manager .item { position: relative; - width: 240px; - height: 360px; + width: var(--model-manager-thumbnail-width);; + height: var(--model-manager-thumbnail-height);; text-align: center; overflow: hidden; border-radius: 8px; diff --git a/web/model-manager.js b/web/model-manager.js index 0f9a28d..2005ded 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -250,8 +250,6 @@ function imageUri( return uri; } const PREVIEW_NONE_URI = imageUri(); -const PREVIEW_THUMBNAIL_WIDTH = 320; -const PREVIEW_THUMBNAIL_HEIGHT = 480; /** * @@ -2042,6 +2040,10 @@ class ModelGrid { !settingsElements['model-add-embedding-extension'].checked; const previewThumbnailFormat = settingsElements['model-preview-thumbnail-type'].value; + const previewThumbnailWidth = + Math.round(settingsElements['model-preview-thumbnail-width'].value / 0.75); + const previewThumbnailHeight = + Math.round(settingsElements['model-preview-thumbnail-height'].value / 0.75); if (models.length > 0) { const $overlay = IS_FIREFOX @@ -2092,8 +2094,8 @@ class ModelGrid { src: imageUri( previewInfo?.path, previewInfo?.dateModified, - PREVIEW_THUMBNAIL_WIDTH, - PREVIEW_THUMBNAIL_HEIGHT, + previewThumbnailWidth, + previewThumbnailHeight, previewThumbnailFormat, ), draggable: false, @@ -4361,6 +4363,8 @@ class SettingsView { /** @type {HTMLInputElement} */ 'model-persistent-search': null, /** @type {HTMLInputElement} */ 'model-preview-thumbnail-type': null, + /** @type {HTMLInputElement} */ 'model-preview-thumbnail-width': null, + /** @type {HTMLInputElement} */ 'model-preview-thumbnail-height': null, /** @type {HTMLInputElement} */ 'model-preview-fallback-search-safetensors-thumbnail': null, /** @type {HTMLInputElement} */ 'model-show-label-extensions': null, @@ -4632,6 +4636,34 @@ class SettingsView { textContent: 'Preview thumbnail type', options: ['AUTO', 'JPEG'], // should use AUTO to avoid artifacts from changing between formats; use JPEG for backward compatibility }), + $el('label', [ + 'Preview thumbnail width', + $el('input', { + $: (el) => (settings['model-preview-thumbnail-width'] = el), + type: 'range', + name: 'default thumbnail width', + value: 240, + min: 150, + max: 480, + step: 5, + oninput: function(){ this.nextElementSibling.textContent = this.value + 'px'}, + }), + $el('span'), + ]), + $el('label', [ + 'Preview thumbnail height', + $el('input', { + $: (el) => (settings['model-preview-thumbnail-height'] = el), + type: 'range', + name: 'default thumbnail height', + value: 360, + min: 185, + max: 480, + step: 5, + oninput: function(){ this.nextElementSibling.textContent = this.value + 'px'}, + }), + $el('span'), + ]), $checkbox({ $: (el) => (settings['model-preview-fallback-search-safetensors-thumbnail'] = @@ -5448,6 +5480,24 @@ class ModelManager extends ComfyDialog { this.#downloadView.elements.clearSearchButton.style.display = hideClearSearchButtons ? 'none' : ''; } + + { + // update thumbnail widths & heights + const thumbnailWidthEl = settings['model-preview-thumbnail-width']; + const thumbnailHeightEl = settings['model-preview-thumbnail-height']; + + this.element.style.setProperty( + '--model-manager-thumbnail-width', + thumbnailWidthEl.value.toString() + 'px', + ); + thumbnailWidthEl.dispatchEvent(new Event('input')); + + this.element.style.setProperty( + '--model-manager-thumbnail-height', + thumbnailHeightEl.value.toString() + 'px', + ); + thumbnailHeightEl.dispatchEvent(new Event('input')); + } } #resetManagerContentsScroll = () => { From 6fa3b357c3facccde1650ed8eeaf19343b8a4a13 Mon Sep 17 00:00:00 2001 From: EtSL33py Date: Mon, 23 Sep 2024 20:19:38 +0300 Subject: [PATCH 54/59] Added 'Show buttons on hover only' setting for preview buttons --- __init__.py | 1 + web/model-manager.css | 10 +++++++++- web/model-manager.js | 13 +++++++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/__init__.py b/__init__.py index a8c112b..f63cc65 100644 --- a/__init__.py +++ b/__init__.py @@ -190,6 +190,7 @@ def ui_rules(): Rule("model-show-copy-button", True, bool), Rule("model-show-load-workflow-button", True, bool), Rule("model-info-button-on-left", False, bool), + Rule("model-buttons-only-on-hover", False, bool), Rule("model-add-embedding-extension", False, bool), Rule("model-add-drag-strict-on-field", False, bool), diff --git a/web/model-manager.css b/web/model-manager.css index 7c222cd..394185e 100644 --- a/web/model-manager.css +++ b/web/model-manager.css @@ -492,7 +492,6 @@ .model-manager .comfy-grid .model-preview-top-right, .model-manager .comfy-grid .model-preview-top-left { position: absolute; - display: flex; flex-direction: column; gap: 8px; top: 8px; @@ -506,6 +505,15 @@ left: 8px; } +.model-manager .item .model-buttons-hidden { + display: none; +} + +.model-manager .item:hover .model-buttons-hidden, +.model-manager .comfy-grid .model-buttons-visible { + display: flex; +} + .model-manager .comfy-grid .model-button { opacity: 0.65; } diff --git a/web/model-manager.js b/web/model-manager.js index 2005ded..551c11f 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -2044,6 +2044,8 @@ class ModelGrid { Math.round(settingsElements['model-preview-thumbnail-width'].value / 0.75); const previewThumbnailHeight = Math.round(settingsElements['model-preview-thumbnail-height'].value / 0.75); + const buttonsOnlyOnHover = + settingsElements['model-buttons-only-on-hover'].checked; if (models.length > 0) { const $overlay = IS_FIREFOX @@ -2085,6 +2087,8 @@ class ModelGrid { draggable: true, }); }); + const forHiddingButtonsClass = buttonsOnlyOnHover + ? 'model-buttons-hidden' : 'model-buttons-visible'; return models.map((item) => { const previewInfo = item.preview; @@ -2182,14 +2186,14 @@ class ModelGrid { strictDragToAdd, ), $el( - 'div.model-preview-top-right', + 'div.model-preview-top-right.' + forHiddingButtonsClass, { draggable: false, }, modelInfoButtonOnLeft ? infoButtons : actionButtons, ), $el( - 'div.model-preview-top-left', + 'div.model-preview-top-left.' + forHiddingButtonsClass, { draggable: false, }, @@ -4372,6 +4376,7 @@ class SettingsView { /** @type {HTMLInputElement} */ 'model-show-copy-button': null, /** @type {HTMLInputElement} */ 'model-show-load-workflow-button': null, /** @type {HTMLInputElement} */ 'model-info-button-on-left': null, + /** @type {HTMLInputElement} */ 'model-buttons-only-on-hover': null, /** @type {HTMLInputElement} */ 'model-add-embedding-extension': null, /** @type {HTMLInputElement} */ 'model-add-drag-strict-on-field': null, @@ -4690,6 +4695,10 @@ class SettingsView { $: (el) => (settings['model-info-button-on-left'] = el), textContent: '"Model Info" button on left', }), + $checkbox({ + $: (el) => (settings['model-buttons-only-on-hover'] = el), + textContent: 'Show buttons on hover only', + }), $el('h2', ['Node Graph']), $checkbox({ $: (el) => (settings['model-add-embedding-extension'] = el), From 182c515a6e82d5d464672b86c3e5708a24ec303f Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:03:18 -0400 Subject: [PATCH 55/59] Moved sidebar state setting under "Window" --- web/model-manager.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index 564b49d..ed07c3b 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -4898,11 +4898,6 @@ class SettingsView { 'vae_approx', ], }), - $select({ - $: (el) => (settings['sidebar-default-state'] = el), - textContent: 'Default model manager position (on start up)', - options: ['Left', 'Right', 'Top', 'Bottom', 'None'], - }), $checkbox({ $: (el) => (settings['model-real-time-search'] = el), textContent: 'Real-time search', @@ -4975,6 +4970,11 @@ class SettingsView { textContent: 'Save notes by default.', }), $el('h2', ['Window']), + $select({ + $: (el) => (settings['sidebar-default-state'] = el), + textContent: 'Default model manager position (on start up)', + options: ['None', 'Left', 'Bottom', 'Top', 'Right'], + }), sidebarControl, $el('label', [ 'Sidebar width (on start up)', From 75f922bea25dbd813e80136c2a76b06c8335b4fb Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:55:27 -0400 Subject: [PATCH 56/59] Added scan to download previews from model info files. - Fixed bug where scan button was not getting reset. - Attempt to get full size image preview. (May not get original image.) --- __init__.py | 185 ++++++++++++++++++++++++++++++------------- web/model-manager.js | 35 +++++++- 2 files changed, 164 insertions(+), 56 deletions(-) diff --git a/__init__.py b/__init__.py index c97a92c..5263ba8 100644 --- a/__init__.py +++ b/__init__.py @@ -271,6 +271,45 @@ def hash_file(path, buffer_size=1024*1024): class Civitai: + IMAGE_URL_SUBDIRECTORY_PREFIX = "https://civitai.com/images/" + IMAGE_URL_DOMAIN_PREFIX = "'https://image.civitai.com/" + + @staticmethod + def image_subdirectory_url_to_image_url(image_url): + url_suffix = image_url[len(Civitai.IMAGE_URL_SUBDIRECTORY_PREFIX):] + image_id = re.search(r"^\d+", url_suffix).group(0) + image_id = str(int(image_id)) + image_info_url = f"https://civitai.com/api/v1/images?imageId={image_id}" + def_headers = get_def_headers(image_info_url) + response = requests.get( + url=image_info_url, + stream=False, + verify=False, + headers=def_headers, + proxies=None, + allow_redirects=False, + ) + if response.ok: + #content_type = response.headers.get("Content-Type") + info = response.json() + items = info["items"] + if len(items) == 0: + raise RuntimeError("Civitai /api/v1/images returned 0 items!") + return items[0]["url"] + else: + raise RuntimeError("Bad response from api/v1/images!") + + @staticmethod + def image_domain_url_full_size(url, width = None): + result = re.search("/width=(\d+)", url) + if width is None: + i0 = result.span()[0] + i1 = result.span()[1] + return url[0:i0] + url[i1:] + else: + w = int(result.group(1)) + return url.replace(str(w), str(width)) + @staticmethod def search_by_hash(sha256_hash): url_api_hash = r"https://civitai.com/api/v1/model-versions/by-hash/" + sha256_hash @@ -301,11 +340,17 @@ class Civitai: return url @staticmethod - def get_preview_urls(model_version_info): + def get_preview_urls(model_version_info, full_size=False): images = model_version_info.get("images", None) if images is None: return [] - return [image_info["url"] for image_info in images] + preview_urls = [] + for image_info in images: + url = image_info["url"] + if full_size: + url = Civitai.image_domain_url_full_size(url, image_info.get("width", None)) + preview_urls.append(url) + return preview_urls @staticmethod def search_notes(model_version_info): @@ -432,10 +477,10 @@ class ModelInfo: return "" @staticmethod - def get_web_preview_urls(model_info): + def get_web_preview_urls(model_info, full_size=False): if len(model_info) == 0: return [] - preview_urls = Civitai.get_preview_urls(model_info) + preview_urls = Civitai.get_preview_urls(model_info, full_size) if len(preview_urls) > 0: return preview_urls # TODO: support other websites @@ -652,42 +697,16 @@ async def get_image_extensions(request): return web.json_response(image_extensions) -def download_model_preview(formdata): - path = formdata.get("path", None) - if type(path) is not str: +def download_model_preview(path, image, overwrite): + if not os.path.isfile(path): raise ValueError("Invalid path!") - path, model_type = search_path_to_system_path(path) - model_type_extensions = folder_paths_get_supported_pt_extensions(model_type) - path_without_extension, _ = split_valid_ext(path, model_type_extensions) + path_without_extension = os.path.splitext(path)[0] - overwrite = formdata.get("overwrite", "true").lower() - overwrite = True if overwrite == "true" else False - - image = formdata.get("image", None) if type(image) is str: - civitai_image_url = "https://civitai.com/images/" - if image.startswith(civitai_image_url): - image_id = re.search(r"^\d+", image[len(civitai_image_url):]).group(0) - image_id = str(int(image_id)) - image_info_url = f"https://civitai.com/api/v1/images?imageId={image_id}" - def_headers = get_def_headers(image_info_url) - response = requests.get( - url=image_info_url, - stream=False, - verify=False, - headers=def_headers, - proxies=None, - allow_redirects=False, - ) - if response.ok: - content_type = response.headers.get("Content-Type") - info = response.json() - items = info["items"] - if len(items) == 0: - raise RuntimeError("Civitai /api/v1/images returned 0 items!") - image = items[0]["url"] - else: - raise RuntimeError("Bad response from api/v1/images!") + if image.startswith(Civitai.IMAGE_URL_SUBDIRECTORY_PREFIX): + image = Civitai.image_subdirectory_url_to_image_url(image) + if image.startswith(Civitai.IMAGE_URL_DOMAIN_PREFIX): + image = Civitai.image_domain_url_full_size(image) _, image_extension = split_valid_ext(image, image_extensions) if image_extension == "": raise ValueError("Invalid image type!") @@ -715,17 +734,23 @@ def download_model_preview(formdata): # detect (and try to fix) wrong file extension image_format = None - with Image.open(image_path) as image: - image_format = image.format - image_dir_and_name, image_ext = os.path.splitext(image_path) - if not image_format_is_equal(image_format, image_ext): - corrected_image_path = image_dir_and_name + "." + image_format.lower() - if os.path.exists(corrected_image_path) and not overwrite: - print("WARNING: '" + image_path + "' has wrong extension!") - else: - os.rename(image_path, corrected_image_path) - print("Saved file: " + corrected_image_path) - image_path = corrected_image_path + try: + with Image.open(image_path) as image: + image_format = image.format + image_dir_and_name, image_ext = os.path.splitext(image_path) + if not image_format_is_equal(image_format, image_ext): + corrected_image_path = image_dir_and_name + "." + image_format.lower() + if os.path.exists(corrected_image_path) and not overwrite: + print("WARNING: '" + image_path + "' has wrong extension!") + else: + os.rename(image_path, corrected_image_path) + print("Saved file: " + corrected_image_path) + image_path = corrected_image_path + except Image.UnidentifiedImageError as e: #TODO: handle case where "image" is actually video + print("WARNING: '" + image_path + "' image format was unknown!") + os.remove(image_path) + print("Deleted file: " + image_path) + image_path = "" return image_path # return in-case need corrected path @@ -733,7 +758,15 @@ def download_model_preview(formdata): async def set_model_preview(request): formdata = await request.post() try: - download_model_preview(formdata) + search_path = formdata.get("path", None) + model_path, model_type = search_path_to_system_path(search_path) + + image = formdata.get("image", None) + + overwrite = formdata.get("overwrite", "true").lower() + overwrite = True if overwrite == "true" else False + + download_model_preview(model_path, image, overwrite) return web.json_response({ "success": True }) except ValueError as e: print(e, file=sys.stderr, flush=True) @@ -1047,6 +1080,48 @@ async def try_scan_download(request): response["success"] = True return web.json_response(response) +@server.PromptServer.instance.routes.post("/model-manager/preview/scan") +async def try_scan_download_previews(request): + refresh = request.query.get("refresh", None) is not None + response = { + "success": False, + "count": 0, + } + model_paths = folder_paths_folder_names_and_paths(refresh) + for _, (model_dirs, model_extension_whitelist) in model_paths.items(): + for root_dir in model_dirs: + for root, dirs, files in os.walk(root_dir): + for file in files: + file_name, file_extension = os.path.splitext(file) + if file_extension not in model_extension_whitelist: + continue + model_file_path = root + os.path.sep + file + model_file_head = os.path.splitext(model_file_path)[0] + + preview_exists = False + for preview_extension in preview_extensions: + preview_path = model_file_head + preview_extension + if os.path.isfile(preview_path): + preview_exists = True + break + if preview_exists: + continue + + model_info = ModelInfo.try_load_cached(model_file_path) # NOTE: model info must already be downloaded + web_previews = ModelInfo.get_web_preview_urls(model_info, True) + if len(web_previews) == 0: + continue + saved_image_path = download_model_preview( + model_file_path, + image=web_previews[0], + overwrite=False, + ) + if os.path.isfile(saved_image_path): + response["count"] += 1 + + response["success"] = True + return web.json_response(response) + def download_file(url, filename, overwrite): if not overwrite and os.path.isfile(filename): @@ -1272,7 +1347,7 @@ async def get_model_metadata(request): tags.sort(key=lambda x: x[1], reverse=True) model_info = ModelInfo.try_load_cached(abs_path) - web_previews = ModelInfo.get_web_preview_urls(model_info) + web_previews = ModelInfo.get_web_preview_urls(model_info, True) result["success"] = True result["info"] = data @@ -1398,11 +1473,11 @@ async def download_model(request): image = formdata.get("image") if image is not None and image != "": try: - download_model_preview({ - "path": model_path + os.sep + name, - "image": image, - "overwrite": formdata.get("overwrite"), - }) + download_model_preview( + file_name, + image, + formdata.get("overwrite"), + ) except Exception as e: print(e, file=sys.stderr, flush=True) result["alert"] = "Failed to download preview!\n\n" + str(e) diff --git a/web/model-manager.js b/web/model-manager.js index ed07c3b..5659dcc 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -4836,7 +4836,8 @@ class SettingsView { }).catch((err) => { return { success: false }; }); - const successMessage = data['success'] ? "Scan Finished!" : "Scan Failed!"; + const success = data['success']; + const successMessage = success ? "Scan Finished!" : "Scan Failed!"; const infoCount = data['infoCount']; const notesCount = data['notesCount']; const urlCount = data['urlCount']; @@ -4849,6 +4850,37 @@ class SettingsView { }, }).element; + const scanDownloadPreviewsButton = new ComfyButton({ + content: 'Download Missing Previews', + tooltip: 'Downloads missing model previews from model info.\nRun model info scan first!', + action: async (e) => { + const confirmation = window.confirm( + 'WARNING: This may take a while and generate MANY server requests!\nUSE AT YOUR OWN RISK!', + ); + if (!confirmation) { + return; + } + + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const data = await comfyRequest('/model-manager/preview/scan', { + method: 'POST', + body: JSON.stringify({}), + }).catch((err) => { + return { success: false }; + }); + const success = data['success']; + const successMessage = success ? "Scan Finished!" : "Scan Failed!"; + const count = data['count']; + window.alert(`${successMessage}\nPreviews Downloaded: ${count}`); + comfyButtonAlert(e.target, success); + if (count > 0) { + await this.reload(true); + } + button.disabled = false; + }, + }).element; + $el( 'div.model-manager-settings', { @@ -5011,6 +5043,7 @@ class SettingsView { $el('h2', ['Scan Files']), $el('div', [correctPreviewsButton]), $el('div', [scanDownloadModelInfosButton]), + $el('div', [scanDownloadPreviewsButton]), $el('h2', ['Random Tag Generator']), $select({ $: (el) => (settings['tag-generator-sampler-method'] = el), From e01afe01b6209c7b90f7abce1e9727c9ef14130d Mon Sep 17 00:00:00 2001 From: Christian Bastian <80225746+cdb-boop@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:41:37 -0400 Subject: [PATCH 57/59] Fixed "load workflow " to provide human-readable image file name. --- web/model-manager.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/web/model-manager.js b/web/model-manager.js index 5659dcc..48c7057 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -104,11 +104,10 @@ const IS_FIREFOX = navigator.userAgent.indexOf('Firefox') > -1; * @param {string} url */ async function loadWorkflow(url) { - const fileNameIndex = Math.max(url.lastIndexOf('/'), url.lastIndexOf('\\')) + 1; - const fileName = url.substring(fileNameIndex); + const fileName = SearchPath.filename(decodeURIComponent(url)); const response = await fetch(url); const data = await response.blob(); - const file = new File([data], fileName, { type: data.type }); + const file = new File([data], fileName, { type: data.type }); app.handleFile(file); } @@ -261,6 +260,19 @@ class SearchPath { const i2 = path.indexOf(searchSeparator, i1 + 1); return path.slice(i2 + 1).replaceAll(searchSeparator, systemSeparator); } + + /** + * @param {string} s search path or url + * @returns {string} + */ + static filename(s) { + let name = SearchPath.split(s)[1]; + const queryIndex = name.indexOf('?'); + if (queryIndex > -1) { + return name.substring(0, queryIndex); + } + return name; + } } /** From 9ff6f9d7a3b98035b6a538284686ab4b2654197f Mon Sep 17 00:00:00 2001 From: Hayden <48267247+hayden-fr@users.noreply.github.com> Date: Tue, 24 Sep 2024 11:28:50 +0800 Subject: [PATCH 58/59] Revert "File download scans and urls" --- README.md | 2 - __init__.py | 633 ++---------- ...odel-preview-thumbnail-buttons-example.png | Bin 78388 -> 73525 bytes requirements.txt | 1 - web/model-manager.css | 23 +- web/model-manager.js | 928 ++++++------------ 6 files changed, 383 insertions(+), 1204 deletions(-) delete mode 100644 requirements.txt diff --git a/README.md b/README.md index 2e3f391..41626f7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,6 @@ Designed to support desktop, mobile and multi-screen devices. - Press the "copy" button to copy a model to ComfyUI's clipboard or copy the embedding to the system clipboard. (Copying the embedding to the system clipboard requires a secure http connection.) - Press the "add" button to add the model to the ComfyUI graph or append the embedding to one or more selected nodes. - Press the "load workflow" button to try and load a workflow embedded in a model's preview image. -- Press the "open model url" button to try and search the web and open a model's webpage. ### Download Tab @@ -56,7 +55,6 @@ Designed to support desktop, mobile and multi-screen devices. - Read, edit and save notes. (Saved as a `.txt` file beside the model). - `Ctrl+s` or `⌘+S` to save a note when the textarea is in focus. - Autosave can be enabled in settings. (Note: Once the model info view is closed, the undo history is lost.) - - Automatically search the web for model info and save as notes with a single button. - Change or remove a model's preview image. - View training tags and use the random tag generator to generate prompt ideas. (Inspired by the one in A1111.) diff --git a/__init__.py b/__init__.py index 9d38800..f63cc65 100644 --- a/__init__.py +++ b/__init__.py @@ -8,8 +8,6 @@ import copy import importlib import re import base64 -import hashlib -import markdownify from aiohttp import web import server @@ -25,7 +23,7 @@ import folder_paths comfyui_model_uri = folder_paths.models_dir -extension_uri = os.path.dirname(os.path.abspath(__file__)) +extension_uri = os.path.dirname(__file__) config_loader_path = os.path.join(extension_uri, 'config_loader.py') config_loader_spec = importlib.util.spec_from_file_location('config_loader', config_loader_path) @@ -60,8 +58,7 @@ preview_extensions = ( # TODO: JavaScript does not know about this (x2 states) image_extensions + # order matters stable_diffusion_webui_civitai_helper_image_extensions ) -model_notes_extension = ".txt" -model_info_extension = ".json" +model_info_extension = ".txt" #video_extensions = (".avi", ".mp4", ".webm") # TODO: Requires ffmpeg or cv2. Cache preview frame? def split_valid_ext(s, *arg_exts): @@ -74,7 +71,6 @@ def split_valid_ext(s, *arg_exts): _folder_names_and_paths = None # dict[str, tuple[list[str], list[str]]] def folder_paths_folder_names_and_paths(refresh = False): - # TODO: "diffusers" extension whitelist is ["folder"] global _folder_names_and_paths if refresh or _folder_names_and_paths is None: _folder_names_and_paths = {} @@ -193,7 +189,6 @@ def ui_rules(): Rule("model-show-add-button", True, bool), Rule("model-show-copy-button", True, bool), Rule("model-show-load-workflow-button", True, bool), - Rule("model-show-open-model-url-button", False, bool), Rule("model-info-button-on-left", False, bool), Rule("model-buttons-only-on-hover", False, bool), @@ -237,7 +232,6 @@ def get_def_headers(url=""): if url.startswith("https://civitai.com/"): api_key = server_settings["civitai_api_key"] if (api_key != ""): - def_headers["Content-Type"] = f"application/json" def_headers["Authorization"] = f"Bearer {api_key}" url += "&" if "?" in url else "?" # not the most robust solution url += f"token={api_key}" # TODO: Authorization didn't work in the header @@ -249,246 +243,6 @@ def get_def_headers(url=""): return def_headers -def save_web_url(path, url): - with open(path, "w", encoding="utf-8") as f: - f.write(f"[InternetShortcut]\nURL={url}\n") - - -def try_load_web_url(path): - with open(path, "r", encoding="utf-8") as f: - if f.readline() != "[InternetShortcut]\n": return "" - url = f.readline() - if not url.startswith("URL="): return "" - if not url.endswith("\n"): return "" - return url[4:len(url)-1] - - -def hash_file(path, buffer_size=1024*1024): - sha256 = hashlib.sha256() - with open(path, 'rb') as f: - while True: - data = f.read(buffer_size) - if not data: break - sha256.update(data) - return sha256.hexdigest() - - -class Civitai: - IMAGE_URL_SUBDIRECTORY_PREFIX = "https://civitai.com/images/" - IMAGE_URL_DOMAIN_PREFIX = "'https://image.civitai.com/" - - @staticmethod - def image_subdirectory_url_to_image_url(image_url): - url_suffix = image_url[len(Civitai.IMAGE_URL_SUBDIRECTORY_PREFIX):] - image_id = re.search(r"^\d+", url_suffix).group(0) - image_id = str(int(image_id)) - image_info_url = f"https://civitai.com/api/v1/images?imageId={image_id}" - def_headers = get_def_headers(image_info_url) - response = requests.get( - url=image_info_url, - stream=False, - verify=False, - headers=def_headers, - proxies=None, - allow_redirects=False, - ) - if response.ok: - #content_type = response.headers.get("Content-Type") - info = response.json() - items = info["items"] - if len(items) == 0: - raise RuntimeError("Civitai /api/v1/images returned 0 items!") - return items[0]["url"] - else: - raise RuntimeError("Bad response from api/v1/images!") - - @staticmethod - def image_domain_url_full_size(url, width = None): - result = re.search("/width=(\d+)", url) - if width is None: - i0 = result.span()[0] - i1 = result.span()[1] - return url[0:i0] + url[i1:] - else: - w = int(result.group(1)) - return url.replace(str(w), str(width)) - - @staticmethod - def search_by_hash(sha256_hash): - url_api_hash = r"https://civitai.com/api/v1/model-versions/by-hash/" + sha256_hash - hash_response = requests.get(url_api_hash) - if hash_response.status_code != 200: - return {} - return hash_response.json() # model version info - - @staticmethod - def search_by_model_id(model_id): - url_api_model = r"https://civitai.com/api/v1/models/" + str(model_id) - model_response = requests.get(url_api_model) - if model_response.status_code != 200: - return {} - return model_response.json() # model group info - - @staticmethod - def get_model_url(model_version_info): - if len(model_version_info) == 0: return "" - model_id = model_version_info.get("modelId") - if model_id is None: - # there can be incomplete model info, so don't throw just in case - return "" - url = f"https://civitai.com/models/{model_id}" - version_id = model_version_info.get("id") - if version_id is not None: - url += f"?modelVersionId={version_id}" - return url - - @staticmethod - def get_preview_urls(model_version_info, full_size=False): - images = model_version_info.get("images", None) - if images is None: - return [] - preview_urls = [] - for image_info in images: - url = image_info["url"] - if full_size: - url = Civitai.image_domain_url_full_size(url, image_info.get("width", None)) - preview_urls.append(url) - return preview_urls - - @staticmethod - def search_notes(model_version_info): - if len(model_version_info) == 0: - return "" - model_name = None - if "modelId" in model_version_info and "id" in model_version_info: - model_id = model_version_info.get("modelId") - model_version_id = model_version_info.get("id") - - model_version_description = "" - model_trigger_words = [] - model_info = Civitai.search_by_model_id(model_id) - if len(model_info) == 0: # can happen if model download is disabled - print("Model Manager WARNING: Unable to find Civitai 'modelId' " + str(model_id) + ". Try deleting .json file and trying again later!") - return "" - model_name = model_info.get("name") - model_description = model_info.get("description") - for model_version in model_info["modelVersions"]: - if model_version["id"] == model_version_id: - model_version_description = model_version.get("description") - model_trigger_words = model_version.get("trainedWords") - break - elif "description" in model_version_info and "activation text" in model_version_info and "notes" in model_version_info: - # {'description': str, 'sd version': str, 'activation text': str, 'preferred weight': int, 'notes': str} - model_description = model_version_info.get("description") - activation_text = model_version_info.get("activation text") - if activation_text != "": - model_trigger_words = [activation_text] - else: - model_trigger_words = [] - model_version_description = model_version_info.get("notes") - else: - return "" - model_description = model_description if model_description is not None else "" - model_trigger_words = model_trigger_words if model_trigger_words is not None else [] - model_version_description = model_version_description if model_version_description is not None else "" - model_name = model_name if model_name is not None else "Model Description" - - notes = "" - if len(model_trigger_words) > 0: - notes += "# Trigger Words\n\n" - model_trigger_words = [re.sub(",$", "", s.strip()) for s in model_trigger_words] - join_separator = ', ' - for s in model_trigger_words: - if ',' in s: - join_separator = '\n' - break - if join_separator == '\n': - model_trigger_words = ["* " + s for s in model_trigger_words] - notes += join_separator.join(model_trigger_words) - if model_version_description != "": - if len(notes) > 0: notes += "\n\n" - notes += "# About this version\n\n" - notes += markdownify.markdownify(model_version_description) - if model_description != "": - if len(notes) > 0: notes += "\n\n" - notes += "# " + model_name + "\n\n" - notes += markdownify.markdownify(model_description) - return notes.strip() - - -class ModelInfo: - @staticmethod - def search_by_hash(sha256_hash): - model_info = Civitai.search_by_hash(sha256_hash) - if len(model_info) > 0: return model_info - # TODO: search other websites - return {} - - @staticmethod - def try_load_cached(model_path): - model_info_path = os.path.splitext(model_path)[0] + model_info_extension - if os.path.isfile(model_info_path): - with open(model_info_path, "r", encoding="utf-8") as f: - model_info = json.load(f) - return model_info - return {} - - @staticmethod - def get_hash(model_info): - model_info = Civitai.get_hash(model_info) - if len(model_info) > 0: return model_info - # TODO: search other websites - return {} - - @staticmethod - def search_info(model_path, cache=True, use_cached=True): - model_info = ModelInfo.try_load_cached(model_path) - if use_cached and len(model_info) > 0: - return model_info - - sha256_hash = hash_file(model_path) - model_info = ModelInfo.search_by_hash(sha256_hash) - if cache and len(model_info) > 0: - model_info_path = os.path.splitext(model_path)[0] + model_info_extension - with open(model_info_path, "w", encoding="utf-8") as f: - json.dump(model_info, f, indent=4) - print("Saved file: " + model_info_path) - - return model_info - - @staticmethod - def get_url(model_info): - if len(model_info) == 0: - return "" - model_url = Civitai.get_model_url(model_info) - if model_url != "": - return model_url - # TODO: huggingface has / formats - # TODO: support other websites - return "" - - @staticmethod - def search_notes(model_path): - assert(os.path.isfile(model_path)) - model_info = ModelInfo.search_info(model_path, cache=True, use_cached=True) # assume cached is correct; re-download elsewhere - if len(model_info) == 0: - return "" - notes = Civitai.search_notes(model_info) - if len(notes) > 0 and not notes.isspace(): - return notes - # TODO: search other websites - return "" - - @staticmethod - def get_web_preview_urls(model_info, full_size=False): - if len(model_info) == 0: - return [] - preview_urls = Civitai.get_preview_urls(model_info, full_size) - if len(preview_urls) > 0: - return preview_urls - # TODO: support other websites - return [] - @server.PromptServer.instance.routes.get("/model-manager/timestamp") async def get_timestamp(request): return web.json_response({ "timestamp": datetime.now().timestamp() }) @@ -573,12 +327,9 @@ def get_auto_thumbnail_format(original_format): return "JPEG" # default fallback -@server.PromptServer.instance.routes.get("/model-manager/preview/get/{uri}") +@server.PromptServer.instance.routes.get("/model-manager/preview/get") async def get_model_preview(request): - uri = request.match_info["uri"] - if uri is None: # BUG: this should never happen - print(f"Invalid uri! Request url: {request.url}") - uri = "no-preview" + uri = request.query.get("uri") quality = 75 response_image_format = request.query.get("image-format", None) if isinstance(response_image_format, str): @@ -700,16 +451,42 @@ async def get_image_extensions(request): return web.json_response(image_extensions) -def download_model_preview(path, image, overwrite): - if not os.path.isfile(path): +def download_model_preview(formdata): + path = formdata.get("path", None) + if type(path) is not str: raise ValueError("Invalid path!") - path_without_extension = os.path.splitext(path)[0] + path, model_type = search_path_to_system_path(path) + model_type_extensions = folder_paths_get_supported_pt_extensions(model_type) + path_without_extension, _ = split_valid_ext(path, model_type_extensions) + overwrite = formdata.get("overwrite", "true").lower() + overwrite = True if overwrite == "true" else False + + image = formdata.get("image", None) if type(image) is str: - if image.startswith(Civitai.IMAGE_URL_SUBDIRECTORY_PREFIX): - image = Civitai.image_subdirectory_url_to_image_url(image) - if image.startswith(Civitai.IMAGE_URL_DOMAIN_PREFIX): - image = Civitai.image_domain_url_full_size(image) + civitai_image_url = "https://civitai.com/images/" + if image.startswith(civitai_image_url): + image_id = re.search(r"^\d+", image[len(civitai_image_url):]).group(0) + image_id = str(int(image_id)) + image_info_url = f"https://civitai.com/api/v1/images?imageId={image_id}" + def_headers = get_def_headers(image_info_url) + response = requests.get( + url=image_info_url, + stream=False, + verify=False, + headers=def_headers, + proxies=None, + allow_redirects=False, + ) + if response.ok: + content_type = response.headers.get("Content-Type") + info = response.json() + items = info["items"] + if len(items) == 0: + raise RuntimeError("Civitai /api/v1/images returned 0 items!") + image = items[0]["url"] + else: + raise RuntimeError("Bad response from api/v1/images!") _, image_extension = split_valid_ext(image, image_extensions) if image_extension == "": raise ValueError("Invalid image type!") @@ -737,23 +514,17 @@ def download_model_preview(path, image, overwrite): # detect (and try to fix) wrong file extension image_format = None - try: - with Image.open(image_path) as image: - image_format = image.format - image_dir_and_name, image_ext = os.path.splitext(image_path) - if not image_format_is_equal(image_format, image_ext): - corrected_image_path = image_dir_and_name + "." + image_format.lower() - if os.path.exists(corrected_image_path) and not overwrite: - print("WARNING: '" + image_path + "' has wrong extension!") - else: - os.rename(image_path, corrected_image_path) - print("Saved file: " + corrected_image_path) - image_path = corrected_image_path - except Image.UnidentifiedImageError as e: #TODO: handle case where "image" is actually video - print("WARNING: '" + image_path + "' image format was unknown!") - os.remove(image_path) - print("Deleted file: " + image_path) - image_path = "" + with Image.open(image_path) as image: + image_format = image.format + image_dir_and_name, image_ext = os.path.splitext(image_path) + if not image_format_is_equal(image_format, image_ext): + corrected_image_path = image_dir_and_name + "." + image_format.lower() + if os.path.exists(corrected_image_path) and not overwrite: + print("WARNING: '" + image_path + "' has wrong extension!") + else: + os.rename(image_path, corrected_image_path) + print("Saved file: " + corrected_image_path) + image_path = corrected_image_path return image_path # return in-case need corrected path @@ -761,15 +532,7 @@ def download_model_preview(path, image, overwrite): async def set_model_preview(request): formdata = await request.post() try: - search_path = formdata.get("path", None) - model_path, model_type = search_path_to_system_path(search_path) - - image = formdata.get("image", None) - - overwrite = formdata.get("overwrite", "true").lower() - overwrite = True if overwrite == "true" else False - - download_model_preview(model_path, image, overwrite) + download_model_preview(formdata) return web.json_response({ "success": True }) except ValueError as e: print(e, file=sys.stderr, flush=True) @@ -947,8 +710,8 @@ async def get_model_list(request): if image is not None: raw_post = os.path.join(model_type, str(base_path_index), rel_path, image) item["preview"] = { - "path": raw_post, - "dateModified": str(image_modified), + "path": urllib.parse.quote_plus(raw_post), + "dateModified": urllib.parse.quote_plus(str(image_modified)), } model_items.append(item) @@ -1016,116 +779,6 @@ async def get_directory_list(request): return web.json_response(dir_list) -def try_download_and_save_model_info(model_file_path): - success = (0, 0, 0) #info, notes, url - head, _ = os.path.splitext(model_file_path) - model_info_path = head + model_info_extension - model_notes_path = head + model_notes_extension - model_url_path = head + ".url" - if os.path.exists(model_info_path) and os.path.exists(model_notes_path) and os.path.exists(model_url_path): - return success - print("Scanning " + model_file_path) - - model_info = {} - model_info = ModelInfo.search_info(model_file_path, cache=True, use_cached=True) - if len(model_info) == 0: - return success - success[0] = 1 - - if not os.path.exists(model_notes_path): - notes = ModelInfo.search_notes(model_file_path) - if not notes.isspace() and notes != "": - try: - with open(model_notes_path, "w", encoding="utf-8") as f: - f.write(notes) - print("Saved file: " + model_notes_path) - success[1] = 1 - except Exception as e: - print(f"Failed to save {model_notes_path}!") - print(e, file=sys.stderr, flush=True) - - if not os.path.exists(model_url_path): - web_url = ModelInfo.get_url(model_info) - if web_url is not None and web_url != "": - try: - save_web_url(model_url_path, web_url) - print("Saved file: " + model_url_path) - success[2] = 1 - except Exception as e: - print(f"Failed to save {model_url_path}!") - print(e, file=sys.stderr, flush=True) - return success - - -@server.PromptServer.instance.routes.post("/model-manager/models/scan") -async def try_scan_download(request): - refresh = request.query.get("refresh", None) is not None - response = { - "success": False, - "infoCount": 0, - "notesCount": 0, - "urlCount": 0, - } - model_paths = folder_paths_folder_names_and_paths(refresh) - for _, (model_dirs, model_extension_whitelist) in model_paths.items(): - for root_dir in model_dirs: - for root, dirs, files in os.walk(root_dir): - for file in files: - file_name, file_extension = os.path.splitext(file) - if file_extension not in model_extension_whitelist: - continue - model_file_path = root + os.path.sep + file - savedInfo, savedNotes, savedUrl = try_download_and_save_model_info(model_file_path) - response["infoCount"] += savedInfo - response["notesCount"] += savedNotes - response["urlCount"] += savedUrl - - response["success"] = True - return web.json_response(response) - -@server.PromptServer.instance.routes.post("/model-manager/preview/scan") -async def try_scan_download_previews(request): - refresh = request.query.get("refresh", None) is not None - response = { - "success": False, - "count": 0, - } - model_paths = folder_paths_folder_names_and_paths(refresh) - for _, (model_dirs, model_extension_whitelist) in model_paths.items(): - for root_dir in model_dirs: - for root, dirs, files in os.walk(root_dir): - for file in files: - file_name, file_extension = os.path.splitext(file) - if file_extension not in model_extension_whitelist: - continue - model_file_path = root + os.path.sep + file - model_file_head = os.path.splitext(model_file_path)[0] - - preview_exists = False - for preview_extension in preview_extensions: - preview_path = model_file_head + preview_extension - if os.path.isfile(preview_path): - preview_exists = True - break - if preview_exists: - continue - - model_info = ModelInfo.try_load_cached(model_file_path) # NOTE: model info must already be downloaded - web_previews = ModelInfo.get_web_preview_urls(model_info, True) - if len(web_previews) == 0: - continue - saved_image_path = download_model_preview( - model_file_path, - image=web_previews[0], - overwrite=False, - ) - if os.path.isfile(saved_image_path): - response["count"] += 1 - - response["success"] = True - return web.json_response(response) - - def download_file(url, filename, overwrite): if not overwrite and os.path.isfile(filename): raise ValueError("File already exists!") @@ -1232,13 +885,13 @@ def bytes_to_size(total_bytes): return "{:.2f}".format(total_bytes / (1 << (i * 10))) + " " + units[i] -@server.PromptServer.instance.routes.get("/model-manager/model/info/{path}") -async def get_model_metadata(request): +@server.PromptServer.instance.routes.get("/model-manager/model/info") +async def get_model_info(request): result = { "success": False } - model_path = request.match_info["path"] + model_path = request.query.get("path", None) if model_path is None: - result["alert"] = "Invalid model path!" + result["alert"] = "Missing model path!" return web.json_response(result) model_path = urllib.parse.unquote(model_path) @@ -1247,16 +900,16 @@ async def get_model_metadata(request): result["alert"] = "Invalid model path!" return web.json_response(result) - data = {} + info = {} comfyui_directory, name = os.path.split(model_path) - data["File Name"] = name - data["File Directory"] = comfyui_directory - data["File Size"] = bytes_to_size(os.path.getsize(abs_path)) + info["File Name"] = name + info["File Directory"] = comfyui_directory + info["File Size"] = bytes_to_size(os.path.getsize(abs_path)) stats = pathlib.Path(abs_path).stat() date_format = "%Y-%m-%d %H:%M:%S" date_modified = datetime.fromtimestamp(stats.st_mtime).strftime(date_format) - #data["Date Modified"] = date_modified - #data["Date Created"] = datetime.fromtimestamp(stats.st_ctime).strftime(date_format) + #info["Date Modified"] = date_modified + #info["Date Created"] = datetime.fromtimestamp(stats.st_ctime).strftime(date_format) model_extensions = folder_paths_get_supported_pt_extensions(model_type) abs_name , _ = split_valid_ext(abs_path, model_extensions) @@ -1266,36 +919,36 @@ async def get_model_metadata(request): if os.path.isfile(maybe_preview): preview_path, _ = split_valid_ext(model_path, model_extensions) preview_modified = pathlib.Path(maybe_preview).stat().st_mtime_ns - data["Preview"] = { - "path": preview_path + extension, - "dateModified": str(preview_modified), + info["Preview"] = { + "path": urllib.parse.quote_plus(preview_path + extension), + "dateModified": urllib.parse.quote_plus(str(preview_modified)), } break header = get_safetensor_header(abs_path) metadata = header.get("__metadata__", None) - if metadata is not None and data.get("Preview", None) is None: + if metadata is not None and info.get("Preview", None) is None: thumbnail = metadata.get("modelspec.thumbnail") if thumbnail is not None: i0 = thumbnail.find("/") + 1 i1 = thumbnail.find(";", i0) thumbnail_extension = "." + thumbnail[i0:i1] if thumbnail_extension in image_extensions: - data["Preview"] = { + info["Preview"] = { "path": request.query["path"] + thumbnail_extension, "dateModified": date_modified, } if metadata is not None: - data["Base Training Model"] = metadata.get("ss_sd_model_name", "") - data["Base Model Version"] = metadata.get("ss_base_model_version", "") - data["Network Dimension"] = metadata.get("ss_network_dim", "") - data["Network Alpha"] = metadata.get("ss_network_alpha", "") + info["Base Training Model"] = metadata.get("ss_sd_model_name", "") + info["Base Model Version"] = metadata.get("ss_base_model_version", "") + info["Network Dimension"] = metadata.get("ss_network_dim", "") + info["Network Alpha"] = metadata.get("ss_network_alpha", "") if metadata is not None: training_comment = metadata.get("ss_training_comment", "") - data["Description"] = ( + info["Description"] = ( metadata.get("modelspec.description", "") + "\n\n" + metadata.get("modelspec.usage_hint", "") + @@ -1303,17 +956,12 @@ async def get_model_metadata(request): training_comment if training_comment != "None" else "" ).strip() - notes_file = abs_name + model_notes_extension + info_text_file = abs_name + model_info_extension notes = "" - if os.path.isfile(notes_file): - with open(notes_file, 'r', encoding="utf-8") as f: + if os.path.isfile(info_text_file): + with open(info_text_file, 'r', encoding="utf-8") as f: notes = f.read() - web_url_file = abs_name + ".url" - web_url = "" - if os.path.isfile(web_url_file): - web_url = try_load_web_url(web_url_file) - if metadata is not None: img_buckets = metadata.get("ss_bucket_info", None) datasets = metadata.get("ss_datasets", None) @@ -1335,7 +983,7 @@ async def get_model_metadata(request): resolutions[str(x) + "x" + str(y)] = count resolutions = list(resolutions.items()) resolutions.sort(key=lambda x: x[1], reverse=True) - data["Bucket Resolutions"] = resolutions + info["Bucket Resolutions"] = resolutions tags = None if metadata is not None: @@ -1349,82 +997,21 @@ async def get_model_metadata(request): tags = list(tags.items()) tags.sort(key=lambda x: x[1], reverse=True) - model_info = ModelInfo.try_load_cached(abs_path) - web_previews = ModelInfo.get_web_preview_urls(model_info, True) - result["success"] = True - result["info"] = data + result["info"] = info if metadata is not None: result["metadata"] = metadata if tags is not None: result["tags"] = tags result["notes"] = notes - result["url"] = web_url - result["webPreviews"] = web_previews return web.json_response(result) -@server.PromptServer.instance.routes.get("/model-manager/model/web-url") -async def get_model_web_url(request): - result = { "success": False } - - model_path = request.query.get("path", None) - if model_path is None: - result["alert"] = "Invalid model path!" - return web.json_response(result) - model_path = urllib.parse.unquote(model_path) - - abs_path, model_type = search_path_to_system_path(model_path) - if abs_path is None: - result["alert"] = "Invalid model path!" - return web.json_response(result) - - url_path = os.path.splitext(abs_path)[0] + ".url" - if os.path.isfile(url_path): - web_url = try_load_web_url(url_path) - if web_url != "": - result["success"] = True - return web.json_response({ "url": web_url }) - - model_info = ModelInfo.search_info(abs_path) - if len(model_info) == 0: - result["alert"] = "Unable to find model info!" - return web.json_response(result) - web_url = ModelInfo.get_url(model_info) - if web_url != "" and web_url is not None: - save_web_url(url_path, web_url) - result["success"] = True - - return web.json_response({ "url": web_url }) - - @server.PromptServer.instance.routes.get("/model-manager/system-separator") async def get_system_separator(request): return web.json_response(os.path.sep) -@server.PromptServer.instance.routes.post("/model-manager/model/download/info") -async def download_model_info(request): - result = { "success": False } - - model_path = request.query.get("path", None) - if model_path is None: - result["alert"] = "Missing model path!" - return web.json_response(result) - model_path = urllib.parse.unquote(model_path) - - abs_path, model_type = search_path_to_system_path(model_path) - if abs_path is None: - result["alert"] = "Invalid model path!" - return web.json_response(result) - - model_info = ModelInfo.search_info(abs_path, cache=True, use_cached=False) - if len(model_info) > 0: - result["success"] = True - - return web.json_response(result) - - @server.PromptServer.instance.routes.post("/model-manager/model/download") async def download_model(request): formdata = await request.post() @@ -1439,7 +1026,6 @@ async def download_model(request): result["alert"] = "Invalid save path!" return web.json_response(result) - # download model download_uri = formdata.get("download") if download_uri is None: result["alert"] = "Invalid download url!" @@ -1463,24 +1049,14 @@ async def download_model(request): result["alert"] = "Failed to download model!\n\n" + str(e) return web.json_response(result) - # download model info - model_info = ModelInfo.search_info(file_name, cache=True) # save json - - # save url - url_file_path = os.path.splitext(file_name)[0] + ".url" - url = ModelInfo.get_url(model_info) - if url != "" and url is not None: - save_web_url(url_file_path, url) - - # save image as model preview image = formdata.get("image") if image is not None and image != "": try: - download_model_preview( - file_name, - image, - formdata.get("overwrite"), - ) + download_model_preview({ + "path": model_path + os.sep + name, + "image": image, + "overwrite": formdata.get("overwrite"), + }) except Exception as e: print(e, file=sys.stderr, flush=True) result["alert"] = "Failed to download preview!\n\n" + str(e) @@ -1546,7 +1122,7 @@ async def move_model(request): return web.json_response(result) # TODO: this could overwrite existing files in destination; do a check beforehand? - for extension in preview_extensions + (model_notes_extension,) + (model_info_extension,): + for extension in preview_extensions + (model_info_extension,): old_file = old_file_without_extension + extension if os.path.isfile(old_file): new_file = new_file_without_extension + extension @@ -1600,7 +1176,6 @@ async def delete_model(request): print("Deleted file: " + model_path) delete_same_name_files(path_and_name, preview_extensions) - delete_same_name_files(path_and_name, (model_notes_extension,)) delete_same_name_files(path_and_name, (model_info_extension,)) return web.json_response(result) @@ -1625,7 +1200,7 @@ async def set_notes(request): model_path, model_type = search_path_to_system_path(model_path) model_extensions = folder_paths_get_supported_pt_extensions(model_type) file_path_without_extension, _ = split_valid_ext(model_path, model_extensions) - filename = os.path.normpath(file_path_without_extension + model_notes_extension) + filename = os.path.normpath(file_path_without_extension + model_info_extension) if dt_epoch is not None and os.path.exists(filename) and os.path.getmtime(filename) > dt_epoch: # discard late save @@ -1646,52 +1221,12 @@ async def set_notes(request): except ValueError as e: print(e, file=sys.stderr, flush=True) result["alert"] = "Failed to save notes!\n\n" + str(e) - return web.json_response(result) + web.json_response(result) result["success"] = True return web.json_response(result) -@server.PromptServer.instance.routes.post("/model-manager/notes/download") -async def try_download_notes(request): - result = { "success": False } - - model_path = request.query.get("path", None) - if model_path is None: - result["alert"] = "Missing model path!" - return web.json_response(result) - model_path = urllib.parse.unquote(model_path) - - abs_path, model_type = search_path_to_system_path(model_path) - if abs_path is None: - result["alert"] = "Invalid model path!" - return web.json_response(result) - - overwrite = request.query.get("overwrite", None) - overwrite = not (overwrite == "False" or overwrite == "false" or overwrite == None) - notes_path = os.path.splitext(abs_path)[0] + ".txt" - if not overwrite and os.path.isfile(notes_path): - result["alert"] = "Notes already exist!" - return web.json_response(result) - - notes = ModelInfo.search_notes(abs_path) - if notes.isspace() or notes == "": - result["alert"] = "No notes found!" - return web.json_response(result) - - try: - with open(notes_path, "w", encoding="utf-8") as f: - f.write(notes) - result["success"] = True - except ValueError as e: - print(e, file=sys.stderr, flush=True) - result["alert"] = "Failed to save notes!\n\n" + str(e) - return web.json_response(result) - - result["notes"] = notes - return web.json_response(result) - - WEB_DIRECTORY = "web" NODE_CLASS_MAPPINGS = {} __all__ = ["NODE_CLASS_MAPPINGS"] diff --git a/demo/tab-model-preview-thumbnail-buttons-example.png b/demo/tab-model-preview-thumbnail-buttons-example.png index 0eef0db5916f0b65987e543b0fda26c1b5fb81d9..8f96ba6e6adff439521ac091795ae5641a6ed0cf 100644 GIT binary patch literal 73525 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 fkMBJ zk7KU+DwXv`^Gnf&@qwKF6|et4O?4m}(ooOiUY+E!K(})Zh1aS^$~ge(Qp&oRj>aMr z8T5xEP%TG^%`)Qy3tupU9NAmQ|eeJ68QE zKT3?HG&I@DvjuSH2XaH-0Y54%J!K|K<*B3*abzYk+X^!rsE#^OA^nECgBw+$Sia*| zOaQXnBfBySo~Abrm7gqcqJRNrwKg5vv6yCLoTX+2RabpAeqBbcP^d&##ZbW;yT%6X ztx0rq7V4-D1JtBqM(|Ml%^VPybnZY$;J<)h|1A5gGKM*5p+PkfiO}q5%Ezzg?(3b? zmp{dxrY+mvZQ8(P|8EP0Eb?z|TldHkiu0P#B-r6&iU-#jyr=lBi~ZLLG4CgY#^9c1 zH2v%JG9A+=b6wUNb7jf(8y2G1fZ5PI2<@lC^=w_QTpnI6Cz1jOM7x|odZCy*oOQ@N z$w*b3dTF0V{hG8#KSKWF&v+e4#3TRD{A7G&0-e};-MH8OH6irZslcDcjDE$j zY{}(KLpTqoMh2Zurq|r@A1cLJuq8u9qHec*3c6m?qlC(dTKH?JYXfbFTbo6lF2ER> zC;B*7nxJE(*PjCacD6}J!Mq;ROPxU1oP8;Fex5O$G*01rDJbf9o1^|T;*PzkjJ`K_`_o8aQK2o!fDOJ9kz2*`;jj2QV!fphKfh_05$7~%xwRCJ zTvmHF=b%P%ZocbQ8ogv>CZ1GgGl{KW`0)>;!q=velJc_ zYKnARIIXms%JNH)BY`2hvInT4n-gfi`=DNHP*cHdy9Th-Y(eqV;f=A2M&4m+=!Ot@ zs*l;M_-D47Ty2HQmqWxfh6@_{W5BQ{o1MrtUk{H{-XRCNKgGy4fcQYo z?D=b3qFt@cP)Nw+0{{R$N1xW}Rvi{kNGsnSc{cL5XT*a}QF`^5Z^fj<3MZFR;gP;z zWFNLqi0J^{D88crk62`L@QQUPbGk6dHDw_4f-@){=dEYc57JEs7qQWsPeJjO)veua zC5|1_5C}`X*2MY9q!QL-S7+zI9ec>?nNOO7g+>^$5E%Lw_7}dQ62j$WC)a1@QK1je z9Q0?ncn7FFR9zj(Xd{awXCXF~)JWQ6*@N{IEv6FoIbsPIZ{iE`?p{!V7QH4AN7&L(WY<`bNohZ3b$&F_f^u2-zOhQxTx2-aSnc1 zk-%=3iHX)Dzz!7!y6k#Emy=vH60_LYoA?%~IBNGqT?IF#sop(afDSMVbx+qs61L3f zjNa9lSMzXa(Fb^&6Z}|_yZc=gC7ncWyB}&J73ZJ&FOF{Tp zdgrUg^r0@6QT5lJ`vTRLr2}rcwaMBgP_Q}-IOiN| zfL_9AgF%|n0dQLyYLi>O=0_Z`!aW!3QoyEfL4y}o_+-?tEBuPL+dpc^;;^JtorMU$|5_ZuJ8B2D?`x3-$bG`_n?@2b# zsgNxhxyeom{kpZV)7MD6yxmJBcu&eVkXjEXq|XqU*aAT~jc}YVydk+%Il79jWEQ8Z zxk%lo9s6U#_;-gp(&L)$o{#9_Y2{3B{5%g^1hsKSGp1GhC*8-qlioNzUq{u zd7X-cR@goi{py%bF5|*{t)W4z32^KO&E(a!5#0LOS%AQ3m+^96lNoPJu7+bZ8^DWd zL|7E5GbFd6dYM#AWx1Ky9B{PT@>J=}F5$|w3MxK=N|gD>Pmb(UF!Uz?8V_Q(ka*qSaXg8?_%vFoA-Z9R8DAqZkbU!Vbu=WjW;RKx+wga zpYvQ*-`Lnu4Wd?-HWXQDpl$X7fO*lq2-8M+h<4p z?x$;g0PaD84;=%3(s4nYgJo>U23h+Q3z6a?DtTxG6)3n)&o2d;4=FV*m$p>NOBrAM zqn6atAr{a(lK<_`vxf`hQaQa~hat^(k_tZWMIHVA@&GJY;JS-#%F{&@v27j#E{@g(372x7S#= zENem#0bldEP}cRa`!AQhQ$o01l)R1;{7X}#UG^+PkaWd1=LZMtH81iitr536VrALw z71cs(uCpIE;;5$ejT7{!W(HKL?e(=Ev@jXH9#$_K%&AJGDTonmzRL8+K-D$V2>tgy z@sACo)KyVT&<*T& zYR14!Piz%K5BfIWEdKJnq| zjK-Q>5|;#VTOhjo=8)G$hkPfx-C%&r)bM(|$gO?@*kd+0@B8vP;Uhns!21k25LP#; zB?Fc?hlkNMDGq6-4?JI3IR@FgNGB7)M3hpT_>#R>@jJyb|N7#O9-bpxvI(ebxI-ID zmm3huP|B}`%q)h!iAn|E-2gV+h4tkAk~Rig=Np|N8nMG%Nm9wK3MO<#7z4xbNGco3 zCbRVD*c%vm7ruYuk>E)8sFn^l8eHLg^p4#~z&c(U zhMvT!+P0wo6e@KDEm&$K=rHFek(N0{ns#>0k!`k>hb!4n$$@60JxtvJn~FC;u0Td^ zZp{JKIA5n+kis{SX+j-8ya0#4|x3k$ph)d|GaIi6VX zSD`czFYbo$9pDkFirgXXkr}SbR}{~GR_DC{kicR_wdPb?|4YWVeIG;IfmKe3@zbHP z9;t9eK|4=Q8sIYPGa*2Zh+pH$AufOvsJkMLlKHIENhxuSC*DkO)$)yWivV zu;0z9=3f|ZNuzvhhg2qoL}BAAkfc)5@-itf@`iH*4q%&87UkS^j_;!p_Jm?~lIs&O zDB-jIgz>iRTSE1fXz3Q^=g|p|fFEkrlgAQaKB1Yl(c7VE3r7SpCor;IYTg@3asIUS zsZD(CPvW0Yn-!17D-y7~0*)}w$Csy@yUo1nFogYT#COBm_uRwX+66Dft&4 zF#UWLxA$Pgepl_I*~IXu30s*|w1oF-unSitKf~jW# z9@$kRQ8v`d%`2$W{k5`gq`JYPyaBBC{<8@vK)r-x$#_@I+UEZpBKmx$h!v@FoZ((b zWpU;`&FgqwQNwCxlRjXVUYR)ibuXxBuBn5ZxV&v94D}&#z~c<9B_Io3xr& zrsZP#)R8kXKLF;-_V3p*4vbSzG^3J!X_xf>jZq$UBv@Jbxi)<^gE$=Y+)KJ77D zR+|C%l`>boaA#MWdCTI4VWfh3?h!#C-fe84N)jn_e|Ci!m-PqWzy06*{u~`NdSnn)M)DC< zHuxh<*pgfvv^Ng242v#S3f4}qH~J&-=Wd*Q(#SxQ==)v*SR-BAMnyd+UL_R1+TjC{ z)}XIWLWM(LxA#n|N|_Ztrf5&!8S0EhdYKVj9!7+_6dpAll+xCJpyW%&>$QhdNnq(9 z&jU4Uhn z;uy^wwV3UVBVLXYH%-7NpaF2{?%_t^ar5w`P1P*Ji-TyJ2lBkL-e1?c2KaE#WtLQ? zg;#tMr{D7I0&Gj$YY4psVYF`;1ZR>`_T@hjyzTZj@b?&5JWQQQy_}9AqB~+N4yzAJ z_REypn7UeVys1`EVLXa%440!V3z9MY%GK^^XdY+Uu{`pWVYp}(P5iU9OD>D(OVD=^ zk>|LZ`rcPD0(81;-%OT@3dxJu0c+XZwJQob`}q+EVrflD)p^;tKId^=7Mr>IhH^*DnTeaC^W5C%mH;tz>n+DQm@ij>Pl6)%`~HBR`{>Du zI{~gaHy9--T^c+S^$VK#@^Ux*H>L!mT)dzoI_pA~{%+sz?y^PrluV<1{4N0naTdd&|6W^H2MsNJ7kZou zaw$q>kxfrEu)Wk}`vwHk;AsrlC{xmagSlVTz+_*$l_J0fkVHn1RWWZ|38wTG2>sXV zogogUQ}oWN4OMy?Z14wL#+n4Lz45>#v8+1*)pjE@=)nM?xrW(6-6YPY;RA<9q_Abz z_JykG=I$W(O%6Gj)MQ32siG z;BVw+v~*cBSC;ok+DE)9-abFZTOaYyz%$4zP=6C4{3){_w?@!JIq92c+>J1slk*}u zB;afx++1zbfe5Cr)?i70moFSRadm>ZM7&fZZJ)y#x!rcE5|p5BM(gSY4W1?fdPF%& zQRjw~<^O(fRbMk>2FTm%b>}n~tQ{Q2PMaq<1{DZQEM(MVd$)CHpDAoUP_A@cD|@ z@8%J3t|k53BKUSOfIpnfvxF(Ov=-Uy^CBgcjmD)xuHpG$LZH%mvqxn5K0?<~`Nq}d zeF?Ga61c)QZo)JZjj}!dUog7A$g;=zHw^n0XV{Olgr+&D5|V6I2!j@1 z5SLQXYnN#J1C4<2UBS~;G{nylPbSNk>^?jCQTE|bJbag zzMXR=SY<4Vjf6KHTnN6>ps@FB!pjQM4yN)&kq$9`{ZrXB4j{NoMdH4{ZU6w6ImLiFuv@viN5WPaNnr25AQ9$#tge#yogm$RR?fwB{vb|N zr2eYYL6)xf1Jj^g-DpkJYK3pkf0x@&$|1DukYkUY$MbiGm2Z(ECxUEz11ELX1BPKe zkI|B_h8hV*0a`g~W#ln_&WKc?r}bz1vv&m@1hUY+Te+*w9!G&Kitd-^ZjmT&|8~H( zyS9I3Qk(y{3%XHvlXqh@i%qHlxIr=ApEk%rBSg6R%LCA+Z3bh%iGxKZLk1_?nV>3l z)b~9vBDR0cqzcs+g~Y=iX9%OkC1ZmVc_l(8s9OTR750Kp!7-bq>dJhuQ=@=iq~@ir zWN=~Hi%rTL0ISNft)rua<+aMB%BDR%v%x6S%~}E$q~6iR;V;YCRxDi7Sx;=n_W`R!Y|sh@%SgC%$5TORjQQfI92n)$@9x697N_X)$8h8 z&{-R0J@ib}K5O$hTZf|fiRrq&L1HYSh&C&0v9Ip)NiuKr>{GtD3#@lgM=kd542C1+ zLlhNche$LN$9=vU!1%Z@=ONMc1CW>-Gx0pUMv_~=NKbFe-6L~LmE4hlfx$ji0{|is zYTkdN^|iCnKp(5cQUS|Tys57{Y>%%ws^c$Llm`D~hs++|9N+lD-?F``M;6VpwP79m zH3yYO4eo|*?*TyQe<8GQ1BQwKZSSFZN2lkWH{c;>y?%8q#jFre-iMSO?b9&6OCOXr zty@yqvO-~1N>o!^FmL>GR`SltnfxF5AGq9%&aQLaKA zBug7DP?<(}s6Umu`0}Y$FMOw;1=(Y2X(gNWLi&9HTH$2iv%3=fc!26GR|U&o9XYj% z5R?gZ=NY&MDgv>%iFRO2ydppo!O`r!3&1e-ul)<%xjCom~lW3-F>>d$;>Dt&fOLrjg?nMXxhdBcp7R1UY|8d=r$IvR$H%p**_Dj{0gpgh*1LT~^HerA=iD#7CBCkAKyM7WyT|Dly zfzb?;Jg(4)2I#U>b?Y#7NQ2QgrZKn1zLqkoA*oZhJjeOTwzW9@yvpj@p+Ek}7m&RN zS5ZirD4d9TEX{|BQVkH$o}R8XtiuNG1LD04{>yz(5dPfcnw$Epflt>4LT8SfPrs%j zs%2s_LkcfqdF`Q&t2Q9y8V{bn>H2w*mTpBak4R+R%P6@_p++n6+$a0Ek&@8X_OY*f zaipw&-?ih6hg7?it7=ZcM!hXKT}Rzbsm(QE`cq*W3*WK#rGLzbeh!XMq+}rr3uVA9 zJdgyy_HXhC@ReM+;@e|~7H%kgBaL_SU)zY&(4qrP%b=aG6~)PrPT&2Cp#vjlIov!c zu0P1Jr`oCs$V3HONYOM_*dJC(SPyei?UA6}Dk?cS@#K();k0)2>}@5e01TBOomquY z@aKx*W%<3>4C0Wm&lFg|-`k-BPpeI8`>F5*Kn~)G)8xe-o6AIKQ}Mz~{h0!F+;P`t zfbLiA-28lC9_i@laDbkQxrq#zi9CMq`JJ9=dQmH+tSv2s!MwdWL&x$DFB}a)o z5WUnCI6Rt{S^FZZN$M{vhe7atCq<He9F{KhO6e-6(Y)3dDbv|e(O5yY|T86V8mmOUubVM)q_Atyr z6cvssE@niJt>arjrvjTf=a~Qrg!AIFR?NnF=>U|l*3`C1u=P5tTQ*r^c6ZPQn89Jb zKub!~oTJ~avN94o|F1I=`ZzjkJ&CkWCcXydrB@zr(g1d@66(53lKlZaB`oM*s~^{Y zm_Chj=#^hPNqvnnQfPJn7N&-52Zk9il#$k83}!7qw9`}OQ~79|x1~)VwCMC9X^dkb zHED$^urLs^1z<7uE^n-_41K+I>b54-WF@~~nr#ua1 zmz&H4^SQmi^7%TkXlclhQiGe66#N?Jd|b(1T}g!`fcuy}_Ugf3aLK8vZ@Z@0H@=uov%?Jg&#n*qip|GZzo2cB8t{qWE)(bGV-$8V>dtm%e?K7b-VKHvEh zV2t-H3Y^>dliYr`waZP8I?H>_ud9xW7zRg8YX(=!;@KotV(QYQoQz@~HwcQ;P6-ZC z`mlL;9s-D9(SYHeV#yB6G4wSSWv<1Kik9^+WnoAOL$_4N7KM1W<{T}?2nt;{sai~M zQcR=u8-LD2R7Ib{08Vmhm8{MHPHT5SpI65qe};Gvh?l=wp2@)S#L1Ye%S(~Yj3F;}PB|v$G}i{tMF-Sh=~?Oz7{lCx`XTuBM6&mEa&X z#s)F+kvuk~fUFa!+6$hG$Ni_h0sg4$8nGTT^(-=nrSs9v_Q1AfZ~M}s^Nr;eZ4ljH zYC{cP$7=o?HY1bjwAjk(w4)^om|vM#<)Z^fb_B*=0Q(GMG(yfet;DHWHuxX+UwOXs z3}D&3{G!t*9jQ&C7u&I_u%`jbahd^AiG`_~TPp3wAe&d{IajQJQ#+FaXMmU2cecPg z@5e`LV>N<^<(wm-QtZq3W*+lwotB7npUCCgrUB?galiEA45FN77_~(M%fOI+AD~S7 zm-sU*`j|UshXy_!PjUY3#B26a9jBBrJS5LN#09bM89{hQ-PpkO%n;Y9Ve+-CGW{R9 zd4>R+pLy8$5ws_gS8uM1K@2Do`OKRP{zw)K?n&6QREOz}-q4{aMyn`N_l~tu*kk^y z7^=?S8cuw0DwlCl71USYn`Rmvhr4Zc-|GO!yl8Rc;{wqXpiAg@qWH??+IX%hd)>$J zNe5CC2Un1pJhkE$RaS2%$|9yx#9??&u6I)?#^cyFa=ljM@%`0saSfn(FljRYa>T>n zjxxHlOZoMDR-CM3K_Nt)|(+oeiEOZlHF&VR1ydz(%me_=2_K?&NafY<0FAz&T}Y9MzU;4ZgPC-J=<1I1V-8E}w4(kV~}5eb5?NT$FE~ z%~<&c5YtuxFBEsc*z0aaq_2Z2XBVSW0;8nKW4RfavE$>DAz8RVkvJFgyv~EaJSbiz zmR9@Eln}j_{y5Q?zWI+b{Ga`2sT-#zfrMcUbvzfZ>sB&yr!bk#HRkea{%ixM9Q?wK zL^!hpkuihWWmxWB9pwG(c1ptC-ph5u2hToO;ENz&*hN~jfpku*uc^h|H{25AhpddC zAh9rqo2FPUG_Lg-r(Wh&drisD_qtA2Tyq|?JOe3 zAXgg`dHE3iVYCNQu3iQ8IXY>*DNokOW@@RTDb_cH|K8=xGJpg0`N4T2bz&TsS zereoa%n!Ip#a;^(MJWQMj}b1Pq}QBmdlD>)D_76{+V7>%d;jKNympP_G|B$8|K!td zeuC(87@+9|f)-%dCH7{cWt9CgQ@%h5)ySPG0^Zj;1V3bNahSXjCfD=g0fL2QdXByz#WRLvrgtr5w9kBpCvD5cFlVmr0q7F%llE zG6ub7r^F?EJ)PT!har?Nw~>C=2iP_pKqBzR2`l#munee+;L9Pp9B^Bij`1SDc80b> zm|P8JL7%|#C35=j!e{6;jV}2tjec1VY}jA{-&#bCJ-`a~@R#kXxbP4f*`-0RuN@*g z(45KKx}YD6Oii{ZBG}pQ)z+c|^R;)I_pDEI2?8~C^@JPP{9xCV{o$LXd&#!2r-{o` z!y21$^Yv9+Xt61+I0~1N+?DTi$Yfc=Y{!qACZa?N^FQqa9R5aXY^C~B!?GPO&62(<1dxWF}H$^9G6}Aqp3V$B8A53UY3PrCnF9yCp4IcU2TF^)I0vYtoa{Hg-*P{!!jXWrb(lj; zO%q=yd3L(Uthjlqaw>-eZw}exwsr5_U{+X+m1a`6v+XkC*bYFQlvYpw{7dP^e@!Mv zs|BvL&wha6aw^J@Un>E?g90IVEA88?PnTKNPPJ9@DfFFgNc z9(ADjJeyCXX=vKh_(6+&Qvs765k#`OMP;;+!>G6DLyX#Euc~%J8ZI=~eEkMXsuZ=W z08y5U_kv4cAj7QXOwzkI_)j~&T(Rh7wFA_oQU_-@5KR_(j|xF|4ecD-3_z-+p=itW|{FuM&OWvOTkJ>wDVoe1yX1sPXV#-vLG=- zvisJO=8T}6Vj%H19oYUD2?buG$7&tCSi)4=w_EFl>Rw>JlRy2UN#Ib}vqomV9HzIo zC$zUWrd+0d4i||anqf$e*FKakC<%`kwM%P{R!T<06QlZ$lCxGg=x^opcN0EHudp5N zDbTa{2NI1RJ12IhJq*i@cx879lXGoV#bu)KsL?!=KqVm%1VV?|L-9N+s@#eE*Y_lD zqZ%# zF-gV~i*pAlRDsr6;;)m;uVVl)jeV-+r?N%U%(Di{RFVsmh1`55%1s7MB(osm3v0If zI@5luj=rO19h+>Z!=1?LPD*He0DmSrb%Chz&hZ15^jcmczoC;7!%z5>0HU{k`z8*- zcbyVigtgk&Nj56@ob)h?aMZf?l#BD7G4K@8G+eQh9XSHoO@XT;qY2!AkPahYfQex& z{DQX(jcc|aBJZH4YhY0XD6Q2nZ+=T<#Oiv+>8r2Zs_)wH^)c;P(_;vu-6DWXnx=DM zvNgC@*YNN&@vuO%X^SgQ)hUqudF-X{;osq0+>1&17Fk5`qQruoZ-L1OOP6gX?l=*j^2K*5x(y?n&S_W}$uf->;!RL1W!ZdG6IL?ul1?Dp^;oOPzGMwFl$YZj39Ay(UQjsndvJLuy%{=F1&C?&!9>0 zzlc6ij-)2!2rJa$VfxM=x#$p4?{Nx#D^5y{At>+z(V+xY2%)(HQ)23RUy?Jl=E!rH zPT4!n4Qjh4&tc{g(ES|mDDn z#=5f4Q%8iYHV?V!6;wZ%+H`;c6fjfA)Ev2O zAx;|?VFW}G-{MRU|7pEC`LdbO&aNPjQyeMx9bk3%X%`)VE{RV4#r6e1BVGFU&N57% zj`Q~P8$S*fY)w8NlNuP*B;vVv-+)B@UQixS`(Jw)Ho$&yS5pj?izFzwBnT{bj$cc(jM8TZ^&_svrQCGJgo_wbm`x3gvEfYxS zY&zbvZCMt)<)iTK(#~zreNWWd-aUiHO|8U`^A}s|dq?O)VDt@b{PRbjzdNV7*y5@J zk6iZb9`~-4z7c1YBg50%tDGZ-lU#6DnUn8W(%n1TzJY&fmZEggTu+J|SHp!gpIo!9 zMy3v$wxCVP%*d#vVOeVJJDFb+gC;TKw6kTF%O|ZkZ@brD+KD6fK!Rn%WvKv7`u%%t zz`|%>AmP0?m@MK_#T&}C@hk7U>2Px;vqQ_t@0mPYY+OXjxA!)o1^7(PDLpGqy$~3W zu|e*p@$-)HAMc(gOuzMFMi%tFjok3wx3_%rqqMYsFHhdL*UJ?C>%g0Bbc|a&qMCS` z=(oUiEhe2qG1eW58sDY(7O+%!B&=<{2MmBAdRqI2XT*ug;>$c+#p}N0Ha4b>$b&Zk zAS}8OGubn6!PXZOd|;bYm1*J~EPs@_O!xlZ+B<0)e^y##0rP z8l$y?`r!)wy1@wl!!*=+ih+YjE5)T82Uw@)zj*2%dBiwgOFaMqL zA) z<8A*L~VoH=J_hS2B@Es>%NAk!(fYFJyGCCGezb zJz#UvpqDmly%ivv5hWtOaz=fhn&&{pZb*#T&+@7dW#D%|A#yWLHLv%6yNva!Pr{Te zDn>2=B+w)h0h*8)$vEm-^ihEDQYoVRZT|0*+u??Jsv!!`uDN)vn-)G%e1HQsn>_0TF`yI^x&XgMNfgGCc4MhDT>RGtOM%T>;sm1@NySI#r zE85mX3nzqNA-F@31gqdyxJ!^gutI~oyKC^^L4pK#f(0v_3J^TO-Q8W^PR@Pfoql~! zpVL43Pp`q)z}U5Gt-W;0H|K{V{u4n3Mxpw{g+gc}l2{eL#rK@VCgJG#idJ+IT3aTTp8PDErzE4-Q+g`mNE!QaI`v}*cLhE#F8FxzUVI*?B8KWIOKJt`r zT<(C0hEuJ1KnB(k0iURLSP~iuHWye5b0yDL8M$beJgP2r*c9mD@M|(4*;vA{%}1i{ zEpXPbaw5u3fz+al3?6(lT-FRHGZP97!CvL_E%v!Yyt45aThDtb>j_eH1>1t0{cZ8^ zG}X`gk*2-t>|iMnzlaMgwd)0ci}PHa$(s0C-%1SjD8qI)&5pzflDXGLefj7b8`WAP zt5Ay_u2EQ`Cx{~Cg=Q(OsPWdQTl55?i{h8TuS{>#Cj4}Z-n2^l@DFZ^OL~DVz4kka zK?n_%`kf@e0us^-Oq0bPOtGId+^lroxDRU z939^!91j#$E4g`52>8X1XI&JF!?)kYhY~~DoUvppwh^#)yh9&1d@7&nAiXomsc}B3 z()lFFz|??308U^N9k0Jml>$P-DIG8QiOr(1I>wZD6XLO)%1elWxa+h6(fMC9Q_JNY z$H!dv;JG+n+^vi_|se|xZAavJnYnya>NZHT&Q4V!nea%d>*yAX=dEIzzz>H{I8=2DH~1@dGprT zIV_KvTsNnSIkGdijI3LNmx1whWbTNPp3kIZTmoX*Z|Xvmo5?$&jCojna@{r57-%uTjdUg@Q~HH#GwuD=Q{+u z=L9K)DZFjGaBs*!jmpodeYsxFjI*c7iYLjdwBz}Q%WvsCIPbTAUHjZkpL>XfH!5Dj z24)^QXaf&N>&Q2p$_K)!$pmYM#73pidWq(*Wr4(Mk`Yf9(11Z`m_gP0c@<%FaKx22 z&{HIUA$|`BY@xvwR;RljZBz%w_ud5-C96l9+gmNdcxN%hwrHYDx8zSbYF&nk4QyuH zHOW_+HJKfa1Mh^yqlZOH(g9EnIE&0FHNabH?+Y<(}Gi-D*DQMzkY2 z`%(G)Y^{)_psR3e`4;QkHnO>yr%DPq9iD3%kNgs7tzjlQB#1p{kUb&81Lj8;w(y<* zy5q;+mLcC5u?gOdzsnHzS&n?(Y*6UB7ZbDjfnjTz4>C9Hy*>noV*VVP3nB8BmVo`VuzB^bFKgAujhs zUCXFCmGakF)F69I#c;uX?Mne+^mHF;iL=O|u!gTugqgQf{?2;)Ron4-$z z2;i4x8l`h``fdc};Bawx{oV9_6NMtwxM4O2aL9&Q?2+;AYo}(RfdHYv0m!g7U$KDA zCZsYTA%W=~zD28Jkf|qQp(rJXFtHuiNhBn;XJ{=JC1i9WgYGZEYi5`k1#MG3Y5W}E zyAA4PpFZcU&L$1~0)OuEP>q`f3*Ex~iiSfSZ}0brD$+e($dfwQ?_e97>D)j91Botr zXs(X9%q*8P$^+5Y0tWfADv!R9(X5HjUNZB1H#G?;hmJT%=t{lcr2XuhMtsmyjeZFn z%*@-gg(vr60ZGSGhq+K}ik?ghr|l6|UJnD*46ZdH*a%GYbCrjq=kuCHti4gq3L;p7 zPSw}e+|ueA{A3(x;)m`Dl*?u(Hav7|pJrOVzIFDzk;fBVTiVqTi&RSjFYln;= zS>(uPPZE9&^*OmgE1N^X+kBT4Oxw0&as9l=e3o!V2%*yw7GLsi{K4 z*Nr~4p{-s9x2y)qk{-}6Is-u3I~es5vFb%ZG&#t?#WnP_#_89&E#}YKn%P1e-RGlB z*0v&NeZ7Jfm@*Uv?RjV>AOh40O(IQAhoT5#3>}N|D6VisB7Biwf<87vr0`r5MF$QK zZs}jm?P%pLUr`0$FwrFY(;?6}EN02Ad`It4K4Z4H`$Tu`N7;>bn--MljP*7=Eo~J8 zX;;qK=BX3)pTx_ywiUQyVzVA1KY3s15o#h5wI)E-UwDUK9mlebaFSEeFD4CfA;_L& zOSSWhVtOn)S5f`G6e_o#A=K_}$tH8OUYUa0n3oG+rYWFpvP3^B#teDLJ-Lae?|3(} z*hk@o{G)1>5bk9V7HJ9nP7mH{!ctc^fH6|zQA?Ta($QYKU>NyU#Q85s@9hvk3paE2 zJ)Z@}>%Eq$RVHVeWRtYv(rrRK{U&BXzO#?DX*Mt?=8?tk(b7=QCY|yX8n-=JyE>h> zyQJLi7{@^$iyS%LF0{NHEbl>g#e2|H-&Sz$k1P_kAoD~2&GhulqFAaP%G7YWtoW^? zlYP>UvjktFl%3TlSUf1SIO1YkE=oh*_5LpchBGHlC>CM3(qjgTmk0~e!8p~Wq``5+ zYPOW+%^ugO4DBxnBu%JMw|rv1IeTorS#+1dMGf3S>h>s0eyYjg9m9^Q!sI3rg>#iy zwX1ENM&hzalV-6Rv+eMc$%RJ7L*&RC0%Xify$if{an1d>m4$q8h2s++8Up?Cw7g3H zsBbxUC?X(0bn-$5f!&CDG`mztP6t76qyd2mw19S%&BVy3MbUNEK?FLay@61LCR({; zjoUka#-qZcT0yu1UlHqDJ;>oXQ!_HLH9DIa=?8k_56M;#_eZ+uB>UHy&k#T-JNVJe zSo%AcdGv+gWv`swUb}13qQj*7p$9a0@#wCKL4&qo(D5a|`-VpXo7vTs6FIbOjTclR zl>FUm4z94kYLKcwCPLxX{3>{hI2}iZ^%qw77S1RVoLFG1s$$6(&pIHe-}}e%Ng>c9=`Y*_$0o z>nbA7Cmg&UbKuk`GDqRX;$np^&LLC<5Pf;-VeU@D%?RqEPhTflJqQ&sRXM{|7QGa% zGe2%&rRRa0Ib{P~uoSGb;YSYWMSMs$!Z&!xMITcnK+lE%ml0WNNZRkI0dJTVd7g>Dy4IgtxKZ&BkhaZpfM z-E{j!mE_>D_TS$r9Afmwz(mDtO$4To1NwOO8Qiwu;nZlN#@r(#1UgpGvAA&>)3#U| zQ)U3;vQKq>KH1h0NhqAND>MUX*9?MTA3>-@4Qvor%MNT`W?Kl{0q5EkfUX3z7b9TD z12k+1stjwyg6+i2ndk>h*O82=r`SD z-jfUmn-4E^CZp3FQDQej1hHssA@+0($ijU=lcIWOQxw?eqj`;5^4Ppx@H@dhRvWP7j@#$ncqKM6k8NY5#?c3ib_z?cf25|sH)Pa z%)k*e!mN^_*n9nw_>$*zb4KLDl*3@L5qg|=5DgVICQ~$yrtvw+n>W)qigX=-p{NXpQ^VL!%_YM zIDfD<%X}Zk9@6F-lFa~(f$5LNP)K^e^daZ&t0Fc6}9JH%QUB?mzCodk3$`Nvhha`jzM`%ES2%$Jnq;JiO7Tk|?}7fvr&3 zimY3+eeZGp#S2VkBV@53&AdjZBhr!hrxgpg_;l<3)0aXSELEBnRl4RWo&lnwvlrkE7XWK^x0&5Xfo1y_pbq8blI1`{wLxXc^1E*LeG zyTConn=^y>k%%jAQ)vL~yFv6sWqw9P;rv=>mS(B+U$IL#W>xY+2kj#aZk(qNUXqPv zQJ`d1ep$%Be|oeo!ArlYKwnk?jX@AOO4F|y?{qA=3*%uE1rQXLKIoc(gk(UbO>%1UUfP;8KflSk%U#{m8J4#}q?9x>^^;UQ>;BZ+71NOKqyB^|CyfxuqZCqB z5uEQT6-jMN`1w*skdv)7JQG?B4Oq1WYsZSPG z2j_(VvqJPjnBWKeRd!V{{UZimqDjbb+ZAFjfJq{*{J0z%P@i~tla|ZftI2$MT2nB& zKH@vGb_tv1{_a)NYuYM##&1phV{%(r$23$a6oHVC5XZQx)XmszfE^hU3Y`y!s4KY8 z-h5~+XE~WA2##eY8?XHQa2z9WD67Qc5N5KL7bWIqTiXk|4SX=vh{6UUrQLnJA|p?q zGQXF1U+fAC&rLPdNHV@rI)boWU}n6=xuK}kn_sy&C-nw$8ZO`6;rUD&)ig?@KN;x3 z0J|&pc+B3)h*vk(4{=xcCm=FOIolLI?ZmI1=bEy$$|z5k8F|;@gS6I?N@`VjAquFJ zVu1yNd^SjA-hpossFB?lx1#`coIFWwvInyN8sVrF?hR`{Wy@M^7QV}lR4RSC0^2v# z{p99%#_BbBskvA=nq;D+NP>qKw)t^&NoJl&Ml-WqIq@a;ZnN~pWuCsfqR<2}TjuwT z1;+)5_0-o65k#XSba3vj0Dg%0tOsW_!JW=~#Dd{XpT#3xO4{{{q3hJ}wWX=`URs2S zw7EV7HTBH#fIP4}a;0cU4Ho2#p9B6vL;7Vr@>R8X6{s##p{_{S3@C%7=%;){*0LyM*HTN*{w<%j!z$Zj`eAcI?3!PsoBoxlIa#`Ne z4Jfz_cOZ&$e`RCWHloCoyTDat0&q_*m33Jk082N6>yLTbvcBCBU^giOBKDn+)9E7@ zWkAjt@nx>N_?)Wo zRo^?ajUz$KMgy8d^khgzsy}QS;Vb-Y*d9N?!uON#b>ccEkYHvQ@;n&kM|75_wmC1R z5P&W^$ptX=sjIhN3e~4`anEuAL7eCmz33U$#$ok24&k^|a)H=@4a%TAJ1q%^HtoS8 z^jcB-liBHzrC6tDP3R>>>!g;VcpN9HJQz_5u;qZ$0lG1X#miOQ%;QsmZ6@}gq=^3O zsyf|Ln6_eWhVk>77g;^a#AVodSR(8&^_C?9bfD9?Ju^* zLR{*JB)nRYf94GYv03fyv;piGgZm}Wg_r%?f?&)37|pX*I3ORb9zGlhFSR{XJ`Cte zKR1jPkNUyIKfbj8smJ*M#}tZS3|%nke_E04B)c#-zk1pB*aj|@1CdaX%^g!p>nj~R zLK^&d#32HsbZ{m0DWf ztM&OWhSFb)NxKcvEwJjtsNOl^0AEpqQjs-hz+KvV6LasKqR+3k&Qff<{i#tVc4+XE z{<@llV?>$@!NecOSS`6;%N23kM0o~1@MDNHV8n9 z!Pt*iz}*yyx4JAq0$~_ob-bDWc$5={Ed&@hUKG?a{=Zm&jArRot6+R5LiqhlW+_J> z#qv{cqn`p_h=THRe43n4G|WnY;P=VRHG}S{`-7+-XFnL+4;>sF0;bEvyqyZ08>J{Y z3sSw*(QjDWFTul`ZyM)aZBxGJo29-!Fs(R8v;*Y zcwg1qnU-Umf!fKmvq@dRJ`_pPG{23r>R)eDH!YzK`16B_&ICylc=|8MDF9;Umays# zb9Zp>#HES)3Shs3PErRK)j3P;Mp{!alK7B?MeZCZhycf_hhxxh%g+K6hHVx?6skcu zoJ7C0zKa_NwIDH@VxC2fB9xeDQH4@0TsG#29u%bwE;`s>oC?EBcG=b0st8as#k zSm)|p;5HXV@!Pnn23wcH8O@h->oYR45mm1OzvOnXCm1#Inhanr;1v*n6K45@?v~28 zcsPXtnihBsh1yZHj_PXe#Q@+uGiY5{X+DHWYrW$YZf>`25M6Aj8t+AA2>K!p-Nco2 zOHxHNRY&2-veKpi?J`GM;5rtT`oJ{PT2?Jet%DpjI#TrnTo8_YejqWWXqG24M&c>z zZ1!Zfyxf|8HP{>(lA=-x72fg1=|tHPHFb;TLf=IA@_ZgrbhKaA*Cm+HuwHxqynBvlMF zG=RXo5SFEgxfT$v3D@L&?_7j;+t}NLRO_j0KsW_+pUKDu?W`LmQPNsiYWbE?FFfn8 zVyAjDgz=`AD&N0pdU;PbT@iFM?NBiS{gT?7SU*QjA`)0fun=}^-JO#TWc{4I?m;;? zI0Sfz+|7-njK_m>4rGuD&=)TOj|bp|{KNaEX?Du0hLwG4J2~a)bCn4$*x%@WKfQ?j z3L_FQq;~Q-Q&T1o8U7r>H@UiVY5-Ky?h0Fp$2Ro9qe8Y7-*cvogo~logCROeyKhcT zEpkagep#qOw*swFn1Pq*)Ifk0GC-&35CE8NH5V7Vw4vxwy$pZ=wo|KATqGzAx1I0l zX03_s5rWhi*3IIbzF*L{vMTM&92 zM54)O!s;ec!>GP<%BEY>sKG*d#m>4^!U5FC9?U-)Q&~-dz)_lO(h25QX{4kC`1^-X zSxMN(nz4dGG6$*~z0fy8EKOFU^+GfC;^-EB3r?16XWp@!LT(;46`*XJ?%Dc*{V!Z2 zfHPQ2?#;xx!3>@!W8tSnHz7O#x9<%Jd;N4?hHUI0ls^j}E``e9)Mw5SEX(`lmj>7wza3Un*!4K7VaK2YG@n&v6 zuGS+EMf&$MY0K)g-_vvr!7FQUh{kM@i3r7p_{x2@yr5TD*EWr{GeiM(^uzC-T_-z{ zL@tN%334}7a`C;e!labI5pOqb1|$Q38Fdjjm2d*3!x1EHZ%bnfW68aVc2S!aR^h@h z|4WL~YqHYc7!ytR24gJ)dBaIo>Z<*fT89rfH5}1(dq3-!Qb* z_L^lOb19ONEVN$wYGT1Q#h^OWVN2Dsw$(u5PG8?p0I8&fpBBGS7X#-LsHfwm@o-=Y z@7TPAWKt&f^5?BP2JG&>K7)o;SS@GF4ts!Cg9pD7tr^BKnF5fbVh-YT-L<>LA^l}dKrJ*UO?a(`&z*NjS) zvuzpmDQuV{01wl@v+>?0NpQ=Rw=krpN~(7`Ki>&(`~s<{N9yOVw5lg!Dy_DTxHD>& zgmyf`a_u#l35!bbz^M57L8*yIAD;bCu+=jN^2tC z?Tf#77-C@$z7_hbff_&cy>R>Kf;bxhw$h=_F-9P^@vEp$_eNTdES>Dw^u6o{etAT3Mnr@OG9rfa-pc*eEK_Gn{}R0J8oU)p!gALw@B1un9E z&vyGEN#8}NHrFts=+JU&9R)!E(Ku8eHzUn3L25G1HvEcJNTdg!3aWWJqou z4-D?wEIR&6^XFz!KVC@9>c~KK^!Gg7;UMo8u&V{fo1cbq#!K27+Gl#nC~1I`*3BM} zAJH`mCI^-yQ@T)z6Ikt6sYzW?=|vx^XhX+)_>c5^#C9BX$_G+72FYOwE%HT1nT z{^Ah9qhf4iuHDNSS||>2O897qUIi(IU36-pb3#Xn_Qk^R;Zz@{hTcdi<71hq{K0xH z7*Bm-i7>L3GKw12;%ACER}g3C%6gy5ws8atA~nU$w|AEq+kV?~hEY<20gx}hFv8rL zAz+f^H9M`)BttT%x#6tt4cmI2s46kZ4Q%1SG-1aCav(Rj3`RB+jkwt8>AI)(cr^ZQKFh*9-g=I|-0|IT~vVC@-uiq)ML zko`h5d_<$iBh1uNz!s^?$mz$5o~-(kj*#Yt+DbERae1od>Wih$=p+fwz`D zk}V>#GhnE6hHc_WZVGgTw!~ip5)YIcbvK_c#&F?o|ugcBq^S&w7PUMlyl(dKrl<-_9X{@OEKVpo@P(Zx%~0la~AGKjmg zj{w9??B`^4RKQ~`LU-+cgVW5^(#{DU^!-=H3@oZp;i5vh&KTRjOZlr|RLAr*V9t9% z5Xt9_i8ET?2th;YCF#ch19=>J&o0v>Qv8bO_0}yxoDX^Q!u9YsybwsUIUVzqw^!RJ2om*@uZ7H+#NTmmYke*tZu zm*87DaKq~ZgNz`erIQ^*eaItXgPR**AE>O8a6pFySkTO;=7;;dZ%RbeYxVsY9G<=_ z4;ahl=37O>5r&A7?LeByS)?>Sn$sQg5=YLs01T^R%6#Mwh`ru zO=$RJ%YzM?BkCr@h>>&d{D(=T{n}uoaBSi;G}s0P4?(;aP`CqB7&|VL&#p>2wHcZ zo73iR#K>#G!z~d3S&N=KUTgc*X2TEqc{b5eZoY*~`c1U)VH70h(Q?Z`j&6G=pODB? z4uIhp*m=!oq?$h7%jG-+^K&KlFC$qw_p`{qNQ%RiYl-df$lvS%ajEUy%*!3 z45!<(3dQ^R0rKe}o_80^)ywGDaPCAUN;i(vdW?7b>6Z}~iolE#ZOefZz?!_UtyB^o z^x2tL01}Gk6$3VGo;J`((q!ELs1y0kUBCmyX`VHrR_P$xnQo&ZpD|92c`zwrb-k67 zTI9A<=E5~timJDrKj{1h%Y^R_^be1wY3{|_?hWfEUJGSk&aAzqv>MHyubBxrYN3&^ zL;7>c+XBYF3NWPPJ45s~6?jL&#W<`xmXj5^b&>=*8Xa-t6z|E*kh*~2dZ2l5L#^;4tnMP*EuhLP8Dj%S!j z?1n@!VVwzSn;??e9=QcAx&h?4TmW6DgNFw|4)Ocl*SsDBPb`1wP?l%nCS1{u+@(MQ zd~mwD`}OHl0B9Mvd7qfiofJf@-RvR?spdz+z z;8Mj0WYUM$!_kGqBR9WEnoz9aHt*2s7O{B%#L0zYjH@a!%gsK~!5=hTCNWOnPn4K1 zIT`ZR@Z-rr$PulDzO3`2p~_DK$NP{=*&qbjBcG?Z^F3S5EvuZZx5A%&-uMVHNtN+f z0g`MTNz|`qa-b=s*7Z67h{?^oNon_^s+eb-DJOpFA=*f2V%5B@N@5eOX%v;aqK85+ z6>2PO7gQeVIczVmo_m#dnjSSo_y+Lfhczwa+E`h;>4aA^VhF{$sL^g{Q}qQI4Qt5b zn}E6Rrg(T$VQF3dT*3Z{h*5Q0p5!e%83Pvjs7kf-HJ~^{?qQw9!P~kVN_vW6>ER5?;CSIPkPt&coMmZjT5oAJ%ZB8LkH!h4%cJc5Hm8oH%UPDpw^X^%KzMS z3XaoB)e&V6guOiyeL7UmWxp}s;VSn8IxDi9f}yzz2t=n9`KX?6zszOZ>NrDVQ)_L@ znaT2)mmD|i0FA1g07v$FYwI9K=E@YFchR-1G(!P1MmRZY!%Z~@;FjJJ7eV*fGK;W3 zIWT=8Eq@7blXfClR`ahRKp_h}tkzpJhLqw2QI6mDwzH6DZEhb;&M64dTTfc)>Ol?b z04ET^5fm-GvbuyBK+Q`bQ|}zaCuL}u)p;4IB->9IfzzqiNlJ-Uz3xrf8gbhiwz6Q{IBe#%-@j+;8S;zG?am%E@gwNzQ)!QI4BA=u8 z5xMrpLXzf)MtFehGnIzmH{#=t{=NKF97Ay=RbI||*=W<(WhFnQ?azcjV5TGh_N-_o zH*?2)`hKmso8MSMO&2(#HzHABS10m!zxD6cDHLXMclpD4HPx~iUpYgA3Kjq}1tyaR z70SDOarGqg2(eg;ekK#qC5*5hqmQ|a$7>r;W-2DhvvNml-!Ta_eHYTa>mS8b_LxFa zLT1dAl%p=>vn-ha5|`A6W6fyHcvYh89gcE}pxGw-o3~?*rd0u0gvcI5ziYM!4mz;C zWHHl62$@i4)p(5`&l6l~l(L~=dyfiuTT%3W7_@MmVDCwH2`BrWwl_lzb4u)r+YF!HB%=Q8ETE)6VI{PK-y8`bihgq-?^xJow*TD+m-K~x;4LXKs4`(>%}@n&(&$}riCD}+qBZ|aS=40*JQel>t+ zo?Y450pPlbHjAy3gK<9WrH3#^jPISxM%C>=lth~d@{;ZoFe(`No=mCKdu)3H_0$qI zFZg|>UdN{EX>V$^)BN|_{y~brHrL~Duu=0okZT3V0ELVbMD*PBln;OeI&Hpz>LTYA zJ+)u7f>-XlM&sOR-s!Aev`epZQBv)7_4^~+fM+%?`T%@=n3rLx&9fV zpd3}Nv_gH*luf;P8a>-tL{Kd?`C2OJ%e6F2D`Z7A0OyZYGfk#1utJ7>EZUdC^NL2$$Q!7UaTxfWVuhmeuWinaLSif&%LW+L~J+z2_!1s%MyUYcSr z8IsPxQ)KG&Jy$FW7lzHCw{F;^BZq6Vn42~nCpMCq1RF;s)mVy>#55#(xPhhU%BiSr z(kvMVKaccm01i|$!uEv1Nk0F{OeSOInI=&!0(Ke_I!yQ&x~-l5Zp>TO4Y)IrsS-9B zwxMn1LcKO6w|<$ut7~X(T36DGh+Kc7QWv(qt~~pdar-wPyxkX27-AgAHc>1{T@~Fh zJ7P;8yH@VEhnBnMvkc?5@8?N1t&Z;o*i?WR%bI*eOzv5mFMNrF_#VkgLw94lrZsxT zkStn+qJ~*FBo%eQUU2VVWXJQ5kh&uneDU$#Pedh|aX@Yts|l-uanvPqV{>?;N~5=t zXGn{xcW(RjHd$(1WHR()XOhRKV+15ly4u#T7Xc31XwQuU*96XY_faKPESEhZR$IPM zGw4U5Do_VIIJ^%RwP2oskq&6!jk$B^{Pfi{QFszQ=EuD1s4Rg#GB6o8h=V4CM4@@iHgH~E6q#HYPaUv(#^bvZ2 zzy!d%dC5mrXXlY*VT~~oMgiddJJ76otlpUfbn+<*Jr|v~!<}KpCQW*N_`cUI?gZ#O zk9SEybtrNSi~|_Eg9L634FD9`pU8%Tm7b?u=0=NA9)D=NtmK=20M#02NsiNJGQk?E zk9#RQ31T-DRt{}2@kuxKiJV;|D*hUV-ryyHscMR642ZD}Xbr|c9r01Fo?~tk|kDBA{B9aE`0P0oZqm@ zBs|*1sX;>%zaQUY3%j`s#^^r-5rIkY4fXvvFk2FrT@F(__IeIx{`ZA0YoZY&7cI;;cRbz>i29zlv^v0)Zz z@GK?PF*S@hX@aEH%gm_&K1iN1TFV(kbV!Gw*00~ehkfMulQ*B>1sv{YgoX5@kLz4M zc`HoViztHv0=o_o%{tJ`|N7$8eb}$)nE$+JoX3Ui7ug`K98>E( z3Uyf-SkK|ZKAk~Gt~WWch#`qcrQ4evLMI$u!qK=buLYItt}7kSn)lAITh~+b&z3Gl z`EQ^S5?NO>;bH#ae+uAP#{E;kN7OWbiqVp|#GmrVSNpdB)``Cb2=V({fI!~=5^xfZ}g8$`k{U2`3 z|9%6&N6XYy|2!lA|Gy>iKi&U#75uyVf51-v%QyUY_y1i5|L*?3 zY{0+R6#nBL_*a|4KhLt!$JvE@xP;H51DPNAs2L|_O2o{O;p6)h)s&TFdk!XB7OMHvJGn+2&$9unw#AhGh*CfVH$$ziaA$^WcB>j;SS#av;$1hh~zYiexp2%S46hboKVM z)kAYu5%aX`tfT%U#KhLplQHWbB<9@Y$hJ45Q3vl7(6~dqX^!GBr z!tNvEmdYX>mC~%|dzzHQ_n|-POgNhJ1CjUQ-=0l(O0wcTho>J$~Cs{OZliQ3P%3B_>ZXw>Pr+u@j5- z4w+_z9JGQi>s#qeZ8T&>3v{1w6F)dm6xb=>&ljqX#CG71pjjG$;<}VJtM>`xb-IDqFO0}ckxe<>%q9Izn`|Mf2Q-xmh z>)6uGAur{FnEh9}J7n_)a3A@v(Nr#N&ZF}qc{aN<$89LKt{FhF0TI>Y6bbVDleb?{4 zyuxa&Jjw6SR`_(g6;`5|PP5taWOl&>5d^QXD=~RAHDUcG7RzVd&som>JWH=I;@&GM z3uj0AL-VV--Nes(WQ3l!zquXOO@I4*hcYGDQog<%y?h6I<1ly8t6TVH0K2rlo#HGt zk(}3>JfSi4L)x1#MW(Shn*jOg%GN?uHwtfhcmSW=-n(hXW=vUA{ji-Nk~N1j;h1_VhaQVfI~~JE*VaTWIxSu;_d$=oB*hWhWQm zRQy5u6IqV0ZYbJsryRv|ulf>p7R6!<3r}CQI__4FMO&D=Ywyj2g=#&+lA?3?|`I-sFio7aK$ zyTZ?G?xl?oi=FxSlU*UAw*^*Enai7ZrBt-iAvz`MlVe~{SslOk>6UUA#m36Ye<1asRGovmrQvhv)ro#_W z{wzP7w3}h_chJT8lxXeG#XYBVeeW&{n}6YcNQ&tn-=RpROV8*d{yIQj8eg`Mx@?fxVCf#(-YCfpt4zx0O0~LDy?h=tkZ&&0DiVlef5pEHml8{;-tb$JHTHFc9=|YtWGN{65&O0wxjo!2bDa*fNcU@ z7Ak8Di|v_S4aL;Ty28@#vp+BApPw)P#ZdN5;@Quk?8^k%Vuklcd2}AXeT=MIlvgJo zp3ZGR3VxLx&+=kiSiVnoiXWItJCm&Z4gDam&EhttR7%FCQ+vMEYad72OYopld~rML z^dQgr*o{ZwLh;mnd0Z!fg163Fhav$uMuCN5z?a)ac*n5*gm}iqxez0TUVE6ZT;sZV zuteK7GxN4dTm90by@1lC7@nBNn{Vy?)?|1pA35d3%{%)hnsxd^KN;47<@`sbT?*k) zwdth6lG%DCrpP-s`tP-S`GY0Xi)G`|4Po{+aL;3mceox` zhPlSRHtZh6uJdO+YO;;t0+vE8YK^h8A9PZ4RvO;C6Eq}0HA;82wImV#D7pwCH}{iM z*HR*ON=VcnExQ{f^x3gBACJyxnYFEAlD%;+b$z@+veN0Q$jhMly@o#zTj=@tw7ztC z&yp`_Z!B52c-)qSdIVwxOt%ASxjjUmW1%GIMg#O?=x@GOtqDeV^~xBU>M`{c0|`qSNNN+unG4 z_c8PU+ZpnDt1z*2uWTq~ekSo)9CVbub&TLY{Si{4)u#6X&cD{UQlnI5hw|l6Xot66 z9);~aS{wZBZ;gG(M6s`aJ5ybQTJ(!u^_It(Or3I16_gi>JKuSEeRG4;3%uWZ{u(`r z!O*Y3+V78JEFn7@}g-N^q>E8Di5UAY` z7Z9a7zu1|F(||x%Y>4O(5%*Ki+ZW{Iiqs%b4GllPww|4E2(YELck!IiHnbsvjwq3F zy#3kTwpVx}K7P!>0r?ZZc>esWJYgH~cL!Q3-y*baXh{{+9`#W<7}o5YDF!T515;?T zr@D&DCwxQ@J8f<*jm!RyItBvpMV~Ki>?$`TBu7ty9n+i!KZj36<)*$N#pusdu3fPf z3kE;2K?XBD-Q7Pp?QlH(EpV2d`9G5&r_#r=+~w2w667o|8%7|2zT1tCj*?tE1b@T? z-u-CYv_arQWc2TFsk0!9oiNIWQru%TU_<01Rtw(v`EiV_OF5Wkjg({sBJ^ir1EnAa m{8tYC&m_fv7NbRoZYl9kR^A|g9X|W>O|p_o5*1GST0wS`JTS6KYR9d>FL`g-ZyF*H9)6yUaA|)UoNQiWImxOf31~%Qb zY4+xu3-9MS&vV}Qyx%$R_x<4yS!=Gj<{ERvHLfuxK`#`f39jF{e(BOBg6Gd9l`dVv z(zY^NkGekr$`as~W?Z6YQwcIi?<82*{wRq#8W%`-K-OP6jo zLH{ndS^qG+bm=_pxun=@xb`}FEJAA}Dk-@8t>b|^gUkD8pJ^X{rhlk(Yv^_6!>G{I z%A2REx$oME4rA%H69@Z$ZaoJt)9hYseX6dhDHjp3G@!va zEyGrGr0=pH6|<*C*Zliwifo`ph~jzoR{Au0(qsUG#@QtTYeb^$FlQAgUeRN-ljCWO zya>H-xf)osZLke$v;d`eJ|-$V=Y)s~gFa}ar=55D+4MQ$uz%%M26(>tuKjH*xmN-xUv}2x1nZvwDo1>$!i9A;x0`lT}?iZ`<}H zIA6l0vl1%Y^(_x#PlXXeLbSa*b54obA`+iey;lic50IsXp5VQX>6tyJ25*%bPK5E| zDL))cAqSGS;yRmdIu`?P2>_eGix=%j3SGT+BKj>OB1b6G7qfpWq*JtMt8O_p?Ea{aBky1LBJ z&>O+=Ta4DuJg?He-*s?u%D{MeaXo$<=kFh|#}5|BgL2v)KVIamO*9Y>oRS3F7GG}_ zn9E5_Y=%Uw6qlEO37e$emS3O!EC@R|+nyRI)pZ)Eu4dkz^6ZkByE#!^g)r zGcvlLlbd^jSv0nD>(WqHSF*6MSY2LzmXMH;Sync3xb`;vl*WzyquFj5jQ)F_&q#m} zkR;js%B_^=coK70gNFz{#>U2Sad3pEXJoijH=Ufg43OP!F$1`NM!!zJW z=i56iMkiSWOh}Trar^U;G4BuMtd+?MJ2OYe(#(+HL+{dFhViEq_{CZhZ+%B6z|t`{ zulLCTe@}k_*^;VXio6 zszI>QI0B#=ak$z?YS9wL+_@FPe2GcmGrqAc6Vo*##5{5Kon8bQL;J;m>`x2kk9Omq zpD-&tDiM!2b4@N#^o5m)o(TS^^AYE|3sjGb$gXIg|3Bar(vb6k|MfSHD1sfmTfmNdWrW>Ak;`o`e0(CT{|4DG(9=&ts8s1vUdk_Re9!PuQ zV4S&p@j=81#)|TGz$jCr*v*b_ZtW2fM)TRK!jMCClw}X!S;+^?ZvU(&fr z25q4WsxnE(XG?Z+xVBYA8lE_L&FI7FB$540#WXCOo2k*!PC9g-hOm1Q1Y6UR8NzVqzlVY6LSE#q5L)3@C~wglUR`jaZkr@?91;bYEc7*J}bmYN6p;$z*&_~%?AJQ+|R?j5qLNMOx}hr z)!5j$AD^xI6K3iBENP_&v)&^FTOwQPa4jnLw`ljN_Jv&;_xJb5aJBitcmvto7YN_2 zqjwJ4AwjOMzYTS_*{s^Cwcn~aJjrhaZiME_vsyblI~9Vjp8G>817~M$tE;QKdO^X# z!6kdmJ8s-J`J2g{_kQ!DC#DnhZEV=vlmtXXAg?l!kbn^!{k3(D*~*wcPMF?F9;lzr zbwW5Zx}Tp;D~g`un;qRPq4p!pkrlqB!B9hMTp-)EY4$u}01#Q%_NvD%bN={B? zTb$?n8KP*jlNL6Q*;BzFf70uHLZ@jY}T0Me)g6)7uFei zyw0<(O>G-lv6SfAQ>T+xy(@FFz~;H)byOv$J^vi>L~X%39j0#$89IFW8HjpTIPfH8 zMa8f-XM)xe=8e!m7i18l5X_V9S46c};e%JW1&6?Ah*z`azOgAloq3*xopYd1JGGs1YS0qbk?2( zr}bdrTAWe^>)C>^QaJ-6Z${tDPJkM%{G{1lUzLInn;rSWUQg=kUVxe=Y?lR+rvr7)-CmvYi2R)!A zX5+q}r6V73lWG@jL8K{;+xK=oomV^2=RHJpeYAR)3UM=#W@2D#z z<=jAQFo$EnRo3C*VIdJdK2-|wnut$~&R9lTYu;4AZty_}Xudsblt@8A!J2=s9PHd( z>pHaK29^4a%hg-8r$V(6pG?TLpZ&|EzZx6GPlD@?g6&UGD=1_zn+zl=L3qIMSdob^ zVthPqv*r*%MP>Z#&*oL_u(H!N=Y&Du^OLq3)9HE4c1shyJbEd~Q-p4&gQWbyh3w6=c!4oFmlDL0ys4+pe5WfvVk@7 z0K%3tnB&^|91oY(MHp;_C2`*{;&)hm4cr>F$I&bbXz;N+`E43(W%09FLeDRWuA3EZ z^C$d{>#Ct?sMsD)5dgEw1O?Gf`9#Wh&N@_T3m1%9v-y5$X4jpc)*U+Ms(7Qird_rh za9-)?=!o3e)A!u=p-GL=@!+Q!Q*%Ua&G6Rk>{AkpuQOOmNJx0bU4XQh+Fcy}0}T9h zzMWDQ01uuv5k4j+rWNq|=fc9m$GUVZ_z%-Ma>!|65 zr>xr5%S@%z!Y;)JP6gk;HyzS=p4pzKT-R%@DpUB%H!B{j=bMCHH_^HjURvMVbdH%m zcXa_yc`rP{gb{O7L@(t9Zow(!$Xv;qdx;f=!WkGDos1mBckfwu^!DDNljPj)7Tiib zMu$irt8QUpE&j*l!Rfyy(T(*713}o*UX85ZWOG_{RtT4gpTGfVU#t z6Q?u30f!o1A3#uATs+UIF^kXOPglF$h`%Lp!!`r*!*Mtl!1tEc2&8zf5%K#@u*;6~ zzlhE!28M?h+d$l|xd|_}itIIqAkLy#6TTm$0SGL~+goEGV0g?+q~kU7J91*jz%C#N zxCt4i78w2~7ou|{0`K^PJw~M(+e~P(EBUM z!;<$*Pfu^{)L>h(+L15gpGe{sI02js;WBdYohj{nZYa~xG%h~A@{C2UUgdF3({=oR z!H*KqXU+A_Hks+>i+Fe%8r~}@DOsqQART|EfseZE4st8kf51dS2z$^uC6%{%w7IH1 zijo;Gv!1p@%d=U2|5(gD+V#I6VPDk#VFrZVxBMDxXX?GU*x79~EC!455l{V1@5OCqEk4`B-5xXb7zD!B3}VUIjdp0A!Wue=ToU7-K{%Dad44RiyKJ!1Tyr=a{jxUUn|$#{9>{Ix`hpCA&dLGg z8c2rxh{W6tIYs$2*%;RJim|cc;^N4kSy_(7YW~A-(`BRs2(wmb$hJv6R?(c|frr7E zo7#fAAh9(7u?{>Pf1#J<%3%A-IUxJ{ql5o{C-47lj14T~-vBww+}vC|KdW!KnA_UK zbbCR9iHrFotx9{2-@m)l0aALcrB(8s#dbH^g!7Gn0DwqNt2AWK?%w@wW(wy^A_m;U zz`seg49|ptp+7It*u%w#|?Lm^`zs88c{RH-fLiF1wx%&9hSci~WYZ~Qy})&VM3TFDyK(*)h1~1W$lm-t{y$74 zHztw}fiuy(fYBetKyDfr3Daa#&1Nl!Ff&LO;t~@Njy2cT*5vP&zyDk3@GXB1AT853 zF1GErH}G2WxJ~PgO}AfX4cTu_R&WUlPQ0dHtN8|LcVFuj%aIonkoV!jzc8D;x`UtS zn}nqLhVS0>2i!vB_VSFYl4`S5022UHTDe1J{aCdc!`~)&p1CWzb2J>r{6$Mxb7MIwDsu+O065OBs3FWDh+sL^>W}&QG-5U+g^2M>G zSnguLc|i9&F79iB4Q>0(hVLoJ5@(y!Ydo%P3Y-))zXs$j;{q$jPBd8&O(iO3Z(Sk3 z13miT&(xTojoNXYB?*5#A6RsA4y0}Jk|knqBc0{{ks1ES4XNsQ`~#$0ZsTz2$f+bW z7gG8E);)(ugD_ZAg&hau4YGDW6$C-_Xe>f;QB@{GA)%vSEu*ZAcVnWAt)z5w{g9n` zLxi6{mV|_4H#}i(w7>wQG$tbF#~_U2?sy#iJK2$QuaesHYzH;gZ~R~Jj~`qF9DO#xw}GteSNPq` zs;Y@Ocq)|6FfcGU-up!Ae8uQRG_=pn+L9oWmE%o5YQl#SzYI3FS^UhL9G2f*U8!3h zhgB<$e)z}h`y4zx(X|I9d1(y|4aK#!i5_QjG#MF59s)@<9$eKRg~+8LVEYT%N(=lK zm=^5Pg(C?hluJ|Ei6Xp+mCZv?q;sQ%X+W6vD`u+h)M=&mbhA_X&uvF2CT_(iCnuw% zJyFstp@N&+QjcqQqw=1?FGxhqt3V~1Z|hwS0l}PhYe>&4MD(ml6g7kkXqq!J?L0R3 z71@>MAmUoUTYy!pUZ7gsy%M^=}0WEfHgJ@l1-^Z{kQbR`kJGl zce>GrQVB+jfQ?)dhBg7$mKzc(O<-tfD5|2zoz)#lob>BopU@=oCrA`@VwIPZ)8v*@ zP)LUo$T`6OW&N4fQN6XTjn_^SK-Z&xKv&^o!_YMQ)xk{4(;0T5ZG4?0Z#FzpPR@v0 zkm+uYx|YI&c1M7=fGGb3B0R!8&*o650mY@F5yB=4{J)6}y5`f__~|2;P&_(EV(0%? zIP@Eec{W*HD=tT~0Ru60XA7@0U+;!bc}ekm95vCTgKUtMrow|O189FP4K(^f8C}1W zO?wFb?(SZ!nezE}(=c{%5fI*KCay)DE-rQp*0e`dKlCZQ`0N9Eh|-XsQ6|?O?Yan# znxfE^3-5d}!uP)k;r>U10p6>ED93kiw+c!&TewIsHpgjX%NFTr#qJa z*%jJ5IW4KmP`RqU z1>E=uZVWGRd<+Rm1zcCP)2TRxnT40gw?8&&Hd{e|W3>|v->dm95V(aPJiSaop zh_WT%v7`Cp^G_h3|1SV;Tfk=K$sIDX@*I+pix4+-Rb{ty0O!I;e!qv7)-hU(W)Pvy zSA|!D8wc2k7&ymaTXo_+Q73bCsTR=vGnVd(`T(CfS@ag|21%5GQtPfdA_f$Kge|} zhlSBoP%Pe*!ZLCO@&}TfkSDgh!gTD8+G!h*2ow4oN-4OSm@I>{_bskHwr0g4eY4mL zu)R4-e?sfi3!l6`56}gOQ9c*65=1axeBA%XoZ^3^kpJhwsTY-@3%c$i1eWgo@8IZt z1;j3dN2OOcHxB+aDVa~F$vgVeS z5KEd_RK&S|aB$+0@Z0{}hcF#v0eiIol&nE{UpdFchTrmD16=>rk*+SexG!Ix4Gav3 zBw4t-*O+0GzED|}n=-?)OqO?0ul`-E1*vd~8gS4lczR#7;N{-tC2`$=x-~X2iI*{~ zAq7Q&J^;VIZQS`ATZuu~Y96Rv$@J{3cnI*zCodW&Zi8yTT4UDzL$5yu2&Jm>*O-nA zDs^TdZvWoa-`xJUHv~{z>$?FNjiKCEkpu&dfHlVh8_R%Fp6(rUka7Xh1ZrG>TwHB8 z&1gT9H;sVO&kN%Do6^6yPksTxKz^~Px@$CRogu}UdwX1N0w3bz!Th#N&<+rD@M#W^8|R|Np!Jcze4B z?XNv={^sq$To=v=S}*W9|FarmKU9ozig`keWZ22E_GD~B(1^P30-|GOF!L3^BN`(0 zK@l-+csKz~?VmQq$jCSV*ea1iJ4!)E<~F61t|ieV1Mpr1;XiF1NYs|NJW6t8E=)90 z

AtIE2)4fE#CYl()I;{OX#~ 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�R7#^rL) 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�{q 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

Bb__(()L_a)uhPO5wTr`3M^Wn1wZB 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 z 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 YHDssj!Yp#9{Q+F(&sv#RoN -1; * @param {string} url */ async function loadWorkflow(url) { - const fileName = SearchPath.filename(decodeURIComponent(url)); - const response = await fetch(url); - const data = await response.blob(); - const file = new File([data], fileName, { type: data.type }); - app.handleFile(file); -} - -/** - * @param {string} modelSearchPath - * @returns {Promise} - */ -async function tryGetModelWebUrl(modelSearchPath) { - const encodedPath = encodeURIComponent(modelSearchPath); - const response = await comfyRequest(`/model-manager/model/web-url?path=${encodedPath}`); - const url = response.url; - return url !== undefined && url !== '' ? url : undefined; -} - -/** - * @param {string} url - * @param {string} name - * @returns {boolean} - */ -function tryOpenUrl(url, name="Url") { - try { - new URL(url); - } - catch (exception) { - return false; - } - try { - window.open(url, '_blank').focus(); - } - catch (exception) { - // browser or ad-blocker blocking opening new window - modelManagerDialog.show($el("span", - [ - $el("p", { - style: { color: "var(--input-text)" }, - }, [name]), - $el("a", { - href: url, - target: "_blank", - }, [ - $el("span", [ - url, - $el("i.mdi.mdi-open-in-new"), - ]) - ]), - ] - )); - } - return true; + const uri = new URL(url).searchParams.get('uri'); + const fileNameIndex = + Math.max(uri.lastIndexOf('/'), uri.lastIndexOf('\\')) + 1; + const fileName = uri.substring(fileNameIndex); + const response = await fetch(url); + const data = await response.blob(); + const file = new File([data], fileName, { type: data.type }); + app.handleFile(file); } const modelNodeType = { @@ -260,57 +215,40 @@ class SearchPath { const i2 = path.indexOf(searchSeparator, i1 + 1); return path.slice(i2 + 1).replaceAll(searchSeparator, systemSeparator); } - - /** - * @param {string} s search path or url - * @returns {string} - */ - static filename(s) { - let name = SearchPath.split(s)[1]; - const queryIndex = name.indexOf('?'); - if (queryIndex > -1) { - return name.substring(0, queryIndex); - } - return name; - } } /** - * @param {string | undefined} [imageUriSearchPath=undefined] + * @param {string | undefined} [searchPath=undefined] * @param {string | undefined} [dateImageModified=undefined] * @param {string | undefined} [width=undefined] * @param {string | undefined} [height=undefined] * @param {string | undefined} [imageFormat=undefined] * @returns {string} */ - function imageUri( - imageUriSearchPath = undefined, - dateImageModified = undefined, - width = undefined, - height = undefined, - imageFormat = undefined, - ) { - const params = []; +function imageUri( + imageSearchPath = undefined, + dateImageModified = undefined, + width = undefined, + height = undefined, + imageFormat = undefined, +) { + const path = imageSearchPath ?? 'no-preview'; + const date = dateImageModified; + let uri = `/model-manager/preview/get?uri=${path}`; if (width !== undefined && width !== null) { - params.push(`width=${width}`); + uri += `&width=${width}`; } if (height !== undefined && height !== null) { - params.push(`height=${height}`); + uri += `&height=${height}`; } - if (dateImageModified !== undefined && dateImageModified !== null) { - params.push(`v=${dateImageModified}`); + if (date !== undefined && date !== null) { + uri += `&v=${date}`; } if (imageFormat !== undefined && imageFormat !== null) { - params.push(`image-format=${imageFormat}`); - } - - const path = imageUriSearchPath ?? 'no-preview'; - const uri = `/model-manager/preview/get/${path}`; - if (params.length > 0) { - return uri + '?' + params.join('&'); + uri += `&image-format=${imageFormat}`; } return uri; - } +} const PREVIEW_NONE_URI = imageUri(); /** @@ -656,7 +594,6 @@ class ImageSelect { /** @type {HTMLImageElement} */ defaultPreviewNoImage: null, /** @type {HTMLDivElement} */ defaultPreviews: null, /** @type {HTMLDivElement} */ defaultUrl: null, - /** @type {HTMLDivElement} */ previewButtons: null, /** @type {HTMLImageElement} */ customUrlPreview: null, /** @type {HTMLInputElement} */ customUrl: null, @@ -721,15 +658,11 @@ class ImageSelect { case this.#PREVIEW_NONE: return PREVIEW_NONE_URI; } - console.warn(`Invalid preview select type: ${value}`); - return PREVIEW_NONE_URI; + return ''; } - /** - * @param {String[]} defaultPreviewUrls - * @returns {void} - */ - resetModelInfoPreview(defaultPreviewUrls = []) { + /** @returns {void} */ + resetModelInfoPreview() { let noimage = this.elements.defaultUrl.dataset.noimage; [ this.elements.defaultPreviewNoImage, @@ -748,18 +681,6 @@ class ImageSelect { el.src = PREVIEW_NONE_URI; } }); - const defaultPreviews = this.elements.defaultPreviews; - defaultPreviews.innerHTML = ''; - if (defaultPreviewUrls.length > 0) { - ImageSelect.generateDefaultPreviews(defaultPreviewUrls).forEach(previewElement => { - defaultPreviews.appendChild(previewElement); - }); - } - else { - const defaultImage = ImageSelect.generateDefaultPreviews([PREVIEW_NONE_URI]); - defaultPreviews.appendChild(defaultImage[0]); - } - this.elements.previewButtons.style.display = defaultPreviewUrls.length > 1 ? 'block' : 'none'; this.checkDefault(); this.elements.uploadFile.value = ''; this.elements.customUrl.value = ''; @@ -820,28 +741,6 @@ class ImageSelect { children[currentIndex].style.display = 'block'; } - /** - * @param {string[]|undefined} defaultPreviewUrls - * @returns {HTMLImageElement[]} - */ - static generateDefaultPreviews(defaultPreviewUrls) { - const imgs = defaultPreviewUrls.map((url) => { - return $el('img', { - loading: - 'lazy' /* `loading` BEFORE `src`; Known bug in Firefox 124.0.2 and Safari for iOS 17.4.1 (https://stackoverflow.com/a/76252772) */, - src: url, - style: { display: 'none' }, - onerror: (e) => { - e.target.src = PREVIEW_NONE_URI; - }, - }); - }); - if (imgs.length > 0) { - imgs[0].style.display = 'block'; - } - return imgs; - } - /** * @param {string} radioGroupName - Should be unique for every radio group. * @param {string[]|undefined} defaultPreviews @@ -879,7 +778,23 @@ class ImageSelect { height: '100%', }, }, - ImageSelect.generateDefaultPreviews(defaultPreviews), + (() => { + const imgs = defaultPreviews.map((url) => { + return $el('img', { + loading: + 'lazy' /* `loading` BEFORE `src`; Known bug in Firefox 124.0.2 and Safari for iOS 17.4.1 (https://stackoverflow.com/a/76252772) */, + src: url, + style: { display: 'none' }, + onerror: (e) => { + e.target.src = el_defaultUri.dataset.noimage ?? PREVIEW_NONE_URI; + }, + }); + }); + if (imgs.length > 0) { + imgs[0].style.display = 'block'; + } + return imgs; + })(), ); const el_uploadPreview = $el('img', { @@ -989,7 +904,6 @@ class ImageSelect { const el_previewButtons = $el( 'div.model-preview-overlay', { - $: (el) => (this.elements.previewButtons = el), style: { display: el_defaultPreviews.children.length > 1 ? 'block' : 'none', }, @@ -1914,7 +1828,6 @@ class ModelGrid { const widgetIndex = ModelGrid.modelWidgetIndex(nodeType); const target = selectedNode?.widgets[widgetIndex]?.element; if (target && target.type === 'textarea') { - // TODO: If the node has >1 text areas, the textarea element must be selected target.value = ModelGrid.insertEmbeddingIntoText( target.value, embeddingFile, @@ -1924,7 +1837,7 @@ class ModelGrid { } } if (!success) { - window.alert('No selected nodes have a text area!'); + console.warn('Try selecting a node before adding the embedding.'); } event.stopPropagation(); } @@ -2109,16 +2022,13 @@ class ModelGrid { // TODO: separate text and model logic; getting too messy // TODO: fallback on button failure to copy text? const canShowButtons = modelNodeType[modelType] !== undefined; - const shouldShowTryOpenModelUrl = - canShowButtons && - settingsElements['model-show-open-model-url-button'].checked; - const showLoadWorkflowButton = - canShowButtons && - settingsElements['model-show-load-workflow-button'].checked; const showAddButton = canShowButtons && settingsElements['model-show-add-button'].checked; const showCopyButton = canShowButtons && settingsElements['model-show-copy-button'].checked; + const showLoadWorkflowButton = + canShowButtons && + settingsElements['model-show-load-workflow-button'].checked; const strictDragToAdd = settingsElements['model-add-drag-strict-on-field'].checked; const addOffset = parseInt(settingsElements['model-add-offset'].value); @@ -2186,8 +2096,8 @@ class ModelGrid { loading: 'lazy' /* `loading` BEFORE `src`; Known bug in Firefox 124.0.2 and Safari for iOS 17.4.1 (https://stackoverflow.com/a/76252772) */, src: imageUri( - previewInfo?.path ? encodeURIComponent(previewInfo.path) : undefined, - previewInfo?.dateModified ? encodeURIComponent(previewInfo.dateModified) : undefined, + previewInfo?.path, + previewInfo?.dateModified, previewThumbnailWidth, previewThumbnailHeight, previewThumbnailFormat, @@ -2201,47 +2111,23 @@ class ModelGrid { systemSeparator, ); let actionButtons = []; - if (shouldShowTryOpenModelUrl) { + if (showCopyButton) { actionButtons.push( - new ComfyButton({ - icon: 'open-in-new', - tooltip: 'Attempt to open model url page in a new tab.', - classList: 'comfyui-button icon-button model-button', - action: async (e) => { - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const webUrl = await tryGetModelWebUrl(searchPath); - const success = tryOpenUrl(webUrl, searchPath); - comfyButtonAlert(e.target, success, 'mdi-check-bold', 'mdi-close-thick'); - button.disabled = false; - }, - }).element + new ComfyButton({ + icon: 'content-copy', + tooltip: 'Copy model to clipboard', + classList: 'comfyui-button icon-button model-button', + action: (e) => + ModelGrid.#copyModelToClipboard( + e, + modelType, + path, + removeEmbeddingExtension, + ), + }).element, ); - } - if (showLoadWorkflowButton) { - actionButtons.push( - new ComfyButton({ - icon: 'arrow-bottom-left-bold-box-outline', - tooltip: 'Load preview workflow', - classList: 'comfyui-button icon-button model-button', - action: async (e) => { - const urlString = previewThumbnail.src; - const url = new URL(urlString); - const urlSearchParams = url.searchParams; - const uri = urlSearchParams.get('uri'); - const v = urlSearchParams.get('v'); - const urlFull = - urlString.substring(0, urlString.indexOf('?')) + - '?uri=' + - uri + - '&v=' + - v; - await loadWorkflow(urlFull); - }, - }).element, - ); - } - if (showAddButton) { + } + if (showAddButton && !(modelType === 'embeddings' && !navigator.clipboard)) { actionButtons.push( new ComfyButton({ icon: 'plus-box-outline', @@ -2258,36 +2144,37 @@ class ModelGrid { }).element, ); } - if ( - showCopyButton && - !(modelType === 'embeddings' && !navigator.clipboard) - ) { - actionButtons.push( - new ComfyButton({ - icon: 'content-copy', - tooltip: 'Copy model to clipboard', - classList: 'comfyui-button icon-button model-button', - action: (e) => - ModelGrid.#copyModelToClipboard( - e, - modelType, - path, - removeEmbeddingExtension, - ), - }).element, - ); + if (showLoadWorkflowButton) { + actionButtons.push( + new ComfyButton({ + icon: 'arrow-bottom-left-bold-box-outline', + tooltip: 'Load preview workflow', + classList: 'comfyui-button icon-button model-button', + action: async (e) => { + const urlString = previewThumbnail.src; + const url = new URL(urlString); + const urlSearchParams = url.searchParams; + const uri = urlSearchParams.get('uri'); + const v = urlSearchParams.get('v'); + const urlFull = + urlString.substring(0, urlString.indexOf('?')) + + '?uri=' + + uri + + '&v=' + + v; + await loadWorkflow(urlFull); + }, + }).element, + ); } const infoButtons = [ new ComfyButton({ icon: 'information-outline', tooltip: 'View model information', classList: 'comfyui-button icon-button model-button', - action: async(e) => { - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; + action: async () => { await showModelInfo(searchPath); - button.disabled = false; - }, + }, }).element, ]; return $el('div.item', {}, [ @@ -2377,21 +2264,14 @@ class ModelGrid { previousModelType.value = modelType; } - let modelTypeOptions = []; - for (const key of Object.keys(models)) { - const el = $el('option', [key]); - modelTypeOptions.push(el); - } - modelTypeOptions.sort((a, b) => - a.innerText.localeCompare( - b.innerText, - undefined, - {sensitivity : 'base'}, - ) - ); - modelSelect.innerHTML = ""; - modelTypeOptions.forEach(option => modelSelect.add(option)); - modelSelect.value = modelType; + let modelTypeOptions = []; + for (const [key, value] of Object.entries(models)) { + const el = $el('option', [key]); + modelTypeOptions.push(el); + } + modelSelect.innerHTML = ''; + modelTypeOptions.forEach((option) => modelSelect.add(option)); + modelSelect.value = modelType; const searchAppend = settings['model-search-always-append'].value; const searchText = modelFilter.value + ' ' + searchAppend; @@ -2433,18 +2313,13 @@ class ModelInfo { /** @type {[HTMLElement][]} */ #settingsElements = null; - /** @type {() -> Promise} */ - #tryHideModelInfo = () => {}; - /** * @param {ModelData} modelData * @param {(withoutComfyRefresh?: boolean) => Promise} updateModels * @param {any} settingsElements - * @param {() => Promise} tryHideModelInfo */ - constructor(modelData, updateModels, settingsElements, tryHideModelInfo) { + constructor(modelData, updateModels, settingsElements) { this.#settingsElements = settingsElements; - this.#tryHideModelInfo = tryHideModelInfo; const moveDestinationInput = $el('input.search-text-area', { name: 'move directory', autocomplete: 'off', @@ -2530,6 +2405,11 @@ class ModelInfo { }, }).element; this.elements.setPreviewButton = setPreviewButton; + previewSelect.elements.radioButtons.addEventListener('change', (e) => { + setPreviewButton.style.display = previewSelect.defaultIsChecked() + ? 'none' + : 'block'; + }); this.element = $el( 'div', @@ -2662,9 +2542,9 @@ class ModelInfo { tabContent: this.element, }, { - name: 'Notes', - icon: 'pencil-outline', - tabContent: $el('div', ['Notes']), + name: 'Metadata', + icon: 'file-document-outline', + tabContent: $el('div', ['Metadata']), }, { name: 'Tags', @@ -2672,9 +2552,9 @@ class ModelInfo { tabContent: $el('div', ['Tags']), }, { - name: 'Metadata', - icon: 'file-document-outline', - tabContent: $el('div', ['Metadata']), + name: 'Notes', + icon: 'pencil-outline', + tabContent: $el('div', ['Notes']), }, ]); } @@ -2745,8 +2625,8 @@ class ModelInfo { */ async update(searchPath, updateModels, searchSeparator) { const path = encodeURIComponent(searchPath); - const [info, metadata, tags, noteText, url, webPreviews] = await comfyRequest( - `/model-manager/model/info/${path}`, + const [info, metadata, tags, noteText] = await comfyRequest( + `/model-manager/model/info?path=${path}`, ) .then((result) => { const success = result['success']; @@ -2762,8 +2642,6 @@ class ModelInfo { result['metadata'], result['tags'], result['notes'], - result['url'], - result['webPreviews'], ]; }) .catch((err) => { @@ -2870,131 +2748,38 @@ class ModelInfo { const previewSelect = this.previewSelect; const defaultUrl = previewSelect.elements.defaultUrl; if (info['Preview']) { - const imagePath = encodeURIComponent(info['Preview']['path']); - const imageDateModified = encodeURIComponent(info['Preview']['dateModified']); + const imagePath = info['Preview']['path']; + const imageDateModified = info['Preview']['dateModified']; defaultUrl.dataset.noimage = imageUri(imagePath, imageDateModified); } else { defaultUrl.dataset.noimage = PREVIEW_NONE_URI; } - previewSelect.resetModelInfoPreview(webPreviews); - const setPreviewDiv = $el('div.row.tab-header', { - style: { - display: "none" - } - }, [ - $el('div.row.tab-header-flex-block', [ - previewSelect.elements.radioGroup, - ]), - $el('div.row.tab-header-flex-block', [ - this.elements.setPreviewButton, - ]), - ]); - previewSelect.elements.previews.style.display = "none"; - - let previewUri; - if (info['Preview']) { - const imagePath = encodeURIComponent(info['Preview']['path']); - const imageDateModified = encodeURIComponent(info['Preview']['dateModified']); - previewUri = imageUri(imagePath, imageDateModified); - } else { - previewUri = PREVIEW_NONE_URI; - } - const previewImage = $el('img.model-preview-full', { - loading: - 'lazy' /* `loading` BEFORE `src`; Known bug in Firefox 124.0.2 and Safari for iOS 17.4.1 (https://stackoverflow.com/a/76252772) */, - src: previewUri, - }); + previewSelect.resetModelInfoPreview(); + const setPreviewButton = this.elements.setPreviewButton; + setPreviewButton.style.display = previewSelect.defaultIsChecked() + ? 'none' + : 'block'; innerHtml.push( $el('div', [ - $el('div.row.tab-header', { style: { "flex-direction": "row" } }, [ - new ComfyButton({ - icon: 'arrow-bottom-left-bold-box-outline', - tooltip: 'Attempt to load preview image workflow', - classList: 'comfyui-button icon-button', - action: async () => { - await loadWorkflow(previewImage.src); - }, - }).element, - new ComfyButton({ - icon: 'open-in-new', - tooltip: 'Attempt to open model url page in a new tab.', - classList: 'comfyui-button icon-button', - action: async (e) => { - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - let webUrl; - if (url !== undefined && url !== "") { - webUrl = url; - } - else { - webUrl = await tryGetModelWebUrl(searchPath); - } - const success = tryOpenUrl(webUrl, searchPath); - comfyButtonAlert(e.target, success, "mdi-check-bold", "mdi-close-thick"); - button.disabled = false; - }, - }).element, - new ComfyButton({ - icon: 'earth-arrow-down', - tooltip: 'Hash model and try to download model info.', - classList: 'comfyui-button icon-button', - action: async(e) => { - const confirm = window.confirm('Overwrite model info?'); - if (!confirm) { - comfyButtonAlert(e.target, false, 'mdi-check-bold', 'mdi-close-thick'); - return; - } - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const success = await comfyRequest( - `/model-manager/model/download/info?path=${path}`, - { - method: 'POST', - body: {}, - } - ).then((data) => { - const success = data['success']; - const message = data['alert']; - if (message !== undefined) { - window.alert(message); - } - return success; - }).catch((err) => { - return false; - }); - if (success) { - this.#tryHideModelInfo(); - } - comfyButtonAlert(e.target, success, 'mdi-check-bold', 'mdi-close-thick'); - button.disabled = false; - }, - }).element, - new ComfyButton({ - icon: 'image-edit-outline', - tooltip: 'Open preview edit dialog.', - classList: 'comfyui-button icon-button', - action: () => { - // TODO: toggle button border highlight - if (previewImage.style.display === "none") { - setPreviewDiv.style.display = "none"; - previewSelect.elements.previews.style.display = "none"; - previewImage.style.display = ""; - } - else { - previewImage.style.display = "none"; - previewSelect.elements.previews.style.display = ""; - setPreviewDiv.style.display = ""; - if (previewSelect.elements.defaultPreviews.children[0].src.includes(PREVIEW_NONE_URI)) { - window.alert("No model previews found!\nTry downloading model info first!"); - } - } - }, - }).element, - ]), - previewImage, previewSelect.elements.previews, - setPreviewDiv, + $el('div.row.tab-header', [ + $el('div', [ + new ComfyButton({ + content: 'Load Workflow', + tooltip: 'Attempt to load preview image workflow', + action: async () => { + const urlString = + previewSelect.elements.defaultPreviews.children[0].src; + await loadWorkflow(urlString); + }, + }).element, + ]), + $el('div.row.tab-header-flex-block', [ + previewSelect.elements.radioGroup, + ]), + $el('div.row.tab-header-flex-block', [setPreviewButton]), + ]), $el('h2', ['File Info:']), $el( 'div', @@ -3037,163 +2822,40 @@ class ModelInfo { infoHtml.append.apply(infoHtml, innerHtml); // TODO: set default value of dropdown and value to model type? - // - // NOTES - // - - const saveIcon = 'content-save'; - const savingIcon = 'cloud-upload-outline'; - - const saveNotesButton = new ComfyButton({ - icon: saveIcon, - tooltip: 'Save note', - classList: 'comfyui-button icon-button', - action: async (e) => { - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const saved = await this.trySave(false); - comfyButtonAlert(e.target, saved); - button.disabled = false; - }, - }).element; - - const downloadNotesButton = new ComfyButton({ - icon: 'earth-arrow-down', - tooltip: 'Attempt to download model info from the internet.', - classList: 'comfyui-button icon-button', - action: async (e) => { - if (this.#savedNotesValue !== '') { - const overwriteNoteConfirmation = window.confirm('Overwrite note?'); - if (!overwriteNoteConfirmation) { - comfyButtonAlert(e.target, false, 'mdi-check-bold', 'mdi-close-thick'); - return; - } - } - - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const [success, downloadedNotesValue] = await comfyRequest( - `/model-manager/notes/download?path=${path}&overwrite=True`, - { - method: 'POST', - body: {}, - } - ).then((data) => { - const success = data['success']; - const message = data['alert']; - if (message !== undefined) { - window.alert(message); - } - return [success, data['notes']]; - }).catch((err) => { - return [false, '']; - }); - if (success) { - this.#savedNotesValue = downloadedNotesValue; - this.elements.notes.value = downloadedNotesValue; - this.elements.markdown.innerHTML = marked.parse(downloadedNotesValue); - } - comfyButtonAlert(e.target, success, 'mdi-check-bold', 'mdi-close-thick'); - button.disabled = false; - }, - }).element; - - const saveDebounce = debounce(async () => { - const saveIconClass = 'mdi-' + saveIcon; - const savingIconClass = 'mdi-' + savingIcon; - const iconElement = saveNotesButton.getElementsByTagName('i')[0]; - iconElement.classList.remove(saveIconClass); - iconElement.classList.add(savingIconClass); - const saved = await this.trySave(false); - iconElement.classList.remove(savingIconClass); - iconElement.classList.add(saveIconClass); - }, 1000); - /** @type {HTMLDivElement} */ - const notesElement = this.elements.tabContents[1]; // TODO: remove magic value - notesElement.innerHTML = ''; - const markdown = $el('div', {}, ''); - markdown.innerHTML = marked.parse(noteText); - - notesElement.append.apply( - notesElement, - (() => { - const notes = $el('textarea.comfy-multiline-input', { - name: 'model notes', - value: noteText, - oninput: (e) => { - if (this.#settingsElements['model-info-autosave-notes'].checked) { - saveDebounce(); + const metadataElement = this.elements.tabContents[1]; // TODO: remove magic value + const isMetadata = + typeof metadata === 'object' && + metadata !== null && + Object.keys(metadata).length > 0; + metadataElement.innerHTML = ''; + metadataElement.append.apply(metadataElement, [ + $el('h1', ['Metadata']), + $el( + 'div', + (() => { + const tableRows = []; + if (isMetadata) { + for (const [key, value] of Object.entries(metadata)) { + if (value === undefined || value === null) { + continue; + } + if (value !== '') { + tableRows.push( + $el('tr', [ + $el('th.model-metadata-key', [key]), + $el('th.model-metadata-value', [value]), + ]), + ); + } } - }, - }); - - if (navigator.userAgent.includes('Mac')) { - new KeyComboListener(['MetaLeft', 'KeyS'], saveDebounce, notes); - new KeyComboListener(['MetaRight', 'KeyS'], saveDebounce, notes); - } else { - new KeyComboListener(['ControlLeft', 'KeyS'], saveDebounce, notes); - new KeyComboListener(['ControlRight', 'KeyS'], saveDebounce, notes); - } - - this.elements.notes = notes; - this.elements.markdown = markdown; - this.#savedNotesValue = noteText; - - const notesEditor = $el( - 'div', - { - style: { - display: noteText == '' ? 'flex' : 'none', - height: '100%', - 'min-height': '60px', - }, - }, - notes, - ); - const notesViewer = $el( - 'div', - { - style: { - display: noteText == '' ? 'none' : 'flex', - height: '100%', - 'min-height': '60px', - overflow: 'scroll', - 'overflow-wrap': 'anywhere', - }, - }, - markdown, - ); - - const editNotesButton = new ComfyButton({ - icon: 'pencil', - tooltip: 'Change file name', - classList: 'comfyui-button icon-button', - action: async () => { - notesEditor.style.display = - notesEditor.style.display == 'flex' ? 'none' : 'flex'; - notesViewer.style.display = - notesViewer.style.display == 'none' ? 'flex' : 'none'; - }, - }).element; - - return [ - $el( - 'div.row', - { - style: { 'align-items': 'center' }, - }, - [$el('h1', ['Notes']), downloadNotesButton, saveNotesButton, editNotesButton], - ), - notesEditor, - notesViewer, - ]; - })(), - ); - - // - // TAGS - // + } + return $el('table.model-metadata', tableRows); + })(), + ), + ]); + const metadataButton = this.elements.tabButtons[1]; // TODO: remove magic value + metadataButton.style.display = isMetadata ? '' : 'none'; /** @type {HTMLDivElement} */ const tagsElement = this.elements.tabContents[2]; // TODO: remove magic value @@ -3307,44 +2969,114 @@ class ModelInfo { const tagButton = this.elements.tabButtons[2]; // TODO: remove magic value tagButton.style.display = isTags ? '' : 'none'; - // - // METADATA - // + const saveIcon = 'content-save'; + const savingIcon = 'cloud-upload-outline'; + + const saveNotesButton = new ComfyButton({ + icon: saveIcon, + tooltip: 'Save note', + classList: 'comfyui-button icon-button', + action: async (e) => { + const [button, icon, span] = comfyButtonDisambiguate(e.target); + button.disabled = true; + const saved = await this.trySave(false); + comfyButtonAlert(e.target, saved); + button.disabled = false; + }, + }).element; + + const saveDebounce = debounce(async () => { + const saveIconClass = 'mdi-' + saveIcon; + const savingIconClass = 'mdi-' + savingIcon; + const iconElement = saveNotesButton.getElementsByTagName('i')[0]; + iconElement.classList.remove(saveIconClass); + iconElement.classList.add(savingIconClass); + const saved = await this.trySave(false); + iconElement.classList.remove(savingIconClass); + iconElement.classList.add(saveIconClass); + }, 1000); /** @type {HTMLDivElement} */ - const metadataElement = this.elements.tabContents[3]; // TODO: remove magic value - const isMetadata = - typeof metadata === 'object' && - metadata !== null && - Object.keys(metadata).length > 0; - metadataElement.innerHTML = ''; - metadataElement.append.apply(metadataElement, [ - $el('h1', ['Metadata']), - $el( - 'div', - (() => { - const tableRows = []; - if (isMetadata) { - for (const [key, value] of Object.entries(metadata)) { - if (value === undefined || value === null) { - continue; - } - if (value !== '') { - tableRows.push( - $el('tr', [ - $el('th.model-metadata-key', [key]), - $el('th.model-metadata-value', [value]), - ]), - ); - } + const notesElement = this.elements.tabContents[3]; // TODO: remove magic value + notesElement.innerHTML = ''; + const markdown = $el('div', {}, ''); + markdown.innerHTML = marked.parse(noteText); + + notesElement.append.apply( + notesElement, + (() => { + const notes = $el('textarea.comfy-multiline-input', { + name: 'model notes', + value: noteText, + oninput: (e) => { + if (this.#settingsElements['model-info-autosave-notes'].checked) { + saveDebounce(); } - } - return $el('table.model-metadata', tableRows); - })(), - ), - ]); - const metadataButton = this.elements.tabButtons[3]; // TODO: remove magic value - metadataButton.style.display = isMetadata ? '' : 'none'; + }, + }); + + if (navigator.userAgent.includes('Mac')) { + new KeyComboListener(['MetaLeft', 'KeyS'], saveDebounce, notes); + new KeyComboListener(['MetaRight', 'KeyS'], saveDebounce, notes); + } else { + new KeyComboListener(['ControlLeft', 'KeyS'], saveDebounce, notes); + new KeyComboListener(['ControlRight', 'KeyS'], saveDebounce, notes); + } + + this.elements.notes = notes; + this.elements.markdown = markdown; + this.#savedNotesValue = noteText; + + const notes_editor = $el( + 'div', + { + style: { + display: noteText == '' ? 'flex' : 'none', + height: '100%', + 'min-height': '60px', + }, + }, + notes, + ); + const notes_viewer = $el( + 'div', + { + style: { + display: noteText == '' ? 'none' : 'flex', + height: '100%', + 'min-height': '60px', + overflow: 'scroll', + 'overflow-wrap': 'anywhere', + }, + }, + markdown, + ); + + const editNotesButton = new ComfyButton({ + icon: 'pencil', + tooltip: 'Change file name', + classList: 'comfyui-button icon-button', + action: async () => { + notes_editor.style.display = + notes_editor.style.display == 'flex' ? 'none' : 'flex'; + notes_viewer.style.display = + notes_viewer.style.display == 'none' ? 'flex' : 'none'; + }, + }).element; + + return [ + $el( + 'div.row', + { + style: { 'align-items': 'center' }, + }, + [$el('h1', ['Notes']), saveNotesButton, editNotesButton], + ), + notes_editor, + notes_viewer, + ]; + })(), + ); } static UniformTagSampling( @@ -3994,7 +3726,11 @@ class DownloadView { onkeydown: async (e) => { if (e.key === 'Enter') { e.stopPropagation(); - searchButton.click(); + if (this.elements.url.value === '') { + reset(); + } else { + await update(); + } e.target.blur(); } }, @@ -4639,7 +4375,6 @@ class SettingsView { /** @type {HTMLInputElement} */ 'model-show-add-button': null, /** @type {HTMLInputElement} */ 'model-show-copy-button': null, /** @type {HTMLInputElement} */ 'model-show-load-workflow-button': null, - /** @type {HTMLInputElement} */ 'model-show-open-model-url-button': null, /** @type {HTMLInputElement} */ 'model-info-button-on-left': null, /** @type {HTMLInputElement} */ 'model-buttons-only-on-hover': null, @@ -4667,7 +4402,7 @@ class SettingsView { }; /** @return {(withoutComfyRefresh?: boolean) => Promise} */ - #updateModels = async () => {}; + #updateModels = () => {}; /** @return {() => void} */ #updateSidebarSettings = () => {}; @@ -4809,7 +4544,7 @@ class SettingsView { this.elements.saveButton = saveButton; const correctPreviewsButton = new ComfyButton({ - content: 'Fix Preview Extensions', + content: 'Fix Extensions', tooltip: 'Correct image file extensions in all model directories', action: async (e) => { const [button, icon, span] = comfyButtonDisambiguate(e.target); @@ -4834,70 +4569,6 @@ class SettingsView { }, }).element; - const scanDownloadModelInfosButton = new ComfyButton({ - content: 'Download Model Info', - tooltip: 'Scans all model files and tries to download and save model info, notes and urls.', - action: async (e) => { - const confirmation = window.confirm( - 'WARNING: This may take a while and generate MANY server requests!\nUSE AT YOUR OWN RISK!', - ); - if (!confirmation) { - return; - } - - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const data = await comfyRequest('/model-manager/models/scan', { - method: 'POST', - body: JSON.stringify({}), - }).catch((err) => { - return { success: false }; - }); - const success = data['success']; - const successMessage = success ? "Scan Finished!" : "Scan Failed!"; - const infoCount = data['infoCount']; - const notesCount = data['notesCount']; - const urlCount = data['urlCount']; - window.alert(`${successMessage}\nScanned: ${infoCount}\nSaved Notes: ${notesCount}\nSaved Url: ${urlCount}`); - comfyButtonAlert(e.target, success); - if (infoCount > 0 || notesCount > 0 || urlCount > 0) { - await this.reload(true); - } - button.disabled = false; - }, - }).element; - - const scanDownloadPreviewsButton = new ComfyButton({ - content: 'Download Missing Previews', - tooltip: 'Downloads missing model previews from model info.\nRun model info scan first!', - action: async (e) => { - const confirmation = window.confirm( - 'WARNING: This may take a while and generate MANY server requests!\nUSE AT YOUR OWN RISK!', - ); - if (!confirmation) { - return; - } - - const [button, icon, span] = comfyButtonDisambiguate(e.target); - button.disabled = true; - const data = await comfyRequest('/model-manager/preview/scan', { - method: 'POST', - body: JSON.stringify({}), - }).catch((err) => { - return { success: false }; - }); - const success = data['success']; - const successMessage = success ? "Scan Finished!" : "Scan Failed!"; - const count = data['count']; - window.alert(`${successMessage}\nPreviews Downloaded: ${count}`); - comfyButtonAlert(e.target, success); - if (count > 0) { - await this.reload(true); - } - button.disabled = false; - }, - }).element; - $el( 'div.model-manager-settings', { @@ -4947,6 +4618,11 @@ class SettingsView { 'vae_approx', ], }), + $select({ + $: (el) => (settings['sidebar-default-state'] = el), + textContent: 'Default model manager position (on start up)', + options: ['Left', 'Right', 'Top', 'Bottom', 'None'], + }), $checkbox({ $: (el) => (settings['model-real-time-search'] = el), textContent: 'Real-time search', @@ -5010,9 +4686,6 @@ class SettingsView { $checkbox({ $: (el) => (settings['model-show-load-workflow-button'] = el), textContent: 'Show "Load Workflow" button', - }),$checkbox({ - $: (el) => (settings['model-show-open-model-url-button'] = el), - textContent: 'Show "Open Model Url" button', }), $checkbox({ $: (el) => (settings['model-info-button-on-left'] = el), @@ -5051,11 +4724,6 @@ class SettingsView { textContent: 'Save notes by default.', }), $el('h2', ['Window']), - $select({ - $: (el) => (settings['sidebar-default-state'] = el), - textContent: 'Default model manager position (on start up)', - options: ['None', 'Left', 'Bottom', 'Top', 'Right'], - }), sidebarControl, $el('label', [ 'Sidebar width (on start up)', @@ -5089,18 +4757,16 @@ class SettingsView { $: (el) => (settings['text-input-always-hide-clear-button'] = el), textContent: 'Always hide "Clear Search" buttons.', }), - $el('h2', ['Scan Files']), + $el('h2', ['Model Preview Images']), $el('div', [correctPreviewsButton]), - $el('div', [scanDownloadModelInfosButton]), - $el('div', [scanDownloadPreviewsButton]), $el('h2', ['Random Tag Generator']), $select({ $: (el) => (settings['tag-generator-sampler-method'] = el), - textContent: 'Sampling method', + textContent: 'Default sampling method', options: ['Frequency', 'Uniform'], }), $el('label', [ - 'Generation count', + 'Default count', $el('input', { $: (el) => (settings['tag-generator-count'] = el), type: 'number', @@ -5110,7 +4776,7 @@ class SettingsView { }), ]), $el('label', [ - 'Minimum frequency threshold', + 'Default minimum threshold', $el('input', { $: (el) => (settings['tag-generator-threshold'] = el), type: 'number', @@ -5361,7 +5027,6 @@ class ModelManager extends ComfyDialog { this.#modelData, this.#refreshModels, this.#settingsView.elements.settings, - () => this.#tryHideModelInfo(), ); this.#browseView = new BrowseView( @@ -5922,21 +5587,14 @@ class ModelManager extends ComfyDialog { /** @type {ModelManager | undefined} */ let instance; -/** @type {ComfyDialog | undefined} */ -let modelManagerDialog; - /** * @returns {ModelManager} */ function getInstance() { - if (!instance) { - instance = new ModelManager(); - - modelManagerDialog = new ComfyDialog(); - modelManagerDialog.element.classList.add("model-manager-dialog"); - instance.element.appendChild(modelManagerDialog.element); - } - return instance; + if (!instance) { + instance = new ModelManager(); + } + return instance; } const toggleModelManager = () => { From 4463daeb413665575c61b15c8951303d5d351394 Mon Sep 17 00:00:00 2001 From: Hayden Date: Wed, 30 Oct 2024 14:05:06 +0800 Subject: [PATCH 59/59] Update pyproject.toml Add publisherId --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b0b3b02..fcb572f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,6 @@ Repository = "https://github.com/hayden-fr/ComfyUI-Model-Manager" # Used by Comfy Registry https://comfyregistry.org [tool.comfy] -PublisherId = "" +PublisherId = "hayden" DisplayName = "ComfyUI-Model-Manager" Icon = ""