From 54c865e82f970495a587ec83b0b4769725809661 Mon Sep 17 00:00:00 2001 From: bymyself Date: Fri, 12 Dec 2025 01:00:03 -0800 Subject: [PATCH] assign node images for backwards compat --- .../vueNodes/components/ImagePreview.vue | 21 +++++++--- .../vueNodes/components/ImagePreview.test.ts | 39 +++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/renderer/extensions/vueNodes/components/ImagePreview.vue b/src/renderer/extensions/vueNodes/components/ImagePreview.vue index 381941311..6acbd5ace 100644 --- a/src/renderer/extensions/vueNodes/components/ImagePreview.vue +++ b/src/renderer/extensions/vueNodes/components/ImagePreview.vue @@ -197,6 +197,17 @@ watch( { deep: true, immediate: true } ) +/** + * Sync node.imgs for backwards compatibility with legacy systems (e.g., Copy Image). + */ +const syncNodeImgs = () => { + if (!props.nodeId || !currentImageEl.value) return + const node = app.rootGraph?.getNodeById(props.nodeId) + if (!node) return + node.imgs = [currentImageEl.value] + node.imageIndex = currentIndex.value +} + // Event handlers const handleImageLoad = (event: Event) => { if (!event.target || !(event.target instanceof HTMLImageElement)) return @@ -207,6 +218,7 @@ const handleImageLoad = (event: Event) => { if (img.naturalWidth && img.naturalHeight) { actualDimensions.value = `${img.naturalWidth} x ${img.naturalHeight}` } + syncNodeImgs() } const handleImageError = () => { @@ -216,14 +228,11 @@ const handleImageError = () => { actualDimensions.value = null } -// In vueNodes mode, we need to set them manually before opening the mask editor. const setupNodeForMaskEditor = () => { - if (!props.nodeId || !currentImageEl.value) return + syncNodeImgs() + if (!props.nodeId) return const node = app.rootGraph?.getNodeById(props.nodeId) - if (!node) return - node.imageIndex = currentIndex.value - node.imgs = [currentImageEl.value] - app.canvas?.select(node) + if (node) app.canvas?.select(node) } const handleEditMask = () => { diff --git a/tests-ui/tests/renderer/extensions/vueNodes/components/ImagePreview.test.ts b/tests-ui/tests/renderer/extensions/vueNodes/components/ImagePreview.test.ts index d38ea0b8e..6cb4b1058 100644 --- a/tests-ui/tests/renderer/extensions/vueNodes/components/ImagePreview.test.ts +++ b/tests-ui/tests/renderer/extensions/vueNodes/components/ImagePreview.test.ts @@ -12,6 +12,22 @@ vi.mock('@/base/common/downloadUtil', () => ({ downloadFile: vi.fn() })) +// Mock app for node.imgs sync tests +const mockNode: { + imgs?: HTMLImageElement[] | undefined + imageIndex?: number | null +} = {} +vi.mock('@/scripts/app', () => ({ + app: { + rootGraph: { + getNodeById: vi.fn(() => mockNode) + }, + canvas: { + select: vi.fn() + } + } +})) + const i18n = createI18n({ legacy: false, locale: 'en', @@ -297,4 +313,27 @@ describe('ImagePreview', () => { expect(imgElement.exists()).toBe(true) expect(imgElement.attributes('alt')).toBe('Node output 2') }) + + it('syncs node.imgs on image load for legacy compatibility', async () => { + // Reset mock node state + delete mockNode.imgs + delete mockNode.imageIndex + + const wrapper = mountImagePreview({ + imageUrls: [defaultProps.imageUrls[0]], + nodeId: 'test-node-123' + }) + + const img = wrapper.find('img') + expect(img.exists()).toBe(true) + + // Simulate image load event + await img.trigger('load') + await nextTick() + + // Verify node.imgs was synced + expect(mockNode.imgs).toBeDefined() + expect(mockNode.imgs).toHaveLength(1) + expect(mockNode.imageIndex).toBe(0) + }) })