mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-28 18:22:40 +00:00
[backport core/1.33] fix: preserve Vue node reactivity during undo/redo operations (#7257)
Backport of #7222 to `core/1.33` Automatically created by backport workflow. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7257-backport-core-1-33-fix-preserve-Vue-node-reactivity-during-undo-redo-operations-2c46d73d36508184aff1c7c0e8e82408) by [Unito](https://www.unito.io) Co-authored-by: Terry Jia <terryjia88@gmail.com>
This commit is contained in:
@@ -956,6 +956,15 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
return this.currentActor
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up refs and triggers for a node when its Vue component unmounts.
|
||||
* This should be called from the component's onUnmounted hook.
|
||||
*/
|
||||
cleanupNodeRef(nodeId: NodeId): void {
|
||||
this.nodeRefs.delete(nodeId)
|
||||
this.nodeTriggers.delete(nodeId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize store with existing nodes
|
||||
*/
|
||||
@@ -964,8 +973,10 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
): void {
|
||||
this.ydoc.transact(() => {
|
||||
this.ynodes.clear()
|
||||
this.nodeRefs.clear()
|
||||
this.nodeTriggers.clear()
|
||||
// Note: We intentionally do NOT clear nodeRefs and nodeTriggers here.
|
||||
// Vue components may already hold references to these refs, and clearing
|
||||
// them would break the reactivity chain. The refs will be reused when
|
||||
// nodes are recreated, and stale refs will be cleaned up over time.
|
||||
this.spatialIndex.clear()
|
||||
this.linkSegmentSpatialIndex.clear()
|
||||
this.slotSpatialIndex.clear()
|
||||
@@ -995,6 +1006,9 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
// Add to spatial index
|
||||
this.spatialIndex.insert(layout.id, layout.bounds)
|
||||
})
|
||||
|
||||
// Trigger all existing refs to notify Vue of the new data
|
||||
this.nodeTriggers.forEach((trigger) => trigger())
|
||||
}, 'initialization')
|
||||
}
|
||||
|
||||
@@ -1085,8 +1099,10 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
if (!this.ynodes.has(operation.nodeId)) return
|
||||
|
||||
this.ynodes.delete(operation.nodeId)
|
||||
this.nodeRefs.delete(operation.nodeId)
|
||||
this.nodeTriggers.delete(operation.nodeId)
|
||||
// Note: We intentionally do NOT delete nodeRefs and nodeTriggers here.
|
||||
// During undo/redo, Vue components may still hold references to the old ref.
|
||||
// If we delete the trigger, Vue won't be notified when the node is re-created.
|
||||
// The trigger will be called in finalizeOperation to notify Vue of the change.
|
||||
|
||||
// Remove from spatial index
|
||||
this.spatialIndex.remove(operation.nodeId)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { computed, toValue } from 'vue'
|
||||
import { computed, onUnmounted, toValue } from 'vue'
|
||||
import type { MaybeRefOrGetter } from 'vue'
|
||||
|
||||
import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations'
|
||||
@@ -17,6 +17,11 @@ export function useNodeLayout(nodeIdMaybe: MaybeRefOrGetter<string>) {
|
||||
// Get the customRef for this node (shared write access)
|
||||
const layoutRef = layoutStore.getNodeLayoutRef(nodeId)
|
||||
|
||||
// Clean up refs and triggers when Vue component unmounts
|
||||
onUnmounted(() => {
|
||||
layoutStore.cleanupNodeRef(nodeId)
|
||||
})
|
||||
|
||||
// Computed properties for easy access
|
||||
const position = computed(() => {
|
||||
const layout = layoutRef.value
|
||||
|
||||
Reference in New Issue
Block a user