Skip to content

Commit 0bb1940

Browse files
committed
refactor: delete useVueNodeLifecycle
What was left after node registration moved to `LGraph.add` was two calls on two transitions, wrapped in a shared composable with one consumer. - The `clearAllSlotLayouts` watch was redundant entering Vue mode, since `clearViewGeometry` already drops slot layouts along with link and reroute geometry. It was only doing work on the way out, so dispose clears instead and the watch goes. This widens what mode-leave clears; legacy mode reads none of it and re-entry clears again. - `isInitialized` guarded nothing: `startSync` opens with `stopSync()`, and `clearViewGeometry` is idempotent. - `createSharedComposable` held no shared state once that flag was gone, and `GraphCanvas.vue` was the only caller. - The `arrange()` pass is legacy-canvas preparation, not Vue node lifecycle — it computes slot positions before `drawConnections` can run without them. It moves to `arrangeForLegacyRender` next to the other litegraph canvas adapters, rather than becoming another method on LGraph. The transitions were already driven from `GraphCanvas.vue`, which watches `currentGraph` and `isInSubgraph`, so the remainder lands where it was being called from.
1 parent 626193a commit 0bb1940

3 files changed

Lines changed: 64 additions & 103 deletions

File tree

src/components/graph/GraphCanvas.vue

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
</template>
111111

112112
<script setup lang="ts">
113-
import { until, useEventListener } from '@vueuse/core'
113+
import { until, useEventListener, whenever } from '@vueuse/core'
114114
import {
115115
computed,
116116
nextTick,
@@ -153,7 +153,6 @@ import { useChainCallback } from '@/composables/functional/useChainCallback'
153153
import { useGroupContextMenu } from '@/composables/graph/useGroupContextMenu'
154154
import { installErrorClearingHooks } from '@/composables/graph/useErrorClearingHooks'
155155
import type { NodeState } from '@/types/nodeState'
156-
import { useVueNodeLifecycle } from '@/composables/graph/useVueNodeLifecycle'
157156
import { useNodeBadge } from '@/composables/node/useNodeBadge'
158157
import { useCanvasDrop } from '@/composables/useCanvasDrop'
159158
import { useContextMenuTranslation } from '@/composables/useContextMenuTranslation'
@@ -173,7 +172,9 @@ import { useWorkflowPersistenceV2 as useWorkflowPersistence } from '@/platform/w
173172
import { useNodeDataStore } from '@/stores/nodeDataStore'
174173
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
175174
import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions'
175+
import { arrangeForLegacyRender } from '@/renderer/core/canvas/litegraph/arrangeForLegacyRender'
176176
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
177+
import { useLayoutSync } from '@/renderer/core/layout/sync/useLayoutSync'
177178
import TransformPane from '@/renderer/core/layout/transform/TransformPane.vue'
178179
import MiniMap from '@/renderer/extensions/minimap/MiniMap.vue'
179180
import LGraphNode from '@/renderer/extensions/vueNodes/components/LGraphNode.vue'
@@ -253,8 +254,22 @@ const minimapEnabled = computed(() => settingStore.get('Comfy.Minimap.Visible'))
253254
// Feature flags
254255
const { shouldRenderVueNodes } = useVueFeatureFlags()
255256
256-
// Vue node system
257-
const vueNodeLifecycle = useVueNodeLifecycle()
257+
// Layout↔LiteGraph sync. Node geometry registers itself in LGraph.add, so all
258+
// that is needed here is dropping view-scoped geometry when the viewed graph
259+
// changes and running the sync for as long as Vue nodes are rendering.
260+
const { startSync, stopSync } = useLayoutSync()
261+
262+
const startVueNodeLayout = () => {
263+
layoutStore.clearViewGeometry()
264+
// Start sync AFTER the reset so bootstrap operations don't trigger the
265+
// Layout→LiteGraph writeback loop redundantly.
266+
startSync(canvasStore.canvas)
267+
}
268+
269+
const stopVueNodeLayout = () => {
270+
stopSync()
271+
layoutStore.clearViewGeometry()
272+
}
258273
259274
// Error-clearing hooks run regardless of rendering mode (Vue or legacy canvas).
260275
let cleanupErrorHooks: (() => void) | null = null
@@ -267,13 +282,32 @@ watch(
267282
)
268283
269284
const handleVueNodeLifecycleReset = async () => {
270-
if (shouldRenderVueNodes.value) {
271-
vueNodeLifecycle.disposeVueNodeLayout()
272-
await nextTick()
273-
vueNodeLifecycle.initializeVueNodeLayout()
274-
}
285+
if (!shouldRenderVueNodes.value) return
286+
287+
stopSync()
288+
await nextTick()
289+
startVueNodeLayout()
275290
}
276291
292+
watch(
293+
() => shouldRenderVueNodes.value && Boolean(comfyApp.canvas?.graph),
294+
(enabled) => {
295+
if (enabled) startVueNodeLayout()
296+
},
297+
{ immediate: true }
298+
)
299+
300+
whenever(
301+
() => !shouldRenderVueNodes.value,
302+
() => {
303+
stopVueNodeLayout()
304+
305+
const graph = comfyApp.canvas?.graph
306+
if (graph) arrangeForLegacyRender(graph)
307+
comfyApp.canvas?.setDirty(true, true)
308+
}
309+
)
310+
277311
watch(() => canvasStore.currentGraph, handleVueNodeLifecycleReset)
278312
279313
watch(
@@ -585,7 +619,7 @@ onMounted(async () => {
585619
onUnmounted(() => {
586620
cleanupErrorHooks?.()
587621
cleanupErrorHooks = null
588-
vueNodeLifecycle.disposeVueNodeLayout()
622+
stopSync()
589623
})
590624
function forwardPointerDownPanEvent(e: PointerEvent) {
591625
forwardPanEvent(e, isMiddlePointerInput)

src/composables/graph/useVueNodeLifecycle.ts

Lines changed: 0 additions & 93 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { LGraph } from '@/lib/litegraph/src/litegraph'
2+
3+
/**
4+
* Computes slot positions for every node so the legacy canvas has them before
5+
* it draws.
6+
*
7+
* `drawConnections` can run before `drawNode` on the foreground canvas, so
8+
* without this the first frame after leaving Vue nodes draws links against
9+
* slot positions that were never arranged.
10+
*/
11+
export function arrangeForLegacyRender(graph: LGraph): void {
12+
for (const node of graph._nodes) {
13+
if (node.flags.collapsed) continue
14+
try {
15+
node.arrange()
16+
} catch {
17+
/* skip nodes not fully initialized */
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)