From 4cc6a15fde103d602f1e55cb35d1a956269ee8d5 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Sat, 10 May 2025 13:06:25 -0700 Subject: [PATCH] Fix refresh combos command fails on nodes using V2 spec (#3848) --- .github/workflows/test-ui.yaml | 2 +- .../assets/node_with_v2_combo_input.json | 36 +++++++++++++++++++ browser_tests/tests/widget.spec.ts | 20 +++++++++++ src/scripts/app.ts | 28 ++++++++++++--- 4 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 browser_tests/assets/node_with_v2_combo_input.json diff --git a/.github/workflows/test-ui.yaml b/.github/workflows/test-ui.yaml index 538eb13c9..79e4af102 100644 --- a/.github/workflows/test-ui.yaml +++ b/.github/workflows/test-ui.yaml @@ -30,7 +30,7 @@ jobs: with: repository: 'Comfy-Org/ComfyUI_devtools' path: 'ComfyUI/custom_nodes/ComfyUI_devtools' - ref: '9d2421fd3208a310e4d0f71fca2ea0c985759c33' + ref: 'd05fd48dd787a4192e16802d4244cfcc0e2f9684' - uses: actions/setup-node@v4 with: diff --git a/browser_tests/assets/node_with_v2_combo_input.json b/browser_tests/assets/node_with_v2_combo_input.json new file mode 100644 index 000000000..a50270ba1 --- /dev/null +++ b/browser_tests/assets/node_with_v2_combo_input.json @@ -0,0 +1,36 @@ +{ + "id": "5635564e-189f-49e4-9b25-6b7634bcd595", + "revision": 0, + "last_node_id": 78, + "last_link_id": 53, + "nodes": [ + { + "id": 78, + "type": "DevToolsNodeWithV2ComboInput", + "pos": [1320, 904], + "size": [270.3199157714844, 58], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "COMBO", + "type": "COMBO", + "links": null + } + ], + "properties": { + "Node name for S&R": "DevToolsNodeWithV2ComboInput" + }, + "widgets_values": ["A"] + } + ], + "links": [], + "groups": [], + "config": {}, + "extra": { + "frontendVersion": "1.19.7" + }, + "version": 0.4 +} diff --git a/browser_tests/tests/widget.spec.ts b/browser_tests/tests/widget.spec.ts index ba517cf2d..bf1461a47 100644 --- a/browser_tests/tests/widget.spec.ts +++ b/browser_tests/tests/widget.spec.ts @@ -53,6 +53,26 @@ test.describe('Combo text widget', () => { const refreshedComboValues = await getComboValues() expect(refreshedComboValues).not.toEqual(initialComboValues) }) + + test('Should refresh combo values of nodes with v2 combo input spec', async ({ + comfyPage + }) => { + await comfyPage.loadWorkflow('node_with_v2_combo_input') + // click canvas to focus + await comfyPage.page.mouse.click(400, 300) + // press R to trigger refresh + await comfyPage.page.keyboard.press('r') + // wait for nodes' widgets to be updated + await comfyPage.page.mouse.click(400, 300) + await comfyPage.nextFrame() + // get the combo widget's values + const comboValues = await comfyPage.page.evaluate(() => { + return window['app'].graph.nodes + .find((node) => node.title === 'Node With V2 Combo Input') + .widgets.find((widget) => widget.name === 'combo_input').options.values + }) + expect(comboValues).toEqual(['A', 'B']) + }) }) test.describe('Boolean widget', () => { diff --git a/src/scripts/app.ts b/src/scripts/app.ts index 7f4dceb4e..a2fcf8e66 100644 --- a/src/scripts/app.ts +++ b/src/scripts/app.ts @@ -25,7 +25,11 @@ import { type ModelFile, type NodeId } from '@/schemas/comfyWorkflowSchema' -import type { ComfyNodeDef as ComfyNodeDefV1 } from '@/schemas/nodeDefSchema' +import { + type ComfyNodeDef as ComfyNodeDefV1, + isComboInputSpecV1, + isComboInputSpecV2 +} from '@/schemas/nodeDefSchema' import { getFromWebmFile } from '@/scripts/metadata/ebml' import { getGltfBinaryMetadata } from '@/scripts/metadata/gltf' import { getFromIsobmffFile } from '@/scripts/metadata/isobmff' @@ -1572,12 +1576,26 @@ export class ComfyApp { if (!def?.input) continue if (node.widgets) { + const nodeInputs = def.input for (const widget of node.widgets) { if (widget.type === 'combo') { - if (def['input'].required?.[widget.name] !== undefined) { - widget.options.values = def['input'].required[widget.name][0] - } else if (def['input'].optional?.[widget.name] !== undefined) { - widget.options.values = def['input'].optional[widget.name][0] + let inputType: 'required' | 'optional' | undefined + if (nodeInputs.required?.[widget.name] !== undefined) { + inputType = 'required' + } else if (nodeInputs.optional?.[widget.name] !== undefined) { + inputType = 'optional' + } + if (inputType !== undefined) { + // Get the input spec associated with the widget + const inputSpec = nodeInputs[inputType]?.[widget.name] + if (inputSpec) { + // Refresh the combo widget's options with the values from the input spec + if (isComboInputSpecV2(inputSpec)) { + widget.options.values = inputSpec[1]?.options + } else if (isComboInputSpecV1(inputSpec)) { + widget.options.values = inputSpec[0] + } + } } } }