From a7c21151668e2286e55582b6d4a6fa9aff2c9b53 Mon Sep 17 00:00:00 2001 From: Alexander Brown Date: Tue, 10 Feb 2026 19:37:17 -0800 Subject: [PATCH] feat: add WidgetValueStore for centralized widget value management (#8594) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Implements Phase 1 of the **Vue-owns-truth** pattern for widget values. Widget values are now canonical in a Pinia store; `widget.value` delegates to the store while preserving full backward compatibility. ## Changes - **New store**: `src/stores/widgetValueStore.ts` - centralized widget value storage with `get/set/remove/removeNode` API - **BaseWidget integration**: `widget.value` getter/setter now delegates to store when widget is associated with a node - **LGraphNode wiring**: `addCustomWidget()` automatically calls `widget.setNodeId(this.id)` to wire widgets to their nodes - **Test fixes**: Added Pinia setup to test files that use widgets ## Why This foundation enables: - Vue components to reactively bind to widget values via `computed(() => store.get(...))` - Future Yjs/CRDT backing for real-time collaboration - Cleaner separation between Vue state and LiteGraph rendering ## Backward Compatibility | Extension Pattern | Status | |-------------------|--------| | `widget.value = x` | ✅ Works unchanged | | `node.widgets[i].value` | ✅ Works unchanged | | `widget.callback` | ✅ Still fires | | `node.onWidgetChanged` | ✅ Still fires | ## Testing - ✅ 4252 unit tests pass - ✅ Build succeeds ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8594-feat-add-WidgetValueStore-for-centralized-widget-value-management-2fc6d73d36508160886fcb9f3ebd941e) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp Co-authored-by: github-actions Co-authored-by: GitHub Action --- .../tests/subgraph-duplicate-ids.spec.ts | 7 - browser_tests/tests/subgraph.spec.ts | 10 +- ...ue-nodes-upload-widgets-chromium-linux.png | Bin 81083 -> 81043 bytes .../rightSidePanel/parameters/WidgetItem.vue | 5 +- .../graph/useGraphNodeManager.test.ts | 89 +++++--- src/composables/graph/useGraphNodeManager.ts | 101 ++++----- src/core/graph/subgraph/proxyWidget.test.ts | 8 +- src/core/graph/subgraph/proxyWidget.ts | 9 +- src/core/graph/subgraph/proxyWidgetUtils.ts | 11 +- src/extensions/core/groupNode.ts | 2 +- src/extensions/core/previewAny.ts | 8 +- src/extensions/core/uploadAudio.ts | 14 +- src/lib/litegraph/src/LGraph.ts | 12 +- src/lib/litegraph/src/LGraphCanvas.ts | 2 +- src/lib/litegraph/src/LGraphNode.test.ts | 3 + src/lib/litegraph/src/LGraphNode.ts | 33 ++- .../src/LGraphNode.widgetOrder.test.ts | 3 + src/lib/litegraph/src/types/widgets.ts | 15 +- src/lib/litegraph/src/utils/type.ts | 10 + .../litegraph/src/widgets/BaseWidget.test.ts | 193 ++++++++++++++++++ src/lib/litegraph/src/widgets/BaseWidget.ts | 76 +++++-- .../composables/useLitegraphSettings.ts | 7 - .../settings/constants/coreSettings.ts | 3 +- .../vueNodes/components/LGraphNodePreview.vue | 1 + .../vueNodes/components/NodeHeader.vue | 13 +- .../vueNodes/components/NodeWidgets.test.ts | 7 +- .../vueNodes/components/NodeWidgets.vue | 75 ++++--- .../components/WidgetSelectDefault.vue | 3 +- .../components/WidgetSelectDropdown.vue | 3 +- .../widgets/composables/useMarkdownWidget.ts | 21 +- .../widgets/composables/useStringWidget.ts | 17 +- .../composables/useWidgetRenderer.test.ts | 4 +- src/scripts/domWidget.ts | 2 +- src/scripts/metadata/png.ts | 1 - src/stores/widgetValueStore.test.ts | 155 ++++++++++++++ src/stores/widgetValueStore.ts | 77 +++++++ 36 files changed, 814 insertions(+), 186 deletions(-) create mode 100644 src/lib/litegraph/src/widgets/BaseWidget.test.ts create mode 100644 src/stores/widgetValueStore.test.ts create mode 100644 src/stores/widgetValueStore.ts diff --git a/browser_tests/tests/subgraph-duplicate-ids.spec.ts b/browser_tests/tests/subgraph-duplicate-ids.spec.ts index 1fb77bed8d..17e458f3b3 100644 --- a/browser_tests/tests/subgraph-duplicate-ids.spec.ts +++ b/browser_tests/tests/subgraph-duplicate-ids.spec.ts @@ -5,13 +5,6 @@ import { comfyPageFixture as test } from '../fixtures/ComfyPage' test.describe('Subgraph duplicate ID remapping', { tag: ['@subgraph'] }, () => { const WORKFLOW = 'subgraphs/subgraph-nested-duplicate-ids' - test.beforeEach(async ({ comfyPage }) => { - await comfyPage.settings.setSetting( - 'Comfy.Graph.DeduplicateSubgraphNodeIds', - true - ) - }) - test('All node IDs are globally unique after loading', async ({ comfyPage }) => { diff --git a/browser_tests/tests/subgraph.spec.ts b/browser_tests/tests/subgraph.spec.ts index cc78b49539..c937573dfc 100644 --- a/browser_tests/tests/subgraph.spec.ts +++ b/browser_tests/tests/subgraph.spec.ts @@ -61,7 +61,10 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => { await subgraphNode.navigateIntoSubgraph() const initialCount = await getSubgraphSlotCount(comfyPage, 'inputs') - const vaeEncodeNode = await comfyPage.nodeOps.getNodeRefById('2') + const [vaeEncodeNode] = await comfyPage.nodeOps.getNodeRefsByType( + 'VAEEncode', + true + ) await comfyPage.subgraph.connectFromInput(vaeEncodeNode, 0) await comfyPage.nextFrame() @@ -77,7 +80,10 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => { await subgraphNode.navigateIntoSubgraph() const initialCount = await getSubgraphSlotCount(comfyPage, 'outputs') - const vaeEncodeNode = await comfyPage.nodeOps.getNodeRefById('2') + const [vaeEncodeNode] = await comfyPage.nodeOps.getNodeRefsByType( + 'VAEEncode', + true + ) await comfyPage.subgraph.connectToOutput(vaeEncodeNode, 0) await comfyPage.nextFrame() diff --git a/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png b/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png index a3ff647343d6af6e8e2636004cea1c5882815e26..b4f2e3de582f721d7fc9f44237af201962787a60 100644 GIT binary patch literal 81043 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 @Pf!!R2xE%do9YzR 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 M$*aqi$e6wRAKLg?(f|Me diff --git a/src/components/rightSidePanel/parameters/WidgetItem.vue b/src/components/rightSidePanel/parameters/WidgetItem.vue index 33768adad5..58c3f8db5e 100644 --- a/src/components/rightSidePanel/parameters/WidgetItem.vue +++ b/src/components/rightSidePanel/parameters/WidgetItem.vue @@ -83,10 +83,7 @@ const favoriteNode = computed(() => ) const widgetValue = computed({ - get: () => { - widget.vueTrack?.() - return widget.value - }, + get: () => widget.value, set: (newValue: string | number | boolean | object) => { emit('update:widgetValue', newValue) } diff --git a/src/composables/graph/useGraphNodeManager.test.ts b/src/composables/graph/useGraphNodeManager.test.ts index ba22d98cd2..3669f06e4b 100644 --- a/src/composables/graph/useGraphNodeManager.test.ts +++ b/src/composables/graph/useGraphNodeManager.test.ts @@ -1,49 +1,76 @@ import { setActivePinia } from 'pinia' import { createTestingPinia } from '@pinia/testing' -import { describe, expect, it, vi } from 'vitest' -import { nextTick, watch } from 'vue' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { computed, nextTick, watch } from 'vue' import { useGraphNodeManager } from '@/composables/graph/useGraphNodeManager' -import { LGraph, LGraphNode } from '@/lib/litegraph/src/litegraph' +import { BaseWidget, LGraph, LGraphNode } from '@/lib/litegraph/src/litegraph' import { NodeSlotType } from '@/lib/litegraph/src/types/globalEnums' - -setActivePinia(createTestingPinia()) - -function createTestGraph() { - const graph = new LGraph() - const node = new LGraphNode('test') - node.addInput('input', 'INT') - node.addWidget('number', 'testnum', 2, () => undefined, {}) - graph.add(node) - - const { vueNodeData } = useGraphNodeManager(graph) - const onReactivityUpdate = vi.fn() - watch(vueNodeData, onReactivityUpdate) - - return [node, graph, onReactivityUpdate] as const -} +import { useWidgetValueStore } from '@/stores/widgetValueStore' describe('Node Reactivity', () => { - it('should trigger on callback', async () => { - const [node, , onReactivityUpdate] = createTestGraph() - - node.widgets![0].callback!(2) - await nextTick() - expect(onReactivityUpdate).toHaveBeenCalledTimes(1) + beforeEach(() => { + setActivePinia(createTestingPinia({ stubActions: false })) }) - it('should remain reactive after a connection is made', async () => { - const [node, graph, onReactivityUpdate] = createTestGraph() + function createTestGraph() { + const graph = new LGraph() + const node = new LGraphNode('test') + node.addInput('input', 'INT') + node.addWidget('number', 'testnum', 2, () => undefined, {}) + graph.add(node) + + const { vueNodeData } = useGraphNodeManager(graph) + + return { node, graph, vueNodeData } + } + + it('widget values are reactive through the store', async () => { + const { node } = createTestGraph() + const store = useWidgetValueStore() + const widget = node.widgets![0] + + // Verify widget is a BaseWidget with correct value and node assignment + expect(widget).toBeInstanceOf(BaseWidget) + expect(widget.value).toBe(2) + expect((widget as BaseWidget).node.id).toBe(node.id) + + // Initial value should be in store after setNodeId was called + expect(store.getWidget(node.id, 'testnum')?.value).toBe(2) + + const onValueChange = vi.fn() + const widgetValue = computed( + () => store.getWidget(node.id, 'testnum')?.value + ) + watch(widgetValue, onValueChange) + + widget.value = 42 + await nextTick() + + expect(widgetValue.value).toBe(42) + expect(onValueChange).toHaveBeenCalledTimes(1) + }) + + it('widget values remain reactive after a connection is made', async () => { + const { node, graph } = createTestGraph() + const store = useWidgetValueStore() + const onValueChange = vi.fn() graph.trigger('node:slot-links:changed', { - nodeId: '1', + nodeId: String(node.id), slotType: NodeSlotType.INPUT }) await nextTick() - onReactivityUpdate.mockClear() - node.widgets![0].callback!(2) + const widgetValue = computed( + () => store.getWidget(node.id, 'testnum')?.value + ) + watch(widgetValue, onValueChange) + + node.widgets![0].value = 99 await nextTick() - expect(onReactivityUpdate).toHaveBeenCalledTimes(1) + + expect(onValueChange).toHaveBeenCalledTimes(1) + expect(widgetValue.value).toBe(99) }) }) diff --git a/src/composables/graph/useGraphNodeManager.ts b/src/composables/graph/useGraphNodeManager.ts index 8958655ffa..3ad3a06304 100644 --- a/src/composables/graph/useGraphNodeManager.ts +++ b/src/composables/graph/useGraphNodeManager.ts @@ -3,7 +3,7 @@ * Provides event-driven reactivity with performance optimizations */ import { reactiveComputed } from '@vueuse/core' -import { customRef, reactive, shallowReactive } from 'vue' +import { reactive, shallowReactive } from 'vue' import { useChainCallback } from '@/composables/functional/useChainCallback' import { isProxyWidget } from '@/core/graph/subgraph/proxyWidget' @@ -11,10 +11,7 @@ import type { INodeInputSlot, INodeOutputSlot } from '@/lib/litegraph/src/interfaces' -import type { - IBaseWidget, - IWidgetOptions -} from '@/lib/litegraph/src/types/widgets' +import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets' import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations' import { LayoutSource } from '@/renderer/core/layout/types' import type { NodeId } from '@/renderer/core/layout/types' @@ -41,19 +38,37 @@ export interface WidgetSlotMetadata { linked: boolean } +/** + * Minimal render-specific widget data extracted from LiteGraph widgets. + * Value and metadata (label, hidden, disabled, etc.) are accessed via widgetValueStore. + */ export interface SafeWidgetData { + nodeId?: NodeId name: string type: string - value: WidgetValue - borderStyle?: string + /** Callback to invoke when widget value changes (wraps LiteGraph callback + triggerDraw) */ callback?: ((value: unknown) => void) | undefined + /** Control widget for seed randomization/increment/decrement */ controlWidget?: SafeControlWidget + /** Whether widget has custom layout size computation */ hasLayoutSize?: boolean + /** Whether widget is a DOM widget */ isDOMWidget?: boolean - label?: string + /** Node type (for subgraph promoted widgets) */ nodeType?: string - options?: IWidgetOptions + /** + * Widget options needed for render decisions. + * Note: Most metadata should be accessed via widgetValueStore.getWidget(). + */ + options?: { + canvasOnly?: boolean + advanced?: boolean + hidden?: boolean + read_only?: boolean + } + /** Input specification from node definition */ spec?: InputSpec + /** Input slot metadata (index and link status) */ slotMetadata?: WidgetSlotMetadata } @@ -95,23 +110,6 @@ export interface GraphNodeManager { cleanup(): void } -function widgetWithVueTrack( - widget: IBaseWidget -): asserts widget is IBaseWidget & { vueTrack: () => void } { - if (widget.vueTrack) return - - customRef((track, trigger) => { - widget.callback = useChainCallback(widget.callback, trigger) - widget.vueTrack = track - return { get() {}, set() {} } - }) -} -function useReactiveWidgetValue(widget: IBaseWidget) { - widgetWithVueTrack(widget) - widget.vueTrack() - return widget.value -} - function getControlWidget(widget: IBaseWidget): SafeControlWidget | undefined { const cagWidget = widget.linkedWidgets?.find( (w) => w.name == 'control_after_generate' @@ -133,26 +131,18 @@ function getNodeType(node: LGraphNode, widget: IBaseWidget) { * Shared widget enhancements used by both safeWidgetMapper and Right Side Panel */ interface SharedWidgetEnhancements { - /** Reactive widget value that updates when the widget changes */ - value: WidgetValue /** Control widget for seed randomization/increment/decrement */ controlWidget?: SafeControlWidget /** Input specification from node definition */ spec?: InputSpec /** Node type (for subgraph promoted widgets) */ nodeType?: string - /** Border style for promoted/advanced widgets */ - borderStyle?: string - /** Widget label */ - label?: string - /** Widget options */ - options?: IWidgetOptions } /** * Extracts common widget enhancements shared across different rendering contexts. - * This function centralizes the logic for extracting metadata and reactive values - * from widgets, ensuring consistency between Nodes 2.0 and Right Side Panel. + * This function centralizes the logic for extracting metadata from widgets. + * Note: Value and metadata (label, options, hidden, etc.) are accessed via widgetValueStore. */ export function getSharedWidgetEnhancements( node: LGraphNode, @@ -161,17 +151,9 @@ export function getSharedWidgetEnhancements( const nodeDefStore = useNodeDefStore() return { - value: useReactiveWidgetValue(widget), controlWidget: getControlWidget(widget), spec: nodeDefStore.getInputSpecForWidget(node, widget.name), - nodeType: getNodeType(node, widget), - borderStyle: widget.promoted - ? 'ring ring-component-node-widget-promoted' - : widget.advanced - ? 'ring ring-component-node-widget-advanced' - : undefined, - label: widget.label, - options: widget.options as IWidgetOptions + nodeType: getNodeType(node, widget) } } @@ -212,7 +194,7 @@ function safeWidgetMapper( ): (widget: IBaseWidget) => SafeWidgetData { return function (widget) { try { - // Get shared enhancements used by both Nodes 2.0 and Right Side Panel + // Get shared enhancements (controlWidget, spec, nodeType) const sharedEnhancements = getSharedWidgetEnhancements(node, widget) const slotInfo = slotMetadata.get(widget.name) @@ -228,20 +210,41 @@ function safeWidgetMapper( node.widgets?.forEach((w) => w.triggerDraw?.()) } + // Extract only render-critical options (canvasOnly, advanced, read_only) + const options = widget.options + ? { + canvasOnly: widget.options.canvasOnly, + advanced: widget.advanced, + hidden: widget.options.hidden, + read_only: widget.options.read_only + } + : undefined + const subgraphId = node.isSubgraphNode() && node.subgraph.id + + const localId = isProxyWidget(widget) + ? widget._overlay?.nodeId + : undefined + const nodeId = + subgraphId && localId ? `${subgraphId}:${localId}` : undefined + const name = isProxyWidget(widget) + ? widget._overlay.widgetName + : widget.name + return { - name: widget.name, + nodeId, + name, type: widget.type, ...sharedEnhancements, callback, hasLayoutSize: typeof widget.computeLayoutSize === 'function', isDOMWidget: isDOMWidget(widget), + options, slotMetadata: slotInfo } } catch (error) { return { name: widget.name || 'unknown', - type: widget.type || 'text', - value: undefined + type: widget.type || 'text' } } } diff --git a/src/core/graph/subgraph/proxyWidget.test.ts b/src/core/graph/subgraph/proxyWidget.test.ts index 956e4b9b48..188aba33ac 100644 --- a/src/core/graph/subgraph/proxyWidget.test.ts +++ b/src/core/graph/subgraph/proxyWidget.test.ts @@ -1,4 +1,6 @@ -import { describe, expect, test, vi } from 'vitest' +import { createTestingPinia } from '@pinia/testing' +import { setActivePinia } from 'pinia' +import { beforeEach, describe, expect, test, vi } from 'vitest' import { registerProxyWidgets } from '@/core/graph/subgraph/proxyWidget' import { promoteWidget } from '@/core/graph/subgraph/proxyWidgetUtils' @@ -43,6 +45,10 @@ function setupSubgraph( } describe('Subgraph proxyWidgets', () => { + beforeEach(() => { + setActivePinia(createTestingPinia({ stubActions: false })) + }) + test('Can add simple widget', () => { const [subgraphNode, innerNodes] = setupSubgraph(1) innerNodes[0].addWidget('text', 'stringWidget', 'value', () => {}) diff --git a/src/core/graph/subgraph/proxyWidget.ts b/src/core/graph/subgraph/proxyWidget.ts index 60f6d456aa..1370dfe499 100644 --- a/src/core/graph/subgraph/proxyWidget.ts +++ b/src/core/graph/subgraph/proxyWidget.ts @@ -115,9 +115,11 @@ const onConfigure = function ( if (isActiveGraph && w instanceof DOMWidgetImpl) setWidget(w) return [w] }) - this.widgets = this.widgets.filter( - (w) => !isProxyWidget(w) && !parsed.some(([, name]) => w.name === name) - ) + this.widgets = this.widgets.filter((w) => { + if (isProxyWidget(w)) return false + const widgetName = w.name + return !parsed.some(([, name]) => widgetName === name) + }) this.widgets.push(...newWidgets) canvasStore.canvas?.setDirty(true, true) @@ -152,6 +154,7 @@ function newProxyWidget( computedHeight: undefined, isProxyWidget: true, last_y: undefined, + label: name, name, node: subgraphNode, onRemove: undefined, diff --git a/src/core/graph/subgraph/proxyWidgetUtils.ts b/src/core/graph/subgraph/proxyWidgetUtils.ts index 2cd8685a67..ad99f74f2b 100644 --- a/src/core/graph/subgraph/proxyWidgetUtils.ts +++ b/src/core/graph/subgraph/proxyWidgetUtils.ts @@ -57,15 +57,20 @@ export function demoteWidget( widget.promoted = false } +function getWidgetName(w: IBaseWidget): string { + return isProxyWidget(w) ? w._overlay.widgetName : w.name +} + export function matchesWidgetItem([nodeId, widgetName]: [string, string]) { - return ([n, w]: WidgetItem) => n.id == nodeId && w.name === widgetName + return ([n, w]: WidgetItem) => + n.id == nodeId && getWidgetName(w) === widgetName } export function matchesPropertyItem([n, w]: WidgetItem) { return ([nodeId, widgetName]: [string, string]) => - n.id == nodeId && w.name === widgetName + n.id == nodeId && getWidgetName(w) === widgetName } export function widgetItemToProperty([n, w]: WidgetItem): [string, string] { - return [`${n.id}`, w.name] + return [`${n.id}`, getWidgetName(w)] } function getParentNodes(): SubgraphNode[] { diff --git a/src/extensions/core/groupNode.ts b/src/extensions/core/groupNode.ts index ed7dcbb205..b5c4181dc7 100644 --- a/src/extensions/core/groupNode.ts +++ b/src/extensions/core/groupNode.ts @@ -1412,7 +1412,7 @@ export class GroupNodeHandler { handlerGroupData.oldToNewWidgetMap[Number(n)]?.[w] const widget = this.widgets.find((wg) => wg.name === widgetName) if (widget) { - widget.type = 'hidden' + widget.hidden = true widget.computeSize = () => [0, -4] } } diff --git a/src/extensions/core/previewAny.ts b/src/extensions/core/previewAny.ts index d06ba15843..f6afeb311c 100644 --- a/src/extensions/core/previewAny.ts +++ b/src/extensions/core/previewAny.ts @@ -19,14 +19,14 @@ useExtensionService().registerExtension({ const showValueWidget = ComfyWidgets['MARKDOWN']( this, - 'preview', + 'preview_markdown', ['MARKDOWN', {}], app ).widget as DOMWidget const showValueWidgetPlain = ComfyWidgets['STRING']( this, - 'preview', + 'preview_text', ['STRING', { multiline: true }], app ).widget as DOMWidget @@ -48,6 +48,7 @@ useExtensionService().registerExtension({ showValueWidgetPlain.options.hidden = value } + showValueWidget.label = 'Preview' showValueWidget.hidden = true showValueWidget.options.hidden = true showValueWidget.options.read_only = true @@ -55,6 +56,7 @@ useExtensionService().registerExtension({ showValueWidget.element.disabled = true showValueWidget.serialize = false + showValueWidgetPlain.label = 'Preview' showValueWidgetPlain.hidden = false showValueWidgetPlain.options.hidden = false showValueWidgetPlain.options.read_only = true @@ -71,7 +73,7 @@ useExtensionService().registerExtension({ : onExecuted.apply(this, [message]) const previewWidgets = - this.widgets?.filter((w) => w.name === 'preview') ?? [] + this.widgets?.filter((w) => w.name.startsWith('preview_')) ?? [] for (const previewWidget of previewWidgets) { const text = message.text ?? '' diff --git a/src/extensions/core/uploadAudio.ts b/src/extensions/core/uploadAudio.ts index c1450632b8..86ecd9c4ae 100644 --- a/src/extensions/core/uploadAudio.ts +++ b/src/extensions/core/uploadAudio.ts @@ -23,6 +23,7 @@ import { getNodeByLocatorId } from '@/utils/graphTraversalUtil' import { api } from '../../scripts/api' import { app } from '../../scripts/app' +import { useWidgetValueStore } from '@/stores/widgetValueStore' function updateUIWidget( audioUIWidget: DOMWidget, @@ -137,9 +138,16 @@ app.registerExtension({ } } - let value = '' - audioUIWidget.options.getValue = () => value - audioUIWidget.options.setValue = (v) => (value = v) + audioUIWidget.options.getValue = () => + (useWidgetValueStore().getWidget(node.id, inputName) + ?.value as string) ?? '' + audioUIWidget.options.setValue = (v) => { + const widgetState = useWidgetValueStore().getWidget( + node.id, + inputName + ) + if (widgetState) widgetState.value = v + } return { widget: audioUIWidget } } diff --git a/src/lib/litegraph/src/LGraph.ts b/src/lib/litegraph/src/LGraph.ts index e96b61c5cb..c82f3a19e1 100644 --- a/src/lib/litegraph/src/LGraph.ts +++ b/src/lib/litegraph/src/LGraph.ts @@ -4,6 +4,7 @@ import { SUBGRAPH_INPUT_ID, SUBGRAPH_OUTPUT_ID } from '@/lib/litegraph/src/constants' +import { isNodeBindable } from '@/lib/litegraph/src/utils/type' import type { UUID } from '@/lib/litegraph/src/utils/uuid' import { createUuidv4, zeroUuid } from '@/lib/litegraph/src/utils/uuid' import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations' @@ -158,7 +159,6 @@ export class LGraph static STATUS_STOPPED = 1 static STATUS_RUNNING = 2 - static deduplicateSubgraphIds = false /** List of LGraph properties that are manually handled by {@link LGraph.configure}. */ static readonly ConfigureProperties = new Set([ @@ -962,6 +962,14 @@ export class LGraph node.flags.ghost = true } + // Register all widgets with the WidgetValueStore now that node has a valid ID. + // Widgets added before the node was in the graph deferred their setNodeId call. + if (node.widgets) { + for (const widget of node.widgets) { + if (isNodeBindable(widget)) widget.setNodeId(node.id) + } + } + node.graph = this this._version++ @@ -2437,7 +2445,7 @@ export class LGraph this.subgraphs.get(subgraph.id)?.configure(subgraph) } - if (this.isRootGraph && LGraph.deduplicateSubgraphIds) { + if (this.isRootGraph) { const reservedNodeIds = nodesData ?.map((n) => n.id) .filter((id): id is number => typeof id === 'number') diff --git a/src/lib/litegraph/src/LGraphCanvas.ts b/src/lib/litegraph/src/LGraphCanvas.ts index 130a27809b..e05b3f6a50 100644 --- a/src/lib/litegraph/src/LGraphCanvas.ts +++ b/src/lib/litegraph/src/LGraphCanvas.ts @@ -8347,7 +8347,7 @@ export class LGraphCanvas implements CustomEventDispatcher callback: LGraphCanvas.onMenuNodeCollapse }) } - if (node.widgets?.some((w) => w.advanced)) { + if (node.hasAdvancedWidgets()) { options.push({ content: node.showAdvanced ? 'Hide Advanced' : 'Show Advanced', callback: LGraphCanvas.onMenuToggleAdvanced diff --git a/src/lib/litegraph/src/LGraphNode.test.ts b/src/lib/litegraph/src/LGraphNode.test.ts index 5b498dac34..6ee5049a1c 100644 --- a/src/lib/litegraph/src/LGraphNode.test.ts +++ b/src/lib/litegraph/src/LGraphNode.test.ts @@ -1,3 +1,5 @@ +import { createTestingPinia } from '@pinia/testing' +import { setActivePinia } from 'pinia' import { afterEach, beforeEach, describe, expect, vi } from 'vitest' import type { @@ -42,6 +44,7 @@ describe('LGraphNode', () => { let origLiteGraph: typeof LiteGraph beforeEach(() => { + setActivePinia(createTestingPinia({ stubActions: false })) origLiteGraph = Object.assign({}, LiteGraph) // @ts-expect-error Intended: Force remove an otherwise readonly non-optional property delete origLiteGraph.Classes diff --git a/src/lib/litegraph/src/LGraphNode.ts b/src/lib/litegraph/src/LGraphNode.ts index baf6a44190..c329518234 100644 --- a/src/lib/litegraph/src/LGraphNode.ts +++ b/src/lib/litegraph/src/LGraphNode.ts @@ -10,7 +10,11 @@ import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMuta import { LayoutSource } from '@/renderer/core/layout/types' import { adjustColor } from '@/utils/colorUtil' import type { ColorAdjustOptions } from '@/utils/colorUtil' -import { commonType, toClass } from '@/lib/litegraph/src/utils/type' +import { + commonType, + isNodeBindable, + toClass +} from '@/lib/litegraph/src/utils/type' import { SUBGRAPH_OUTPUT_ID } from '@/lib/litegraph/src/constants' import type { DragAndScale } from './DragAndScale' @@ -1957,6 +1961,14 @@ export class LGraphNode this.widgets ||= [] const widget = toConcreteWidget(custom_widget, this, false) ?? custom_widget this.widgets.push(widget) + + // Only register with store if node has a valid ID (is already in a graph). + // If the node isn't in a graph yet (id === -1), registration happens + // when the node is added via LGraph.add() -> node.onAdded. + if (this.id !== -1 && isNodeBindable(widget)) { + widget.setNodeId(this.id) + } + return widget } @@ -3499,7 +3511,7 @@ export class LGraphNode * Toggles advanced mode of the node, showing advanced widgets */ toggleAdvanced() { - if (!this.widgets?.some((w) => w.advanced)) return + if (!this.hasAdvancedWidgets()) return if (!this.graph) throw new NullGraphError() this.graph._version++ this.showAdvanced = !this.showAdvanced @@ -3877,6 +3889,21 @@ export class LGraphNode return !isHidden } + /** + * Returns all widgets that should participate in layout calculations. + * Filters out hidden widgets only (not collapsed/advanced). + */ + getLayoutWidgets(): IBaseWidget[] { + return this.widgets?.filter((w) => !w.hidden) ?? [] + } + + /** + * Returns `true` if the node has any advanced widgets. + */ + hasAdvancedWidgets(): boolean { + return this.widgets?.some((w) => w.advanced) ?? false + } + updateComputedDisabled() { if (!this.widgets) return for (const widget of this.widgets) @@ -4087,7 +4114,7 @@ export class LGraphNode w: IBaseWidget }[] = [] - const visibleWidgets = this.widgets.filter((w) => !w.hidden) + const visibleWidgets = this.getLayoutWidgets() for (const w of visibleWidgets) { if (w.computeSize) { diff --git a/src/lib/litegraph/src/LGraphNode.widgetOrder.test.ts b/src/lib/litegraph/src/LGraphNode.widgetOrder.test.ts index 21f7a7cd8b..4e7b8f44ef 100644 --- a/src/lib/litegraph/src/LGraphNode.widgetOrder.test.ts +++ b/src/lib/litegraph/src/LGraphNode.widgetOrder.test.ts @@ -1,3 +1,5 @@ +import { createTestingPinia } from '@pinia/testing' +import { setActivePinia } from 'pinia' import { beforeEach, describe, expect, it } from 'vitest' import { LGraphNode } from '@/lib/litegraph/src/litegraph' @@ -8,6 +10,7 @@ describe('LGraphNode widget ordering', () => { let node: LGraphNode beforeEach(() => { + setActivePinia(createTestingPinia({ stubActions: false })) node = new LGraphNode('TestNode') }) diff --git a/src/lib/litegraph/src/types/widgets.ts b/src/lib/litegraph/src/types/widgets.ts index 553bea06d1..25e86ff701 100644 --- a/src/lib/litegraph/src/types/widgets.ts +++ b/src/lib/litegraph/src/types/widgets.ts @@ -1,10 +1,19 @@ import type { Bounds } from '@/renderer/core/layout/types' import type { CanvasColour, Point, RequiredProps, Size } from '../interfaces' -import type { CanvasPointer, LGraphCanvas, LGraphNode } from '../litegraph' +import type { + CanvasPointer, + LGraphCanvas, + LGraphNode, + NodeId +} from '../litegraph' import type { CanvasPointerEvent } from './events' -export interface IWidgetOptions { +export interface NodeBindable { + setNodeId(nodeId: NodeId): void +} + +export interface IWidgetOptions { on?: string off?: string max?: number @@ -301,7 +310,7 @@ export type TWidgetValue = IWidget['value'] export interface IBaseWidget< TValue = boolean | number | string | object | undefined, TType extends string = string, - TOptions extends IWidgetOptions = IWidgetOptions + TOptions extends IWidgetOptions = IWidgetOptions > { [symbol: symbol]: boolean diff --git a/src/lib/litegraph/src/utils/type.ts b/src/lib/litegraph/src/utils/type.ts index 84891fb7f5..cc7b99f593 100644 --- a/src/lib/litegraph/src/utils/type.ts +++ b/src/lib/litegraph/src/utils/type.ts @@ -1,6 +1,7 @@ import { without } from 'es-toolkit' import type { IColorable, ISlotType } from '@/lib/litegraph/src/interfaces' +import type { NodeBindable } from '@/lib/litegraph/src/types/widgets' /** * Converts a plain object to a class instance if it is not already an instance of the class. @@ -29,6 +30,15 @@ export function isColorable(obj: unknown): obj is IColorable { ) } +export function isNodeBindable(widget: unknown): widget is NodeBindable { + return ( + typeof widget === 'object' && + widget !== null && + 'setNodeId' in widget && + typeof widget.setNodeId === 'function' + ) +} + export function commonType(...types: ISlotType[]): ISlotType | undefined { if (!isStrings(types)) return undefined diff --git a/src/lib/litegraph/src/widgets/BaseWidget.test.ts b/src/lib/litegraph/src/widgets/BaseWidget.test.ts new file mode 100644 index 0000000000..cc9a5ce497 --- /dev/null +++ b/src/lib/litegraph/src/widgets/BaseWidget.test.ts @@ -0,0 +1,193 @@ +import { createTestingPinia } from '@pinia/testing' +import { setActivePinia } from 'pinia' +import { beforeEach, describe, expect, it } from 'vitest' + +import { LGraphNode } from '@/lib/litegraph/src/litegraph' +import type { INumericWidget } from '@/lib/litegraph/src/types/widgets' +import { NumberWidget } from '@/lib/litegraph/src/widgets/NumberWidget' +import { useWidgetValueStore } from '@/stores/widgetValueStore' + +function createTestWidget( + node: LGraphNode, + overrides: Partial = {} +): NumberWidget { + return new NumberWidget( + { + type: 'number', + name: 'testWidget', + value: 42, + options: { min: 0, max: 100 }, + y: 0, + ...overrides + }, + node + ) +} + +describe('BaseWidget store integration', () => { + let node: LGraphNode + let store: ReturnType + + beforeEach(() => { + setActivePinia(createTestingPinia({ stubActions: false })) + store = useWidgetValueStore() + node = new LGraphNode('TestNode') + node.id = 1 + }) + + describe('metadata properties before registration', () => { + it('uses internal values when not registered', () => { + const widget = createTestWidget(node, { + label: 'My Label', + hidden: true, + disabled: true, + advanced: true, + promoted: true + }) + + expect(widget.label).toBe('My Label') + expect(widget.hidden).toBe(true) + expect(widget.disabled).toBe(true) + expect(widget.advanced).toBe(true) + expect(widget.promoted).toBe(true) + }) + + it('allows setting properties without store', () => { + const widget = createTestWidget(node) + + widget.label = 'New Label' + widget.hidden = true + widget.disabled = true + widget.advanced = true + widget.promoted = true + + expect(widget.label).toBe('New Label') + expect(widget.hidden).toBe(true) + expect(widget.disabled).toBe(true) + expect(widget.advanced).toBe(true) + expect(widget.promoted).toBe(true) + }) + }) + + describe('metadata properties after registration', () => { + it('reads from store when registered', () => { + const widget = createTestWidget(node, { + name: 'storeWidget', + label: 'Store Label', + hidden: true, + disabled: true, + advanced: true, + promoted: true + }) + widget.setNodeId(1) + + expect(widget.label).toBe('Store Label') + expect(widget.hidden).toBe(true) + expect(widget.disabled).toBe(true) + expect(widget.advanced).toBe(true) + expect(widget.promoted).toBe(true) + }) + + it('writes to store when registered', () => { + const widget = createTestWidget(node, { name: 'writeWidget' }) + widget.setNodeId(1) + + widget.label = 'Updated Label' + widget.hidden = true + widget.disabled = true + widget.advanced = true + widget.promoted = true + + const state = store.getWidget(1, 'writeWidget') + expect(state?.label).toBe('Updated Label') + expect(state?.disabled).toBe(true) + expect(state?.promoted).toBe(true) + + expect(widget.hidden).toBe(true) + expect(widget.advanced).toBe(true) + }) + + it('syncs value with store', () => { + const widget = createTestWidget(node, { name: 'valueWidget', value: 42 }) + widget.setNodeId(1) + + widget.value = 99 + expect(store.getWidget(1, 'valueWidget')?.value).toBe(99) + + const state = store.getWidget(1, 'valueWidget')! + state.value = 55 + expect(widget.value).toBe(55) + }) + }) + + describe('automatic registration via setNodeId', () => { + it('registers widget with all metadata', () => { + const widget = createTestWidget(node, { + name: 'autoRegWidget', + value: 100, + label: 'Auto Label', + hidden: true, + disabled: true, + advanced: true, + promoted: true + }) + widget.setNodeId(1) + + const state = store.getWidget(1, 'autoRegWidget') + expect(state).toBeDefined() + expect(state?.nodeId).toBe(1) + expect(state?.name).toBe('autoRegWidget') + expect(state?.type).toBe('number') + expect(state?.value).toBe(100) + expect(state?.label).toBe('Auto Label') + expect(state?.disabled).toBe(true) + expect(state?.promoted).toBe(true) + expect(state?.options).toEqual({ min: 0, max: 100 }) + + expect(widget.hidden).toBe(true) + expect(widget.advanced).toBe(true) + }) + + it('registers widget with default metadata values', () => { + const widget = createTestWidget(node, { name: 'defaultsWidget' }) + widget.setNodeId(1) + + const state = store.getWidget(1, 'defaultsWidget') + expect(state).toBeDefined() + expect(state?.disabled).toBe(false) + expect(state?.promoted).toBe(false) + expect(state?.label).toBeUndefined() + + expect(widget.hidden).toBeUndefined() + expect(widget.advanced).toBeUndefined() + }) + + it('registers widget value accessible via getWidget', () => { + const widget = createTestWidget(node, { name: 'valuesWidget', value: 77 }) + widget.setNodeId(1) + + expect(store.getWidget(1, 'valuesWidget')?.value).toBe(77) + }) + }) + + describe('fallback behavior', () => { + it('uses internal value before registration', () => { + const widget = createTestWidget(node, { + name: 'fallbackWidget', + label: 'Internal' + }) + // Widget not yet registered - should use internal value + expect(widget.label).toBe('Internal') + }) + + it('handles undefined values correctly', () => { + const widget = createTestWidget(node) + widget.setNodeId(1) + + widget.disabled = undefined + + const state = store.getWidget(1, 'testWidget') + expect(state?.disabled).toBe(false) + }) + }) +}) diff --git a/src/lib/litegraph/src/widgets/BaseWidget.ts b/src/lib/litegraph/src/widgets/BaseWidget.ts index 689dd205fd..15a7d92b44 100644 --- a/src/lib/litegraph/src/widgets/BaseWidget.ts +++ b/src/lib/litegraph/src/widgets/BaseWidget.ts @@ -2,6 +2,7 @@ import { t } from '@/i18n' import { drawTextInArea } from '@/lib/litegraph/src/draw' import { Rectangle } from '@/lib/litegraph/src/infrastructure/Rectangle' import type { Point } from '@/lib/litegraph/src/interfaces' +import type { NodeId } from '@/lib/litegraph/src/LGraphNode' import type { CanvasPointer, LGraphCanvas, @@ -10,7 +11,13 @@ import type { } from '@/lib/litegraph/src/litegraph' import { LiteGraph } from '@/lib/litegraph/src/litegraph' import type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events' -import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets' +import type { + IBaseWidget, + NodeBindable, + TWidgetType +} from '@/lib/litegraph/src/types/widgets' +import type { WidgetState } from '@/stores/widgetValueStore' +import { useWidgetValueStore } from '@/stores/widgetValueStore' export interface DrawWidgetOptions { /** The width of the node where this widget will be displayed. */ @@ -34,9 +41,9 @@ export interface WidgetEventOptions { canvas: LGraphCanvas } -export abstract class BaseWidget< - TWidget extends IBaseWidget = IBaseWidget -> implements IBaseWidget { +export abstract class BaseWidget + implements IBaseWidget, NodeBindable +{ /** From node edge to widget edge */ static margin = 15 /** From widget edge to tip of arrow button */ @@ -66,17 +73,39 @@ export abstract class BaseWidget< linkedWidgets?: IBaseWidget[] name: string options: TWidget['options'] - label?: string type: TWidget['type'] y: number = 0 last_y?: number width?: number - disabled?: boolean computedDisabled?: boolean + tooltip?: string + + private _state: Omit & + Partial> + + get label(): string | undefined { + return this._state.label + } + set label(value: string | undefined) { + this._state.label = value + } + hidden?: boolean advanced?: boolean - promoted?: boolean - tooltip?: string + + get disabled(): boolean | undefined { + return this._state.disabled + } + set disabled(value: boolean | undefined) { + this._state.disabled = value ?? false + } + + get promoted(): boolean | undefined { + return this._state.promoted + } + set promoted(value: boolean | undefined) { + this._state.promoted = value ?? false + } element?: HTMLElement callback?( value: TWidget['value'], @@ -97,13 +126,22 @@ export abstract class BaseWidget< canvas: LGraphCanvas ): boolean - private _value?: TWidget['value'] get value(): TWidget['value'] { - return this._value + return this._state.value as TWidget['value'] + } + set value(value: TWidget['value']) { + this._state.value = value } - set value(value: TWidget['value']) { - this._value = value + /** + * Associates this widget with a node ID and registers it in the WidgetValueStore. + * Once set, value reads/writes will be delegated to the store. + */ + setNodeId(nodeId: NodeId): void { + this._state = useWidgetValueStore().registerWidget({ + ...this._state, + nodeId + }) } constructor(widget: TWidget & { node: LGraphNode }) @@ -141,12 +179,26 @@ export abstract class BaseWidget< displayValue, // @ts-expect-error Prevent naming conflicts with custom nodes. labelBaseline, + label, + disabled, promoted, + value, linkedWidgets, ...safeValues } = widget Object.assign(this, safeValues) + + this._state = { + name: this.name, + type: this.type as TWidgetType, + value, + label, + disabled: disabled ?? false, + promoted: promoted ?? false, + serialize: this.serialize, + options: this.options + } } get outline_color() { diff --git a/src/platform/settings/composables/useLitegraphSettings.ts b/src/platform/settings/composables/useLitegraphSettings.ts index a056b7c58a..ffdb58c92b 100644 --- a/src/platform/settings/composables/useLitegraphSettings.ts +++ b/src/platform/settings/composables/useLitegraphSettings.ts @@ -2,7 +2,6 @@ import { watchEffect } from 'vue' import { CanvasPointer, - LGraph, LGraphNode, LiteGraph } from '@/lib/litegraph/src/litegraph' @@ -163,10 +162,4 @@ export const useLitegraphSettings = () => { 'Comfy.EnableWorkflowViewRestore' ) }) - - watchEffect(() => { - LGraph.deduplicateSubgraphIds = settingStore.get( - 'Comfy.Graph.DeduplicateSubgraphNodeIds' - ) - }) } diff --git a/src/platform/settings/constants/coreSettings.ts b/src/platform/settings/constants/coreSettings.ts index e75e6445c6..05c2758585 100644 --- a/src/platform/settings/constants/coreSettings.ts +++ b/src/platform/settings/constants/coreSettings.ts @@ -1211,7 +1211,8 @@ export const CORE_SETTINGS: SettingParams[] = [ tooltip: 'Automatically reassign duplicate node IDs in subgraphs when loading a workflow.', type: 'boolean', - defaultValue: false, + deprecated: true, + defaultValue: true, experimental: true, versionAdded: '1.40.0' } diff --git a/src/renderer/extensions/vueNodes/components/LGraphNodePreview.vue b/src/renderer/extensions/vueNodes/components/LGraphNodePreview.vue index af7ae07cf0..51bc75e8ec 100644 --- a/src/renderer/extensions/vueNodes/components/LGraphNodePreview.vue +++ b/src/renderer/extensions/vueNodes/components/LGraphNodePreview.vue @@ -57,6 +57,7 @@ const nodeData = computed(() => { const widgets = Object.entries(nodeDef.inputs || {}) .filter(([_, input]) => widgetStore.inputIsWidget(input)) .map(([name, input]) => ({ + nodeId: '-1', name, type: input.widgetType || input.type, value: diff --git a/src/renderer/extensions/vueNodes/components/NodeHeader.vue b/src/renderer/extensions/vueNodes/components/NodeHeader.vue index 5109eaf6de..4f9bd75602 100644 --- a/src/renderer/extensions/vueNodes/components/NodeHeader.vue +++ b/src/renderer/extensions/vueNodes/components/NodeHeader.vue @@ -108,6 +108,7 @@ import NodeBadge from '@/renderer/extensions/vueNodes/components/NodeBadge.vue' import { useNodeTooltips } from '@/renderer/extensions/vueNodes/composables/useNodeTooltips' import { applyLightThemeColor } from '@/renderer/extensions/vueNodes/utils/nodeStyleUtils' import { app } from '@/scripts/app' +import { useWidgetValueStore } from '@/stores/widgetValueStore' import { getLocatorIdFromNodeData, getNodeByLocatorId @@ -214,12 +215,14 @@ const nodeBadges = computed(() => { // For dynamic pricing, also track widget values and input connections if (isDynamicPricing.value) { - // Access only the widget values that affect pricing + // Access only the widget values that affect pricing (from widgetValueStore) const relevantNames = relevantPricingWidgets.value - if (relevantNames.length > 0) { - nodeData?.widgets?.forEach((w) => { - if (relevantNames.includes(w.name)) w.value - }) + const widgetStore = useWidgetValueStore() + if (relevantNames.length > 0 && nodeData?.id != null) { + for (const name of relevantNames) { + // Access value from store to create reactive dependency + void widgetStore.getWidget(nodeData.id, name)?.value + } } // Access input connections for regular inputs const inputNames = relevantInputNames.value diff --git a/src/renderer/extensions/vueNodes/components/NodeWidgets.test.ts b/src/renderer/extensions/vueNodes/components/NodeWidgets.test.ts index 78f6c370a6..2174004779 100644 --- a/src/renderer/extensions/vueNodes/components/NodeWidgets.test.ts +++ b/src/renderer/extensions/vueNodes/components/NodeWidgets.test.ts @@ -13,15 +13,12 @@ describe('NodeWidgets', () => { const createMockWidget = ( overrides: Partial = {} ): SafeWidgetData => ({ + nodeId: 'test_node', name: 'test_widget', type: 'combo', - value: 'test_value', - options: { - values: ['option1', 'option2'] - }, + options: undefined, callback: undefined, spec: undefined, - label: undefined, isDOMWidget: false, slotMetadata: undefined, ...overrides diff --git a/src/renderer/extensions/vueNodes/components/NodeWidgets.vue b/src/renderer/extensions/vueNodes/components/NodeWidgets.vue index 5f6eecc177..c18db79371 100644 --- a/src/renderer/extensions/vueNodes/components/NodeWidgets.vue +++ b/src/renderer/extensions/vueNodes/components/NodeWidgets.vue @@ -26,10 +26,7 @@ :key="`widget-${index}-${widget.name}`" >

@@ -94,6 +91,10 @@ import { shouldExpand, shouldRenderAsVue } from '@/renderer/extensions/vueNodes/widgets/registry/widgetRegistry' +import { + stripGraphPrefix, + useWidgetValueStore +} from '@/stores/widgetValueStore' import type { SimplifiedWidget, WidgetValue } from '@/types/simplifiedWidget' import { cn } from '@/utils/tailwindUtil' @@ -142,6 +143,7 @@ const showAdvanced = computed( const { getWidgetTooltip, createTooltipConfig } = useNodeTooltips( nodeType.value ) +const widgetValueStore = useWidgetValueStore() interface ProcessedWidget { name: string @@ -152,11 +154,15 @@ interface ProcessedWidget { updateHandler: (value: WidgetValue) => void tooltipConfig: TooltipOptions slotMetadata?: WidgetSlotMetadata + hidden: boolean + advanced: boolean + hasLayoutSize: boolean } const processedWidgets = computed((): ProcessedWidget[] => { if (!nodeData?.widgets) return [] + const nodeId = nodeData.id const { widgets } = nodeData const result: ProcessedWidget[] = [] @@ -167,33 +173,47 @@ const processedWidgets = computed((): ProcessedWidget[] => { getComponent(widget.type) || (widget.isDOMWidget ? WidgetDOM : WidgetLegacy) - const { slotMetadata, options } = widget + const { slotMetadata } = widget - // Core feature: Disable Vue widgets when their input slots are connected - // This prevents conflicting input sources - when a slot is linked to another - // node's output, the widget should be read-only to avoid data conflicts + // Get metadata from store (registered during BaseWidget.setNodeId) + const bareWidgetId = stripGraphPrefix(widget.nodeId ?? nodeId) + const widgetState = widgetValueStore.getWidget(bareWidgetId, widget.name) + + // Get value from store (falls back to undefined if not registered) + const value = widgetState?.value as WidgetValue + + // Build options from store state, with slot-linked override for disabled + const storeOptions = widgetState?.options ?? {} const widgetOptions = slotMetadata?.linked - ? { ...options, disabled: true } - : options + ? { ...storeOptions, disabled: true } + : storeOptions + + // Derive border style from store metadata + const borderStyle = + widgetState?.promoted && String(widgetState?.nodeId) === String(nodeId) + ? 'ring ring-component-node-widget-promoted' + : widget.options?.advanced + ? 'ring ring-component-node-widget-advanced' + : undefined const simplified: SimplifiedWidget = { name: widget.name, type: widget.type, - value: widget.value, - borderStyle: widget.borderStyle, + value, + borderStyle, callback: widget.callback, controlWidget: widget.controlWidget, - label: widget.label, + label: widgetState?.label, nodeType: widget.nodeType, options: widgetOptions, spec: widget.spec } - function updateHandler(value: WidgetValue) { - // Update the widget value directly - widget.value = value - - widget.callback?.(value) + function updateHandler(newValue: WidgetValue) { + // Update value in store + if (widgetState) widgetState.value = newValue + // Invoke LiteGraph callback wrapper (handles triggerDraw, etc.) + widget.callback?.(newValue) } const tooltipText = getWidgetTooltip(widget) @@ -204,10 +224,13 @@ const processedWidgets = computed((): ProcessedWidget[] => { type: widget.type, vueComponent, simplified, - value: widget.value, + value, updateHandler, tooltipConfig, - slotMetadata + slotMetadata, + hidden: widget.options?.hidden ?? false, + advanced: widget.options?.advanced ?? false, + hasLayoutSize: widget.hasLayoutSize ?? false }) } @@ -215,15 +238,9 @@ const processedWidgets = computed((): ProcessedWidget[] => { }) const gridTemplateRows = computed((): string => { - if (!nodeData?.widgets) return '' - const processedNames = new Set(toValue(processedWidgets).map((w) => w.name)) - return nodeData.widgets - .filter( - (w) => - processedNames.has(w.name) && - !w.options?.hidden && - (!w.options?.advanced || showAdvanced.value) - ) + // Use processedWidgets directly since it already has store-based hidden/advanced + return toValue(processedWidgets) + .filter((w) => !w.hidden && (!w.advanced || showAdvanced.value)) .map((w) => shouldExpand(w.type) || w.hasLayoutSize ? 'auto' : 'min-content' ) diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue index b0ed8ecc40..5705d60a7a 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue @@ -53,7 +53,8 @@ const props = defineProps() const modelValue = defineModel({ default(props: Props) { - return props.widget.options?.values?.[0] ?? '' + const values = props.widget.options?.values + return (Array.isArray(values) ? values[0] : undefined) ?? '' } }) diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue index 4c16594e60..3c6ca71cc7 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue @@ -59,7 +59,8 @@ provide( const modelValue = defineModel({ default(props: Props) { - return props.widget.options?.values?.[0] ?? '' + const values = props.widget.options?.values + return (Array.isArray(values) ? values[0] : undefined) ?? '' } }) diff --git a/src/renderer/extensions/vueNodes/widgets/composables/useMarkdownWidget.ts b/src/renderer/extensions/vueNodes/widgets/composables/useMarkdownWidget.ts index c54d13bdfe..75017de0d3 100644 --- a/src/renderer/extensions/vueNodes/widgets/composables/useMarkdownWidget.ts +++ b/src/renderer/extensions/vueNodes/widgets/composables/useMarkdownWidget.ts @@ -11,7 +11,10 @@ import type { LGraphNode } from '@/lib/litegraph/src/litegraph' import type { InputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2' import { app } from '@/scripts/app' import type { ComfyWidgetConstructorV2 } from '@/scripts/widgets' +import { useWidgetValueStore } from '@/stores/widgetValueStore' +// TODO: This widget manually syncs with widgetValueStore via getValue/setValue. +// Consolidate with useStringWidget into shared helpers (domWidgetHelpers.ts). function addMarkdownWidget( node: LGraphNode, name: string, @@ -36,6 +39,8 @@ function addMarkdownWidget( editable: false }) + const widgetStore = useWidgetValueStore() + const inputEl = editor.options.element as HTMLElement inputEl.classList.add('comfy-markdown') const textarea = document.createElement('textarea') @@ -43,16 +48,28 @@ function addMarkdownWidget( const widget = node.addDOMWidget(name, 'MARKDOWN', inputEl, { getValue(): string { - return textarea.value + return ( + (widgetStore.getWidget(node.id, name)?.value as string) ?? + textarea.value + ) }, setValue(v: string) { textarea.value = v editor.commands.setContent(v) + const widgetState = widgetStore.getWidget(node.id, name) + if (widgetState) widgetState.value = v } }) - widget.inputEl = inputEl + widget.element = inputEl widget.options.minNodeSize = [400, 200] + inputEl.addEventListener('input', (event) => { + if (event.target instanceof HTMLTextAreaElement) { + widget.value = event.target.value + } + widget.callback?.(widget.value) + }) + inputEl.addEventListener('dblclick', () => { inputEl.classList.add('editing') setTimeout(() => { diff --git a/src/renderer/extensions/vueNodes/widgets/composables/useStringWidget.ts b/src/renderer/extensions/vueNodes/widgets/composables/useStringWidget.ts index 1ace7e9e2a..e4f9f9be23 100644 --- a/src/renderer/extensions/vueNodes/widgets/composables/useStringWidget.ts +++ b/src/renderer/extensions/vueNodes/widgets/composables/useStringWidget.ts @@ -4,14 +4,18 @@ import { isStringInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2' import type { InputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2' import { app } from '@/scripts/app' import type { ComfyWidgetConstructorV2 } from '@/scripts/widgets' +import { useWidgetValueStore } from '@/stores/widgetValueStore' const TRACKPAD_DETECTION_THRESHOLD = 50 +// TODO: This widget manually syncs with widgetValueStore via getValue/setValue. +// Consolidate with useMarkdownWidget into shared helpers (domWidgetHelpers.ts). function addMultilineWidget( node: LGraphNode, name: string, opts: { defaultVal: string; placeholder?: string } ) { + const widgetStore = useWidgetValueStore() const inputEl = document.createElement('textarea') inputEl.className = 'comfy-multiline-input' inputEl.value = opts.defaultVal @@ -20,17 +24,24 @@ function addMultilineWidget( const widget = node.addDOMWidget(name, 'customtext', inputEl, { getValue(): string { - return inputEl.value + const widgetState = widgetStore.getWidget(node.id, name) + + return (widgetState?.value as string) ?? inputEl.value }, setValue(v: string) { inputEl.value = v + const widgetState = widgetStore.getWidget(node.id, name) + if (widgetState) widgetState.value = v } }) - widget.inputEl = inputEl + widget.element = inputEl widget.options.minNodeSize = [400, 200] - inputEl.addEventListener('input', () => { + inputEl.addEventListener('input', (event) => { + if (event.target instanceof HTMLTextAreaElement) { + widget.value = event.target.value + } widget.callback?.(widget.value) }) diff --git a/src/renderer/extensions/vueNodes/widgets/composables/useWidgetRenderer.test.ts b/src/renderer/extensions/vueNodes/widgets/composables/useWidgetRenderer.test.ts index 3fc529a059..3e679a0cc6 100644 --- a/src/renderer/extensions/vueNodes/widgets/composables/useWidgetRenderer.test.ts +++ b/src/renderer/extensions/vueNodes/widgets/composables/useWidgetRenderer.test.ts @@ -123,7 +123,7 @@ describe('widgetRegistry', () => { }) it('should return false for widgets without a type', () => { - const widget = { options: {} } + const widget = {} expect(shouldRenderAsVue(widget)).toBe(false) }) @@ -136,7 +136,7 @@ describe('widgetRegistry', () => { it('should respect options while checking type', () => { const widget: Partial = { type: 'text', - options: { precision: 5 } + options: { canvasOnly: false } } expect(shouldRenderAsVue(widget)).toBe(true) }) diff --git a/src/scripts/domWidget.ts b/src/scripts/domWidget.ts index a1b57496dc..4578696dcc 100644 --- a/src/scripts/domWidget.ts +++ b/src/scripts/domWidget.ts @@ -153,7 +153,7 @@ abstract class BaseDOMWidgetImpl } isVisible(): boolean { - return !['hidden'].includes(this.type) && this.node.isWidgetVisible(this) + return !this.hidden && this.node.isWidgetVisible(this) } override draw( diff --git a/src/scripts/metadata/png.ts b/src/scripts/metadata/png.ts index 526d9b2d75..2d47effcb2 100644 --- a/src/scripts/metadata/png.ts +++ b/src/scripts/metadata/png.ts @@ -34,7 +34,6 @@ async function decompressZlib( return result } -/** @knipIgnoreUnusedButUsedByCustomNodes */ export async function getFromPngBuffer( buffer: ArrayBuffer ): Promise> { diff --git a/src/stores/widgetValueStore.test.ts b/src/stores/widgetValueStore.test.ts new file mode 100644 index 0000000000..d102969ebc --- /dev/null +++ b/src/stores/widgetValueStore.test.ts @@ -0,0 +1,155 @@ +import { createTestingPinia } from '@pinia/testing' +import { setActivePinia } from 'pinia' +import { beforeEach, describe, expect, it } from 'vitest' + +import type { WidgetState } from './widgetValueStore' +import { useWidgetValueStore } from './widgetValueStore' + +function widget( + nodeId: string, + name: string, + type: string, + value: T, + extra: Partial< + Omit, 'nodeId' | 'name' | 'type' | 'value'> + > = {} +): WidgetState { + return { nodeId, name, type, value, options: {}, ...extra } +} + +describe('useWidgetValueStore', () => { + beforeEach(() => { + setActivePinia(createTestingPinia({ stubActions: false })) + }) + + describe('widgetState.value access', () => { + it('getWidget returns undefined for unregistered widget', () => { + const store = useWidgetValueStore() + expect(store.getWidget('missing', 'widget')).toBeUndefined() + }) + + it('widgetState.value can be read and written directly', () => { + const store = useWidgetValueStore() + const state = store.registerWidget( + widget('node-1', 'seed', 'number', 100) + ) + expect(state.value).toBe(100) + + state.value = 200 + expect(store.getWidget('node-1', 'seed')?.value).toBe(200) + }) + + it('stores different value types', () => { + const store = useWidgetValueStore() + store.registerWidget(widget('node-1', 'text', 'string', 'hello')) + store.registerWidget(widget('node-1', 'number', 'number', 42)) + store.registerWidget(widget('node-1', 'boolean', 'toggle', true)) + store.registerWidget(widget('node-1', 'array', 'combo', [1, 2, 3])) + + expect(store.getWidget('node-1', 'text')?.value).toBe('hello') + expect(store.getWidget('node-1', 'number')?.value).toBe(42) + expect(store.getWidget('node-1', 'boolean')?.value).toBe(true) + expect(store.getWidget('node-1', 'array')?.value).toEqual([1, 2, 3]) + }) + }) + + describe('widget registration', () => { + it('registers a widget with minimal properties', () => { + const store = useWidgetValueStore() + const state = store.registerWidget( + widget('node-1', 'seed', 'number', 12345) + ) + + expect(state.nodeId).toBe('node-1') + expect(state.name).toBe('seed') + expect(state.type).toBe('number') + expect(state.value).toBe(12345) + expect(state.disabled).toBeUndefined() + expect(state.promoted).toBeUndefined() + expect(state.serialize).toBeUndefined() + expect(state.options).toEqual({}) + }) + + it('registers a widget with all properties', () => { + const store = useWidgetValueStore() + const state = store.registerWidget( + widget('node-1', 'prompt', 'string', 'test', { + label: 'Prompt Text', + disabled: true, + promoted: true, + serialize: false, + options: { multiline: true } + }) + ) + + expect(state.label).toBe('Prompt Text') + expect(state.disabled).toBe(true) + expect(state.promoted).toBe(true) + expect(state.serialize).toBe(false) + expect(state.options).toEqual({ multiline: true }) + }) + }) + + describe('widget getters', () => { + it('getWidget returns widget state', () => { + const store = useWidgetValueStore() + store.registerWidget(widget('node-1', 'seed', 'number', 100)) + + const state = store.getWidget('node-1', 'seed') + expect(state).toBeDefined() + expect(state?.name).toBe('seed') + expect(state?.value).toBe(100) + }) + + it('getWidget returns undefined for missing widget', () => { + const store = useWidgetValueStore() + expect(store.getWidget('missing', 'widget')).toBeUndefined() + }) + + it('getNodeWidgets returns all widgets for a node', () => { + const store = useWidgetValueStore() + store.registerWidget(widget('node-1', 'seed', 'number', 1)) + store.registerWidget(widget('node-1', 'steps', 'number', 20)) + store.registerWidget(widget('node-2', 'cfg', 'number', 7)) + + const widgets = store.getNodeWidgets('node-1') + expect(widgets).toHaveLength(2) + expect(widgets.map((w) => w.name).sort()).toEqual(['seed', 'steps']) + }) + }) + + describe('direct property mutation', () => { + it('disabled can be set directly via getWidget', () => { + const store = useWidgetValueStore() + const state = store.registerWidget( + widget('node-1', 'seed', 'number', 100) + ) + + state.disabled = true + expect(store.getWidget('node-1', 'seed')?.disabled).toBe(true) + }) + + it('promoted can be set directly via getWidget', () => { + const store = useWidgetValueStore() + const state = store.registerWidget( + widget('node-1', 'seed', 'number', 100) + ) + + state.promoted = true + expect(store.getWidget('node-1', 'seed')?.promoted).toBe(true) + }) + + it('label can be set directly via getWidget', () => { + const store = useWidgetValueStore() + const state = store.registerWidget( + widget('node-1', 'seed', 'number', 100) + ) + + state.label = 'Random Seed' + expect(store.getWidget('node-1', 'seed')?.label).toBe('Random Seed') + + state.label = undefined + expect(store.getWidget('node-1', 'seed')?.label).toBeUndefined() + }) + }) +}) diff --git a/src/stores/widgetValueStore.ts b/src/stores/widgetValueStore.ts new file mode 100644 index 0000000000..87844db9d9 --- /dev/null +++ b/src/stores/widgetValueStore.ts @@ -0,0 +1,77 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' + +import type { NodeId } from '@/lib/litegraph/src/LGraphNode' +import type { + IBaseWidget, + IWidgetOptions +} from '@/lib/litegraph/src/types/widgets' + +/** + * Widget state is keyed by `nodeId:widgetName` without graph context. + * This is intentional: nodes viewed at different subgraph depths share + * the same widget state, enabling synchronized values across the hierarchy. + */ +type WidgetKey = `${NodeId}:${string}` + +/** + * Strips graph/subgraph prefixes from a scoped node ID to get the bare node ID. + * e.g., "graph1:subgraph2:42" → "42" + */ +export function stripGraphPrefix(scopedId: NodeId | string): NodeId { + return String(scopedId).replace(/^(.*:)+/, '') as NodeId +} + +export interface WidgetState< + TValue = unknown, + TType extends string = string, + TOptions extends IWidgetOptions = IWidgetOptions +> extends Pick< + IBaseWidget, + | 'name' + | 'type' + | 'value' + | 'options' + | 'label' + | 'serialize' + | 'disabled' + | 'promoted' +> { + nodeId: NodeId +} + +export const useWidgetValueStore = defineStore('widgetValue', () => { + const widgetStates = ref(new Map()) + + function makeKey(nodeId: NodeId, widgetName: string): WidgetKey { + return `${nodeId}:${widgetName}` + } + + function registerWidget( + state: WidgetState + ): WidgetState { + const key = makeKey(state.nodeId, state.name) + widgetStates.value.set(key, state) + return widgetStates.value.get(key) as WidgetState + } + + function getNodeWidgets(nodeId: NodeId): WidgetState[] { + const prefix = `${nodeId}:` + return [...widgetStates.value] + .filter(([key]) => key.startsWith(prefix)) + .map(([, state]) => state) + } + + function getWidget( + nodeId: NodeId, + widgetName: string + ): WidgetState | undefined { + return widgetStates.value.get(makeKey(nodeId, widgetName)) + } + + return { + registerWidget, + getWidget, + getNodeWidgets + } +})