diff --git a/src/renderer/extensions/vueNodes/components/ImagePreview.vue b/src/renderer/extensions/vueNodes/components/ImagePreview.vue
index aa7c27100..52f7c8a0b 100644
--- a/src/renderer/extensions/vueNodes/components/ImagePreview.vue
+++ b/src/renderer/extensions/vueNodes/components/ImagePreview.vue
@@ -32,6 +32,7 @@
(null)
const imageError = ref(false)
const isLoading = ref(false)
+const currentImageEl = ref()
+
// Computed values
const currentImageUrl = computed(() => props.imageUrls[currentIndex.value])
const hasMultipleImages = computed(() => props.imageUrls.length > 1)
@@ -182,7 +186,18 @@ 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
+ const node = app.rootGraph?.getNodeById(props.nodeId)
+ if (!node) return
+ node.imageIndex = currentIndex.value
+ node.imgs = [currentImageEl.value]
+ app.canvas?.select(node)
+}
+
const handleEditMask = () => {
+ setupNodeForMaskEditor()
void commandStore.execute('Comfy.MaskEditor.OpenMaskEditor')
}
diff --git a/src/scripts/app.ts b/src/scripts/app.ts
index c962fd1eb..043c76862 100644
--- a/src/scripts/app.ts
+++ b/src/scripts/app.ts
@@ -380,11 +380,15 @@ export class ComfyApp {
const paintedIndex = selectedIndex + 1
const combinedIndex = selectedIndex + 2
+ // for vueNodes mode
+ const images =
+ node.images ?? useNodeOutputStore().getNodeOutputs(node)?.images
+
ComfyApp.clipspace = {
widgets: widgets,
imgs: imgs,
original_imgs: orig_imgs,
- images: node.images,
+ images: images,
selectedIndex: selectedIndex,
img_paste_mode: 'selected', // reset to default im_paste_mode state on copy action
paintedIndex: paintedIndex,
@@ -411,7 +415,8 @@ export class ComfyApp {
ComfyApp.clipspace.imgs[ComfyApp.clipspace.combinedIndex].src
}
if (ComfyApp.clipspace.imgs && node.imgs) {
- if (node.images && ComfyApp.clipspace.images) {
+ // Update node.images even if it's initially undefined (vueNodes mode)
+ if (ComfyApp.clipspace.images) {
if (ComfyApp.clipspace['img_paste_mode'] == 'selected') {
node.images = [
ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']]
@@ -513,6 +518,8 @@ export class ComfyApp {
}
app.graph.setDirtyCanvas(true)
+
+ useNodeOutputStore().updateNodeImages(node)
}
}
diff --git a/src/stores/imagePreviewStore.ts b/src/stores/imagePreviewStore.ts
index 848eb0ae7..300c532c9 100644
--- a/src/stores/imagePreviewStore.ts
+++ b/src/stores/imagePreviewStore.ts
@@ -331,6 +331,26 @@ export const useNodeOutputStore = defineStore('nodeOutput', () => {
nodeOutputs.value = outputs
}
+ function updateNodeImages(node: LGraphNode) {
+ if (!node.images?.length) return
+
+ const nodeLocatorId = nodeIdToNodeLocatorId(node.id)
+
+ if (nodeLocatorId) {
+ const existingOutputs = app.nodeOutputs[nodeLocatorId]
+
+ if (existingOutputs) {
+ const updatedOutputs = {
+ ...existingOutputs,
+ images: node.images
+ }
+
+ app.nodeOutputs[nodeLocatorId] = updatedOutputs
+ nodeOutputs.value[nodeLocatorId] = updatedOutputs
+ }
+ }
+ }
+
function resetAllOutputsAndPreviews() {
app.nodeOutputs = {}
nodeOutputs.value = {}
@@ -349,6 +369,7 @@ export const useNodeOutputStore = defineStore('nodeOutput', () => {
setNodeOutputsByExecutionId,
setNodePreviewsByExecutionId,
setNodePreviewsByNodeId,
+ updateNodeImages,
// Cleanup
revokePreviewsByExecutionId,
diff --git a/tests-ui/tests/renderer/extensions/vueNodes/components/ImagePreview.spec.ts b/tests-ui/tests/renderer/extensions/vueNodes/components/ImagePreview.spec.ts
index ccf61ebcf..5b9d658df 100644
--- a/tests-ui/tests/renderer/extensions/vueNodes/components/ImagePreview.spec.ts
+++ b/tests-ui/tests/renderer/extensions/vueNodes/components/ImagePreview.spec.ts
@@ -203,9 +203,8 @@ describe('ImagePreview', () => {
await navigationDots[1].trigger('click')
await nextTick()
- // After clicking, component shows loading state (Skeleton), not img
+ // After clicking, component shows loading state (Skeleton)
expect(wrapper.find('skeleton-stub').exists()).toBe(true)
- expect(wrapper.find('img').exists()).toBe(false)
// Simulate image load event to clear loading state
const component = wrapper.vm as any