Compare commits

...

1 Commits

Author SHA1 Message Date
Rizumu Ayaka
9c07bb459c fix: keep top-level hidden widgets hidden in Nodes 2.0 (FE-630)
SAM3 collector nodes hide widgets via the top-level widget.hidden, matching
litegraph's LGraphNode.isWidgetVisible. extractWidgetDisplayOptions only read
widget.options.hidden, so those widgets leaked into Vue Nodes 2.0 while staying
hidden in litegraph. Fall back to widget.hidden, mirroring the existing
advanced handling.
2026-06-08 16:54:56 +09:00
2 changed files with 59 additions and 5 deletions

View File

@@ -776,3 +776,49 @@ describe('reconcileNodeErrorFlags (via lastNodeErrors watcher)', () => {
expect(subgraphNode.has_errors).toBe(true)
})
})
describe('Widget display options reflect litegraph visibility flags', () => {
beforeEach(() => {
setActivePinia(createTestingPinia({ stubActions: false }))
})
function createNodeWithWidget() {
const graph = new LGraph()
const node = new LGraphNode('test')
node.addWidget('number', 'secret', 1, () => undefined, {})
graph.add(node)
return { graph, node }
}
function getWidgetData(graph: LGraph, node: LGraphNode) {
const { vueNodeData } = useGraphNodeManager(graph)
return vueNodeData
.get(String(node.id))
?.widgets?.find((w) => w.name === 'secret')
}
// FE-630: SAM3 collector nodes hide widgets via the top-level
// `widget.hidden`, matching litegraph's isWidgetVisible. Vue Nodes 2.0 must
// honor it, not only `widget.options.hidden`.
it('marks a widget hidden when only the top-level hidden flag is set', () => {
const { graph, node } = createNodeWithWidget()
node.widgets![0].hidden = true
expect(getWidgetData(graph, node)?.options?.hidden).toBe(true)
})
it('marks a widget advanced when only the top-level advanced flag is set', () => {
const { graph, node } = createNodeWithWidget()
node.widgets![0].advanced = true
expect(getWidgetData(graph, node)?.options?.advanced).toBe(true)
})
it('keeps a plain widget visible', () => {
const { graph, node } = createNodeWithWidget()
const data = getWidgetData(graph, node)
expect(data?.options?.hidden).toBeFalsy()
expect(data?.options?.advanced).toBeFalsy()
})
})

View File

@@ -218,16 +218,24 @@ function safeWidgetMapper(
node: LGraphNode,
slotMetadata: Map<string, WidgetSlotMetadata>
): (widget: IBaseWidget) => SafeWidgetData {
/**
* Mirrors litegraph's visibility check (LGraphNode.isWidgetVisible): both
* `hidden` and `advanced` may live on the widget itself, not just its
* `options`. Custom nodes (e.g. SAM3 collectors) commonly hide widgets via
* the top-level `widget.hidden`, so fall back to it when reading options.
*/
function extractWidgetDisplayOptions(
widget: IBaseWidget
): SafeWidgetData['options'] {
if (!widget.options) return undefined
const advanced = widget.options?.advanced ?? widget.advanced
const hidden = widget.options?.hidden ?? widget.hidden
if (!widget.options && !advanced && !hidden) return undefined
return {
canvasOnly: widget.options.canvasOnly,
advanced: widget.options?.advanced ?? widget.advanced,
hidden: widget.options.hidden,
read_only: widget.options.read_only
canvasOnly: widget.options?.canvasOnly,
advanced,
hidden,
read_only: widget.options?.read_only
}
}