diff --git a/README.md b/README.md index ca5a3e3..c2dac13 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ I made this fork because the original repo was inactive and missing many things - View model metadata, including training tags and bucket resolutions. - Delete or move a model. +- Read, edit and save notes in a `.txt` file beside the model. ### ComfyUI Node Graph diff --git a/__init__.py b/__init__.py index 16a49b1..51150b5 100644 --- a/__init__.py +++ b/__init__.py @@ -457,11 +457,11 @@ async def get_model_info(request): file_name, _ = os.path.splitext(file) txt_file = file_name + ".txt" - description = "" + notes = "" if os.path.isfile(txt_file): with open(txt_file, 'r', encoding="utf-8") as f: - description = f.read() - info["Description"] = description + notes = f.read() + info["Notes"] = notes if metadata is not None: img_buckets = metadata.get("ss_bucket_info", "{}") @@ -635,6 +635,33 @@ async def delete_model(request): return web.json_response(result) +@server.PromptServer.instance.routes.post("/model-manager/notes/save") +async def set_notes(request): + body = await request.json() + + text = body.get("notes", None) + if type(text) is not str: + return web.json_response({ "success": False }) + + model_path = body.get("path", None) + if type(model_path) is not str: + return web.json_response({ "success": False }) + model_path, _ = search_path_to_system_path(model_path) + file_path_without_extension, _ = os.path.splitext(model_path) + filename = os.path.normpath(file_path_without_extension + ".txt") + if text.isspace() or text == "": + if os.path.exists(filename): + os.remove(filename) + else: + try: + with open(filename, "w") as f: + f.write(text) + except: + web.json_response({ "success": False }) + + return web.json_response({ "success": True }) + + WEB_DIRECTORY = "web" NODE_CLASS_MAPPINGS = {} __all__ = ["NODE_CLASS_MAPPINGS"] diff --git a/web/model-manager.css b/web/model-manager.css index 8152388..967d718 100644 --- a/web/model-manager.css +++ b/web/model-manager.css @@ -442,11 +442,12 @@ width: 100%; } -.model-manager .model-manager-settings textarea { +.model-manager textarea { width: 100%; font-size: 1.2em; border: solid 2px var(--border-color); border-radius: 8px; + resize: vertical; } .model-preview-select-radio-container img { diff --git a/web/model-manager.js b/web/model-manager.js index 26d505c..3ec1fbe 100644 --- a/web/model-manager.js +++ b/web/model-manager.js @@ -1386,22 +1386,25 @@ class ModelManager extends ComfyDialog { if (confirmation === affirmation) { const container = this.#el.modelInfoContainer; const path = encodeURIComponent(container.dataset.path); - await request( + deleted = await request( `/model-manager/model/delete?path=${path}`, { method: "POST", } ) .then((result) => { - if (result["success"]) + const deleted = result["success"]; + if (deleted) { container.innerHTML = ""; this.#el.modelInfoView.style.display = "none"; this.#modelTab_updateModels(); - deleted = true; } + return deleted; }) - .catch(err => {}); + .catch(err => { + return false; + }); } if (!deleted) { buttonAlert(e.target, false); @@ -1421,8 +1424,7 @@ class ModelManager extends ComfyDialog { textContent: "Move", onclick: async(e) => { const container = this.#el.modelInfoContainer; - let moved = false; - await request( + const moved = await request( `/model-manager/model/move`, { method: "POST", @@ -1433,15 +1435,18 @@ class ModelManager extends ComfyDialog { } ) .then((result) => { - if (result["success"]) + const moved = result["success"]; + if (moved) { container.innerHTML = ""; this.#el.modelInfoView.style.display = "none"; this.#modelTab_updateModels(); - moved = true; } + return moved; }) - .catch(err => {}); + .catch(err => { + return false; + }); if (!moved) { buttonAlert(e.target, false); } @@ -1644,7 +1649,7 @@ class ModelManager extends ComfyDialog { innerHtml.push($el("h1", [filename])); } for (const [key, value] of Object.entries(info)) { - if (value === undefined || value === null || value === "") { + if (value === undefined || value === null) { continue; } @@ -1669,7 +1674,38 @@ class ModelManager extends ComfyDialog { } } else { - innerHtml.push($el("p", [key + ": " + value])); + if (key === "Notes") { + innerHtml.push($el("h2", [key + ":"])); + const noteArea = $el("textarea.comfy-multiline-input", { + value: value, + rows: 5, + }); + innerHtml.push(noteArea); + innerHtml.push($el("button", { + textContent: "Save Notes", + onclick: (e) => { + const saved = request( + "/model-manager/notes/save", + { + method: "POST", + body: JSON.stringify({ + "path": this.#el.modelInfoContainer.dataset.path, + "notes": noteArea.value, + }), + } + ).then((result) => { + return result["success"]; + }) + .catch((err) => { + return false; + }); + buttonAlert(e.target, saved); + }, + })); + } + else { + innerHtml.push($el("p", [key + ": " + value])); + } } } infoHtml.append.apply(infoHtml, innerHtml); @@ -2106,27 +2142,21 @@ class ModelManager extends ComfyDialog { })(); record["overwrite"] = this.#el.modelInfoOverwrite.checked; e.target.disabled = true; - let success = true; - let resultText = "✔"; - await request( + const [success, resultText] = await request( "/model-manager/model/download", { method: "POST", body: JSON.stringify(record), } ).then(data => { - if (data["success"] !== true) { - // TODO: notify user in app - console.error('Failed to download model:', data); - success = false; - resultText = "📥︎"; - } + const success = data["success"]; + return [success, success ? "✔" : "📥︎"]; }).catch(err => { - // TODO: notify user in app - console.error('Failed to download model:', err); - success = false; - resultText = "📥︎"; + return [false, "📥︎"]; }); + if (success) { + this.#modelTab_updateModels(); + } buttonAlert(e.target, success, "✔", "✖", resultText); e.target.disabled = success; },