diff --git a/__init__.py b/__init__.py index 1f5b8aa6..41c15682 100644 --- a/__init__.py +++ b/__init__.py @@ -16,7 +16,7 @@ sys.path.append('../..') from torchvision.datasets.utils import download_url # ensure .js -print("### Loading: ComfyUI-Manager (V0.5.1)") +print("### Loading: ComfyUI-Manager (V0.6)") comfy_path = os.path.dirname(folder_paths.__file__) custom_nodes_path = os.path.join(comfy_path, 'custom_nodes') @@ -26,6 +26,7 @@ comfyui_manager_path = os.path.dirname(__file__) local_db_model = os.path.join(comfyui_manager_path, "model-list.json") local_db_alter = os.path.join(comfyui_manager_path, "alter-list.json") local_db_custom_node_list = os.path.join(comfyui_manager_path, "custom-node-list.json") +local_db_extension_node_mappings = os.path.join(comfyui_manager_path, "extension-node-map.json") git_script_path = os.path.join(os.path.dirname(__file__), "git_helper.py") @@ -204,6 +205,18 @@ def check_custom_nodes_installed(json_obj): check_a_custom_node_installed(item) +@server.PromptServer.instance.routes.get("/customnode/getmappings") +async def fetch_customnode_mappings(request): + if request.rel_url.query["mode"] == "local": + uri = local_db_extension_node_mappings + else: + uri = 'https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/extension-node-map.json' + + json_obj = await get_data(uri) + + return web.json_response(json_obj, content_type='application/json') + + @server.PromptServer.instance.routes.get("/customnode/getlist") async def fetch_customnode_list(request): if request.rel_url.query["mode"] == "local": diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js index e015ddf3..d64651fa 100644 --- a/js/comfyui-manager.js +++ b/js/comfyui-manager.js @@ -4,6 +4,17 @@ import {ComfyWidgets} from "../../scripts/widgets.js"; var update_comfyui_button = null; +async function getCustomnodeMappings() { + var mode = "url"; + if(ManagerMenuDialog.instance.local_mode_checkbox.checked) + mode = "local"; + + const response = await fetch(`/customnode/getmappings?mode=${mode}`); + + const data = await response.json(); + return data; +} + async function getCustomNodes() { var mode = "url"; if(ManagerMenuDialog.instance.local_mode_checkbox.checked) @@ -165,7 +176,37 @@ class CustomNodesInstaller extends ComfyDialog { } } - async invalidateControl() { + async filter_missing_node(data) { + const mappings = await getCustomnodeMappings(); + + const name_to_url = {}; + for (const url in mappings) { + const names = mappings[url]; + for(const name in names) { + name_to_url[names[name]] = url; + } + } + + const registered_nodes = new Set(); + for (let i in LiteGraph.registered_node_types) { + registered_nodes.add(LiteGraph.registered_node_types[i].type); + } + + const missing_nodes = new Set(); + const nodes = app.graph.serialize().nodes; + for (let i in nodes) { + const node_type = nodes[i].type; + if (!registered_nodes.has(node_type)) { + const url = name_to_url[node_type]; + if(url) + missing_nodes.add(url); + } + } + + return data.filter(node => node.files.some(file => missing_nodes.has(file))); + } + + async invalidateControl(is_missing_node_mode) { this.clear(); // splash @@ -184,6 +225,9 @@ class CustomNodesInstaller extends ComfyDialog { // invalidate this.data = (await getCustomNodes()).custom_nodes; + if(is_missing_node_mode) + this.data = await this.filter_missing_node(this.data); + this.element.removeChild(msg); while (this.element.children.length) { @@ -366,9 +410,9 @@ class CustomNodesInstaller extends ComfyDialog { this.element.appendChild(close_button); } - async show() { + async show(is_missing_node_mode) { try { - this.invalidateControl(); + this.invalidateControl(is_missing_node_mode); this.element.style.display = "block"; } @@ -867,7 +911,18 @@ class ManagerMenuDialog extends ComfyDialog { () => { if(!CustomNodesInstaller.instance) CustomNodesInstaller.instance = new CustomNodesInstaller(app); - CustomNodesInstaller.instance.show(); + CustomNodesInstaller.instance.show(false); + } + }), + + $el("button", { + type: "button", + textContent: "Install Custom Nodes (missing)", + onclick: + () => { + if(!CustomNodesInstaller.instance) + CustomNodesInstaller.instance = new CustomNodesInstaller(app); + CustomNodesInstaller.instance.show(true); } }),