Compare commits

...

3 Commits

Author SHA1 Message Date
Glary-Bot
812fc37ccc fix: filter magic widgets from TabSubgraphInputs panel
Manual verification revealed the bug only manifests on subgraph nodes
that promote canvas-image-preview widgets, because TabSubgraphInputs
builds its widget lists directly from promotion entries rather than
going through computedSectionDataList. Apply isPanelHiddenWidget to
both the promoted-widgets list and the advanced-inputs list.

Update the e2e test to use subgraphs/subgraph-with-preview-node, which
is the actual bug surface.
2026-05-12 05:10:13 +00:00
Glary-Bot
b0e3890b6d refactor: extract isPanelHiddenWidget shared predicate
Apply the $$-prefix filter to both normal and advanced widget sections
by extracting a shared isPanelHiddenWidget predicate. Strengthen the
e2e test with an explicit assertion that '$$canvas-image-preview'
text is absent.
2026-05-12 04:54:28 +00:00
Glary-Bot
dbef649ae5 fix: hide magic-prefixed widgets from right side panel (FE-563)
The internal `$$canvas-image-preview` pseudo-widget was leaking into the
right side panel. Filter widgets whose name starts with `$$` from the
parameters section as a temporary fix until image-preview rendering in the
panel is properly designed.

The new e2e test is intentionally brittle so it fails as soon as the
preview is given a real, user-facing name in a future refactor, forcing
the temporary filter (and the test) to be cleaned up at the right time.
2026-05-06 05:41:21 +00:00
4 changed files with 62 additions and 13 deletions

View File

@@ -0,0 +1,43 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { PropertiesPanelHelper } from '@e2e/tests/propertiesPanel/PropertiesPanelHelper'
/**
* FE-563: the `$$canvas-image-preview` pseudo-widget is not user-facing and
* must not appear in the right side panel. Filtered by `$$` prefix until
* image-preview rendering in the panel is properly designed.
*
* Intentionally brittle: when the preview is given a real, user-facing name
* in a future refactor, this test is expected to FAIL so the temporary
* filter (and this test) get cleaned up at the right time.
*/
test.describe('Properties panel - canvas image preview widget', () => {
let panel: PropertiesPanelHelper
test.beforeEach(async ({ comfyPage }) => {
panel = new PropertiesPanelHelper(comfyPage.page)
})
test('does not render the $$canvas-image-preview promoted widget on a subgraph node', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow(
'subgraphs/subgraph-with-preview-node'
)
await comfyPage.nodeOps.selectNodes(['New Subgraph'])
await comfyPage.actionbar.propertiesButton.click()
await expect(panel.panelTitle).toContainText('New Subgraph')
const widgetItems = panel.contentArea.locator('.widget-item')
await expect(
widgetItems.filter({ hasText: 'filename_prefix' })
).toHaveCount(1)
await expect(
panel.contentArea.getByText('$$canvas-image-preview')
).toHaveCount(0)
await expect(widgetItems).toHaveCount(1)
})
})

View File

@@ -9,7 +9,11 @@ import FormSearchInput from '@/renderer/extensions/vueNodes/widgets/components/f
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
import { computedSectionDataList, searchWidgetsAndNodes } from '../shared'
import {
computedSectionDataList,
isPanelHiddenWidget,
searchWidgetsAndNodes
} from '../shared'
import type { NodeWidgetsListList } from '../shared'
import SectionWidgets from './SectionWidgets.vue'
@@ -36,10 +40,7 @@ const advancedWidgetsSectionDataList = computed((): NodeWidgetsListList => {
.map((node) => {
const { widgets = [] } = node
const advancedWidgets = widgets
.filter(
(w) =>
!(w.options?.canvasOnly || w.options?.hidden) && w.options?.advanced
)
.filter((w) => !isPanelHiddenWidget(w) && w.options?.advanced)
.map((widget) => ({ node, widget }))
return { widgets: advancedWidgets, node }
})

View File

@@ -23,7 +23,7 @@ import { DraggableList } from '@/scripts/ui/draggableList'
import { usePromotionStore } from '@/stores/promotionStore'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
import { searchWidgets } from '../shared'
import { isPanelHiddenWidget, searchWidgets } from '../shared'
import type { NodeWidgetsList } from '../shared'
import SectionWidgets from './SectionWidgets.vue'
@@ -107,7 +107,7 @@ const widgetsList = computed((): NodeWidgetsList => {
}
return w.name === sourceWidgetName
})
if (widget) {
if (widget && !isPanelHiddenWidget(widget)) {
result.push({ node, widget })
}
}
@@ -120,7 +120,7 @@ const advancedInputsWidgets = computed((): NodeWidgetsList => {
const allInteriorWidgets = interiorNodes.flatMap((interiorNode) => {
const { widgets = [] } = interiorNode
return widgets
.filter((w) => !w.computedDisabled)
.filter((w) => !w.computedDisabled && !isPanelHiddenWidget(w))
.map((widget) => ({ node: interiorNode, widget }))
})

View File

@@ -250,6 +250,14 @@ function repeatItems<T>(items: T[]): T[] {
return result
}
export function isPanelHiddenWidget(widget: IBaseWidget): boolean {
return Boolean(
widget.options?.canvasOnly ||
widget.options?.hidden ||
widget.name.startsWith('$$')
)
}
export function computedSectionDataList(nodes: MaybeRefOrGetter<LGraphNode[]>) {
const settingStore = useSettingStore()
@@ -263,11 +271,8 @@ export function computedSectionDataList(nodes: MaybeRefOrGetter<LGraphNode[]>) {
const shownWidgets = widgets
.filter(
(w) =>
!(
w.options?.canvasOnly ||
w.options?.hidden ||
(w.options?.advanced && !includesAdvanced.value)
)
!isPanelHiddenWidget(w) &&
!(w.options?.advanced && !includesAdvanced.value)
)
.map((widget) => ({ node, widget }))
return { widgets: shownWidgets, node }