diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useCopyPaste.ts b/invokeai/frontend/web/src/features/nodes/hooks/useCopyPaste.ts index 08def1514c..8be972363f 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useCopyPaste.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useCopyPaste.ts @@ -5,11 +5,13 @@ import { $copiedNodes, $cursorPos, $edgesToCopiedNodes, - selectionPasted, + edgesChanged, + nodesChanged, selectNodesSlice, } from 'features/nodes/store/nodesSlice'; import { findUnoccupiedPosition } from 'features/nodes/store/util/findUnoccupiedPosition'; import { isEqual, uniqWith } from 'lodash-es'; +import type { EdgeChange, NodeChange } from 'reactflow'; import { v4 as uuidv4 } from 'uuid'; const copySelection = () => { @@ -26,7 +28,7 @@ const copySelection = () => { const pasteSelection = (withEdgesToCopiedNodes?: boolean) => { const { getState, dispatch } = getStore(); - const currentNodes = selectNodesSlice(getState()).nodes; + const { nodes, edges } = selectNodesSlice(getState()); const cursorPos = $cursorPos.get(); const copiedNodes = deepClone($copiedNodes.get()); @@ -46,7 +48,7 @@ const pasteSelection = (withEdgesToCopiedNodes?: boolean) => { const offsetY = cursorPos ? cursorPos.y - minY : 50; copiedNodes.forEach((node) => { - const { x, y } = findUnoccupiedPosition(currentNodes, node.position.x + offsetX, node.position.y + offsetY); + const { x, y } = findUnoccupiedPosition(nodes, node.position.x + offsetX, node.position.y + offsetY); node.position.x = x; node.position.y = y; // Pasted nodes are selected @@ -68,7 +70,40 @@ const pasteSelection = (withEdgesToCopiedNodes?: boolean) => { node.data.id = id; }); - dispatch(selectionPasted({ nodes: copiedNodes, edges: copiedEdges })); + const nodeChanges: NodeChange[] = []; + const edgeChanges: EdgeChange[] = []; + // Deselect existing nodes + nodes.forEach((n) => { + nodeChanges.push({ + id: n.data.id, + type: 'select', + selected: false, + }); + }); + // Add new nodes + copiedNodes.forEach((n) => { + nodeChanges.push({ + item: n, + type: 'add', + }); + }); + // Deselect existing edges + edges.forEach((e) => { + edgeChanges.push({ + id: e.id, + type: 'select', + selected: false, + }); + }); + // Add new edges + copiedEdges.forEach((e) => { + edgeChanges.push({ + item: e, + type: 'add', + }); + }); + dispatch(nodesChanged(nodeChanges)); + dispatch(edgesChanged(edgeChanges)); }; const api = { copySelection, pasteSelection }; diff --git a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts index 0838778454..416d7065bb 100644 --- a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts +++ b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts @@ -347,47 +347,6 @@ export const nodesSlice = createSlice({ state.nodes = []; state.edges = []; }, - selectionPasted: (state, action: PayloadAction<{ nodes: AnyNode[]; edges: InvocationNodeEdge[] }>) => { - const { nodes, edges } = action.payload; - - const nodeChanges: NodeChange[] = []; - - // Deselect existing nodes - state.nodes.forEach((n) => { - nodeChanges.push({ - id: n.data.id, - type: 'select', - selected: false, - }); - }); - // Add new nodes - nodes.forEach((n) => { - nodeChanges.push({ - item: n, - type: 'add', - }); - }); - - const edgeChanges: EdgeChange[] = []; - // Deselect existing edges - state.edges.forEach((e) => { - edgeChanges.push({ - id: e.id, - type: 'select', - selected: false, - }); - }); - // Add new edges - edges.forEach((e) => { - edgeChanges.push({ - item: e, - type: 'add', - }); - }); - - state.nodes = applyNodeChanges(nodeChanges, state.nodes); - state.edges = applyEdgeChanges(edgeChanges, state.edges); - }, selectionDeleted: (state) => { const selectedNodes = state.nodes.filter((n) => n.selected); const selectedEdges = state.edges.filter((e) => e.selected); @@ -455,7 +414,6 @@ export const { nodesChanged, nodeUseCacheChanged, notesNodeValueChanged, - selectionPasted, selectionDeleted, undo, redo, @@ -498,7 +456,7 @@ export const nodesPersistConfig: PersistConfig = { persistDenylist: [], }; -const selectionMatcher = isAnyOf(selectionPasted, nodeExclusivelySelected); +const selectionMatcher = isAnyOf(nodeExclusivelySelected); const isSelectionAction = (action: UnknownAction) => { if (selectionMatcher(action)) { @@ -573,6 +531,5 @@ export const isAnyNodeOrEdgeMutation = isAnyOf( nodeNotesChanged, nodeUseCacheChanged, notesNodeValueChanged, - selectionPasted, selectionDeleted );