mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-07 22:20:03 +00:00
refactor: centralized node mode management
This commit is contained in:
@@ -150,6 +150,7 @@ export function useLayoutMutations(): LayoutMutations {
|
||||
size: layout.size ?? { width: 200, height: 100 },
|
||||
zIndex: layout.zIndex ?? 0,
|
||||
visible: layout.visible ?? true,
|
||||
mode: layout.mode ?? 0, // Default to ALWAYS
|
||||
bounds: {
|
||||
x: layout.position?.x ?? 0,
|
||||
y: layout.position?.y ?? 0,
|
||||
|
||||
@@ -17,6 +17,7 @@ describe('layoutStore CRDT operations', () => {
|
||||
size: { width: 200, height: 100 },
|
||||
zIndex: 0,
|
||||
visible: true,
|
||||
mode: 0,
|
||||
bounds: { x: 100, y: 100, width: 200, height: 100 }
|
||||
})
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import type {
|
||||
RerouteId,
|
||||
RerouteLayout,
|
||||
ResizeNodeOperation,
|
||||
SetNodeModeOperation,
|
||||
SetNodeZIndexOperation,
|
||||
SlotLayout
|
||||
} from '@/renderer/core/layout/types'
|
||||
@@ -295,6 +296,18 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
actor: this.currentActor
|
||||
})
|
||||
}
|
||||
if (existingLayout.mode !== newLayout.mode) {
|
||||
this.applyOperation({
|
||||
type: 'setNodeMode',
|
||||
entity: 'node',
|
||||
nodeId,
|
||||
mode: newLayout.mode,
|
||||
previousMode: existingLayout.mode,
|
||||
timestamp: Date.now(),
|
||||
source: this.currentSource,
|
||||
actor: this.currentActor
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
trigger()
|
||||
@@ -870,6 +883,9 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
case 'setNodeZIndex':
|
||||
this.handleSetNodeZIndex(operation as SetNodeZIndexOperation, change)
|
||||
break
|
||||
case 'setNodeMode':
|
||||
this.handleSetNodeMode(operation as SetNodeModeOperation, change)
|
||||
break
|
||||
case 'createNode':
|
||||
this.handleCreateNode(operation as CreateNodeOperation, change)
|
||||
break
|
||||
@@ -969,7 +985,12 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
* Initialize store with existing nodes
|
||||
*/
|
||||
initializeFromLiteGraph(
|
||||
nodes: Array<{ id: string; pos: [number, number]; size: [number, number] }>
|
||||
nodes: Array<{
|
||||
id: string
|
||||
pos: [number, number]
|
||||
size: [number, number]
|
||||
mode?: number
|
||||
}>
|
||||
): void {
|
||||
this.ydoc.transact(() => {
|
||||
this.ynodes.clear()
|
||||
@@ -993,6 +1014,7 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
size: { width: node.size[0], height: node.size[1] },
|
||||
zIndex: index,
|
||||
visible: true,
|
||||
mode: node.mode ?? 0, // Default to ALWAYS if not provided
|
||||
bounds: {
|
||||
x: node.pos[0],
|
||||
y: node.pos[1],
|
||||
@@ -1078,6 +1100,17 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
change.nodeIds.push(operation.nodeId)
|
||||
}
|
||||
|
||||
private handleSetNodeMode(
|
||||
operation: SetNodeModeOperation,
|
||||
change: LayoutChange
|
||||
): void {
|
||||
const ynode = this.ynodes.get(operation.nodeId)
|
||||
if (!ynode) return
|
||||
|
||||
ynode.set('mode', operation.mode)
|
||||
change.nodeIds.push(operation.nodeId)
|
||||
}
|
||||
|
||||
private handleCreateNode(
|
||||
operation: CreateNodeOperation,
|
||||
change: LayoutChange
|
||||
@@ -1428,6 +1461,43 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
return Y.encodeStateAsUpdate(this.ydoc)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the execution mode for a single node.
|
||||
* Applies the node's changeMode method if available and notifies the graph.
|
||||
*/
|
||||
setNodeMode(nodeId: NodeId, mode: number): void {
|
||||
const ynode = this.ynodes.get(nodeId)
|
||||
if (!ynode) return
|
||||
|
||||
const currentLayout = yNodeToLayout(ynode)
|
||||
if (currentLayout.mode === mode) return // No change needed
|
||||
|
||||
this.applyOperation({
|
||||
type: 'setNodeMode',
|
||||
entity: 'node',
|
||||
nodeId,
|
||||
mode,
|
||||
previousMode: currentLayout.mode,
|
||||
timestamp: Date.now(),
|
||||
source: this.currentSource,
|
||||
actor: this.currentActor
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the execution mode for multiple nodes.
|
||||
* Applies the mode to all nodes atomically.
|
||||
*/
|
||||
setNodesMode(nodeIds: NodeId[], mode: number): void {
|
||||
if (nodeIds.length === 0) return
|
||||
|
||||
// Apply mode to each node
|
||||
// Note: We could create a batch operation type if needed for better performance
|
||||
nodeIds.forEach((nodeId) => {
|
||||
this.setNodeMode(nodeId, mode)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch update node bounds using Yjs transaction for atomicity.
|
||||
*/
|
||||
|
||||
@@ -48,6 +48,7 @@ export interface NodeLayout {
|
||||
size: Size
|
||||
zIndex: number
|
||||
visible: boolean
|
||||
mode: number // LGraphEventMode: 0=ALWAYS, 2=NEVER, 4=BYPASS, etc.
|
||||
// Computed bounds for hit testing
|
||||
bounds: Bounds
|
||||
}
|
||||
@@ -120,6 +121,7 @@ type OperationType =
|
||||
| 'moveNode'
|
||||
| 'resizeNode'
|
||||
| 'setNodeZIndex'
|
||||
| 'setNodeMode'
|
||||
| 'createNode'
|
||||
| 'deleteNode'
|
||||
| 'setNodeVisibility'
|
||||
@@ -157,6 +159,15 @@ export interface SetNodeZIndexOperation extends NodeOpBase {
|
||||
previousZIndex: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Set node mode operation
|
||||
*/
|
||||
export interface SetNodeModeOperation extends NodeOpBase {
|
||||
type: 'setNodeMode'
|
||||
mode: number
|
||||
previousMode: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Create node operation
|
||||
*/
|
||||
@@ -243,6 +254,7 @@ export type LayoutOperation =
|
||||
| MoveNodeOperation
|
||||
| ResizeNodeOperation
|
||||
| SetNodeZIndexOperation
|
||||
| SetNodeModeOperation
|
||||
| CreateNodeOperation
|
||||
| DeleteNodeOperation
|
||||
| SetNodeVisibilityOperation
|
||||
|
||||
@@ -62,6 +62,7 @@ describe('layoutMath utils', () => {
|
||||
size: { width, height },
|
||||
zIndex: 0,
|
||||
visible: true,
|
||||
mode: 0,
|
||||
bounds: { x, y, width, height }
|
||||
})
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ export const NODE_LAYOUT_DEFAULTS: NodeLayout = {
|
||||
size: { width: 100, height: 50 },
|
||||
zIndex: 0,
|
||||
visible: true,
|
||||
mode: 0, // LGraphEventMode.ALWAYS
|
||||
bounds: { x: 0, y: 0, width: 100, height: 50 }
|
||||
}
|
||||
|
||||
@@ -20,6 +21,7 @@ export function layoutToYNode(layout: NodeLayout): NodeLayoutMap {
|
||||
ynode.set('size', layout.size)
|
||||
ynode.set('zIndex', layout.zIndex)
|
||||
ynode.set('visible', layout.visible)
|
||||
ynode.set('mode', layout.mode)
|
||||
ynode.set('bounds', layout.bounds)
|
||||
return ynode
|
||||
}
|
||||
@@ -40,6 +42,7 @@ export function yNodeToLayout(ynode: NodeLayoutMap): NodeLayout {
|
||||
size: getOr(ynode, 'size', NODE_LAYOUT_DEFAULTS.size),
|
||||
zIndex: getOr(ynode, 'zIndex', NODE_LAYOUT_DEFAULTS.zIndex),
|
||||
visible: getOr(ynode, 'visible', NODE_LAYOUT_DEFAULTS.visible),
|
||||
mode: getOr(ynode, 'mode', NODE_LAYOUT_DEFAULTS.mode),
|
||||
bounds: getOr(ynode, 'bounds', NODE_LAYOUT_DEFAULTS.bounds)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ describe('MinimapDataSource', () => {
|
||||
size: { width: 100, height: 50 },
|
||||
zIndex: 0,
|
||||
visible: true,
|
||||
mode: 0,
|
||||
bounds: { x: 0, y: 0, width: 100, height: 50 }
|
||||
}
|
||||
]
|
||||
|
||||
@@ -80,6 +80,7 @@ const mockData = vi.hoisted(() => {
|
||||
size: { width: 100, height: 100 },
|
||||
zIndex: 1,
|
||||
visible: true,
|
||||
mode: 0,
|
||||
bounds: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
||||
Reference in New Issue
Block a user