diff --git a/browser_tests/tests/widget.spec.ts b/browser_tests/tests/widget.spec.ts index 0e6045bc2..1c3e809eb 100644 --- a/browser_tests/tests/widget.spec.ts +++ b/browser_tests/tests/widget.spec.ts @@ -192,3 +192,19 @@ test.describe('Load audio widget', () => { await expect(comfyPage.canvas).toHaveScreenshot('load_audio_widget.png') }) }) + +test.describe('Unserialized widgets', () => { + test('Unserialized widgets values do not mark graph as modified', async ({ + comfyPage + }) => { + // Add workflow w/ LoadImage node, which contains file upload and image preview widgets (not serialized) + await comfyPage.loadWorkflow('widgets/load_image_widget') + + // Move mouse and click to trigger the `graphEqual` check in `changeTracker.ts` + await comfyPage.page.mouse.move(10, 10) + await comfyPage.page.mouse.click(10, 10) + + // Expect the graph to not be modified + expect(await comfyPage.isCurrentWorkflowModified()).toBe(false) + }) +}) diff --git a/src/composables/node/useNodeAnimatedImage.ts b/src/composables/node/useNodeAnimatedImage.ts index 6586ac3a5..0a4c6fee9 100644 --- a/src/composables/node/useNodeAnimatedImage.ts +++ b/src/composables/node/useNodeAnimatedImage.ts @@ -39,6 +39,7 @@ export function useNodeAnimatedImage() { }) as IWidget & { options: { host: ReturnType } } + widget.serialize = false widget.serializeValue = () => undefined widget.options.host.updateImages(node.imgs) } diff --git a/src/composables/node/useNodeImage.ts b/src/composables/node/useNodeImage.ts index 43abbd1f2..80fc52f78 100644 --- a/src/composables/node/useNodeImage.ts +++ b/src/composables/node/useNodeImage.ts @@ -155,9 +155,9 @@ export const useNodeVideo = (node: LGraphNode) => { const hasWidget = node.widgets?.some((w) => w.name === VIDEO_WIDGET_NAME) if (!hasWidget) { const widget = node.addDOMWidget(VIDEO_WIDGET_NAME, 'video', container, { - hideOnZoom: false, - serialize: false + hideOnZoom: false }) + widget.serialize = false widget.computeLayoutSize = () => ({ minHeight, minWidth diff --git a/src/composables/widgets/useImagePreviewWidget.ts b/src/composables/widgets/useImagePreviewWidget.ts index eec7e678e..304bd7b34 100644 --- a/src/composables/widgets/useImagePreviewWidget.ts +++ b/src/composables/widgets/useImagePreviewWidget.ts @@ -238,9 +238,11 @@ class ImagePreviewWidget implements ICustomWidget { readonly type: 'custom' readonly name: string readonly options: IWidgetOptions - // Dummy value to satisfy type requirements + /** Dummy value to satisfy type requirements. */ value: string y: number = 0 + /** Don't serialize the widget value. */ + serialize: boolean = false constructor(name: string, options: IWidgetOptions) { this.type = 'custom' diff --git a/src/extensions/core/uploadAudio.ts b/src/extensions/core/uploadAudio.ts index fb0bc15e6..11fc34c26 100644 --- a/src/extensions/core/uploadAudio.ts +++ b/src/extensions/core/uploadAudio.ts @@ -108,9 +108,8 @@ app.registerExtension({ audio.setAttribute('name', 'media') const audioUIWidget: DOMWidget = - node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio, { - serialize: false - }) + node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio) + audioUIWidget.serialize = false const isOutputNode = node.constructor.nodeData.output_node if (isOutputNode) { diff --git a/src/types/litegraph-augmentation.d.ts b/src/types/litegraph-augmentation.d.ts index c35f75bca..9f6a9e7d4 100644 --- a/src/types/litegraph-augmentation.d.ts +++ b/src/types/litegraph-augmentation.d.ts @@ -16,6 +16,9 @@ declare module '@comfyorg/litegraph/dist/types/widgets' { * Controls whether the widget's value is included in the API workflow/prompt. * - If false, the value will be excluded from the API workflow but still serialized as part of the graph state * - If true or undefined, the value will be included in both the API workflow and graph state + * @default true + * @use {@link IBaseWidget.serialize} if you don't want the widget value to be included in both + * the API workflow and graph state. */ serialize?: boolean /**