mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-28 18:22:40 +00:00
fix: suppress link rendering during slot sync after graph reconfigure (#8367)
## Description Fixes link alignment issues after undo/redo operations in Vue Nodes 2.0. When multiple connections exist from the same output to different nodes, performing an undo would cause the connections to become misaligned with their inputs. ## Root Cause When undo triggers `loadGraphData`, the graph is reconfigured and Vue node components are destroyed and recreated. The new slot elements mount and schedule RAF-batched position syncs via `scheduleSlotLayoutSync`. However, links are drawn **before** the RAF batch completes, causing `getSlotPosition()` to return stale/missing positions. ## Solution - Export a new `flushPendingSlotLayoutSyncs()` function from `useSlotElementTracking.ts` - Create a `useGraphConfigureSlotSync` composable that flushes pending syncs after graph configuration - Integrate the flush into `addAfterConfigureHandler` in `app.ts`, called after `onAfterGraphConfigured` - Force canvas redraw after flushing to render links with correct positions ## Testing - Added unit tests for `flushPendingSlotLayoutSyncs` - Added unit tests for `useGraphConfigureSlotSync` composable - Manual verification: connections now align correctly after undo/redo operations ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8367-fix-flush-pending-slot-layout-syncs-after-graph-configure-2f66d73d365081a3a564fac96c44a048) by [Unito](https://www.unito.io) --------- Co-authored-by: Subagent 5 <subagent@example.com> Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import { useSharedCanvasPositionConversion } from '@/composables/element/useCanv
|
||||
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
|
||||
import { getSlotKey } from '@/renderer/core/layout/slots/slotIdentifier'
|
||||
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
|
||||
import { app } from '@/scripts/app'
|
||||
import type { SlotLayout } from '@/renderer/core/layout/types'
|
||||
import {
|
||||
isPointEqual,
|
||||
@@ -28,16 +29,36 @@ const raf = createRafBatch(() => {
|
||||
|
||||
function scheduleSlotLayoutSync(nodeId: string) {
|
||||
pendingNodes.add(nodeId)
|
||||
// Re-assert pending flag for late mounts (Vue components mounting after
|
||||
// flushScheduledSlotLayoutSync was called synchronously in onConfigure)
|
||||
layoutStore.setPendingSlotSync(true)
|
||||
raf.schedule()
|
||||
}
|
||||
|
||||
function flushScheduledSlotLayoutSync() {
|
||||
if (pendingNodes.size === 0) return
|
||||
export function flushScheduledSlotLayoutSync() {
|
||||
if (pendingNodes.size === 0) {
|
||||
// No pending nodes - check if we should wait for Vue components to mount
|
||||
const graph = app.canvas?.graph
|
||||
const hasNodes = graph && graph._nodes && graph._nodes.length > 0
|
||||
if (hasNodes) {
|
||||
// Graph has nodes but Vue hasn't mounted them yet - keep flag set
|
||||
// so late mounts can re-assert it via scheduleSlotLayoutSync()
|
||||
return
|
||||
}
|
||||
// No nodes in graph - safe to clear the flag (no Vue components will mount)
|
||||
layoutStore.setPendingSlotSync(false)
|
||||
app.canvas?.setDirty(true, true)
|
||||
return
|
||||
}
|
||||
const conv = useSharedCanvasPositionConversion()
|
||||
for (const nodeId of Array.from(pendingNodes)) {
|
||||
pendingNodes.delete(nodeId)
|
||||
syncNodeSlotLayoutsFromDOM(nodeId, conv)
|
||||
}
|
||||
// Clear the pending sync flag - slots are now synced
|
||||
layoutStore.setPendingSlotSync(false)
|
||||
// Trigger canvas redraw now that links can render with correct positions
|
||||
app.canvas?.setDirty(true, true)
|
||||
}
|
||||
|
||||
export function syncNodeSlotLayoutsFromDOM(
|
||||
|
||||
Reference in New Issue
Block a user