From ed4627ad590bb6962959096f6ccba7dd303de7f6 Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Fri, 5 Sep 2025 11:58:46 -0700 Subject: [PATCH] Fix lifecycle in watch --- src/components/graph/GraphCanvas.vue | 31 ++++++++++--------- .../core/layout/sync/useLayoutSync.ts | 5 +++ .../core/layout/sync/useLinkLayoutSync.ts | 2 ++ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index ab9776771..ff7cd66c3 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -181,10 +181,12 @@ const isVueNodesEnabled = computed(() => shouldRenderVueNodes.value) let nodeManager: ReturnType | null = null let cleanupNodeManager: (() => void) | null = null -// Slot layout sync management -let slotSync: ReturnType | null = null +// Slot/link layout sync management +const slotSync = useSlotLayoutSync() let slotSyncStarted = false -let linkSync: ReturnType | null = null +const linkSync = useLinkLayoutSync() +let linkSyncStarted = false +const layoutSync = useLayoutSync() const vueNodeData = ref>(new Map()) const nodeState = ref>(new Map()) const nodePositions = ref>( @@ -238,13 +240,12 @@ const initializeNodeManager = () => { } // Initialize layout sync (one-way: Layout Store → LiteGraph) - const { startSync } = useLayoutSync() - startSync(canvasStore.canvas) + layoutSync.startSync(canvasStore.canvas) // Initialize link layout sync for event-driven updates - linkSync = useLinkLayoutSync() if (canvasStore.canvas) { linkSync.start(canvasStore.canvas as LGraphCanvas) + linkSyncStarted = true } // Force computed properties to re-evaluate @@ -262,11 +263,14 @@ const disposeNodeManagerAndSyncs = () => { cleanupNodeManager = null // Clean up link layout sync - if (linkSync) { + if (linkSyncStarted) { linkSync.stop() - linkSync = null + linkSyncStarted = false } + // Stop layout sync when leaving Vue nodes mode + layoutSync.stopSync() + // Reset reactive maps to inert defaults vueNodeData.value = new Map() nodeState.value = new Map() @@ -309,7 +313,6 @@ watch( } // Start sync if not in Vue mode and not already started - if (!slotSync) slotSync = useSlotLayoutSync() if (!slotSyncStarted && !isVueNodesEnabled.value) { const started = slotSync.attemptStart(canvas as LGraphCanvas) slotSyncStarted = started @@ -339,7 +342,6 @@ watch( if (!canvasStore.canvas || !comfyApp.graph) return // Ensure slot sync is active - if (!slotSync) slotSync = useSlotLayoutSync() if (!slotSyncStarted) { const started = slotSync.attemptStart(canvasStore.canvas as LGraphCanvas) slotSyncStarted = started @@ -773,14 +775,15 @@ onUnmounted(() => { nodeManager.cleanup() nodeManager = null } - if (slotSync) { + if (slotSyncStarted) { slotSync.stop() - slotSync = null slotSyncStarted = false } - if (linkSync) { + if (linkSyncStarted) { linkSync.stop() - linkSync = null + linkSyncStarted = false } + // Ensure layout sync stops + layoutSync.stopSync() }) diff --git a/src/renderer/core/layout/sync/useLayoutSync.ts b/src/renderer/core/layout/sync/useLayoutSync.ts index 2aee7974c..25085c831 100644 --- a/src/renderer/core/layout/sync/useLayoutSync.ts +++ b/src/renderer/core/layout/sync/useLayoutSync.ts @@ -20,6 +20,11 @@ export function useLayoutSync() { * This is one-way: Layout → LiteGraph only */ function startSync(canvas: any) { + // Ensure previous subscription is cleared before starting a new one + if (unsubscribe) { + unsubscribe() + unsubscribe = null + } if (!canvas?.graph) return // Subscribe to layout changes diff --git a/src/renderer/core/layout/sync/useLinkLayoutSync.ts b/src/renderer/core/layout/sync/useLinkLayoutSync.ts index fd6b3b19c..3e616eddd 100644 --- a/src/renderer/core/layout/sync/useLinkLayoutSync.ts +++ b/src/renderer/core/layout/sync/useLinkLayoutSync.ts @@ -258,6 +258,8 @@ export function useLinkLayoutSync() { * Start link layout sync with event-driven functionality */ function start(canvasInstance: LGraphCanvas): void { + // Avoid duplicate subscriptions/handlers if start is called again + stop() canvas = canvasInstance graph = canvas.graph if (!graph) return