From 8a165549f3f9d5ee65e307989be0e05975deb5bc Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" Date: Mon, 15 Jan 2024 23:50:03 +0900 Subject: [PATCH] feat: support component paste feature --- README.md | 19 +++++++++++ __init__.py | 2 +- js/components-manager.js | 70 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0c171d74..c3fa0783 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,25 @@ NODE_CLASS_MAPPINGS.update({ * **All scripts are executed from the root path of the corresponding custom node.** +## Component Paste +* When pasting a component from the clipboard, it supports text in the following JSON format. (text/plain) +``` +{ + "kind": "ComyUI Components", + "timestamp": , + "components": + { + : + } +} +``` +* `` Ensure that the timestamp is always unique. +* "components" should have the same structure as the content of the file stored in ComfyUI-Manager/components. + * ``: The name should be in the format `::`. + * ``: In the nodedata of the group node. + + + ## Support of missing nodes installation ![missing-menu](misc/missing-menu.png) diff --git a/__init__.py b/__init__.py index e2c896ff..b58cab44 100644 --- a/__init__.py +++ b/__init__.py @@ -28,7 +28,7 @@ except: print(f"[WARN] ComfyUI-Manager: Your ComfyUI version is outdated. Please update to the latest version.") -version = [2, 0, 1] +version = [2, 1] version_str = f"V{version[0]}.{version[1]}" + (f'.{version[2]}' if len(version) > 2 else '') print(f"### Loading: ComfyUI-Manager ({version_str})") diff --git a/js/components-manager.js b/js/components-manager.js index b22bc14e..92e20f85 100644 --- a/js/components-manager.js +++ b/js/components-manager.js @@ -127,11 +127,11 @@ export async function save_as_component(node, app) { if(confirm(`Will you save/overwrite component '${component_name}'?`)) { let subgraph = app.graph.extra?.groupNodes?.[component_name]; - let body = - { - name: component_name, - workflow: subgraph - }; + let body = + { + name: component_name, + workflow: subgraph + }; const res = await api.fetchApi('/manager/component/save', { method: "POST", @@ -192,4 +192,62 @@ export async function save_as_component(node, app) { } else app.ui.dialog.show(`Failed to save component.`); -} \ No newline at end of file +} + +async function import_component(component_name, subgraph) { + if(confirm("Will you save component?\n(If canceled, the component won't be saved and can only be used within the current workflow.)")) { + let body = + { + name: component_name, + workflow: subgraph + }; + + const res = await api.fetchApi('/manager/component/save', { + method: "POST", + headers: { "Content-Type": "application/json", }, + body: JSON.stringify(body) + }); + } + + storeGroupNode(component_name, subgraph); + const config = new GroupNodeConfig(component_name, subgraph); + await config.registerType(); +} + +// Using a timestamp prevents duplicate pastes and ensures the prevention of re-deletion of litegrapheditor_clipboard. +let last_paste_timestamp = null; + +function handlePaste(e) { + let data = (e.clipboardData || window.clipboardData); + const items = data.items; + for(const item of items) { + if(item.kind == 'string' && item.type == 'text/plain') { + data = data.getData("text/plain"); + try { + let json_data = JSON.parse(data); + if(json_data.kind == 'ComfyUI Components' && last_paste_timestamp != json_data.timestamp) { + last_paste_timestamp = json_data.timestamp; + + let msg = 'Components are added:\n'; + for(let name in json_data.components) { + let subgraph = json_data.components[name]; + import_component(name, subgraph); + msg += ' - ' + name + '\n'; + } + app.ui.dialog.show(msg); + + // disable paste node + localStorage.removeItem("litegrapheditor_clipboard", null); + } + else { + console.log('This components are already pasted: ignored'); + } + } + catch { + // nothing to do + } + } + } +} + +document.addEventListener("paste", handlePaste); \ No newline at end of file