diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/AddNodePopover/AddNodePopover.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/AddNodePopover/AddNodePopover.tsx index 357514f380..226a8f006d 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/AddNodePopover/AddNodePopover.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/AddNodePopover/AddNodePopover.tsx @@ -143,16 +143,24 @@ const AddNodePopover = () => { // Deselect all other nodes and edges const nodeChanges: NodeChange[] = [{ type: 'add', item: node }]; const edgeChanges: EdgeChange[] = []; - nodes.forEach(({ id }) => { - nodeChanges.push({ type: 'select', id, selected: false }); + nodes.forEach(({ id, selected }) => { + if (selected) { + nodeChanges.push({ type: 'select', id, selected: false }); + } }); - edges.forEach(({ id }) => { - edgeChanges.push({ type: 'select', id, selected: false }); + edges.forEach(({ id, selected }) => { + if (selected) { + edgeChanges.push({ type: 'select', id, selected: false }); + } }); // Onwards! - dispatch(nodesChanged(nodeChanges)); - dispatch(edgesChanged(edgeChanges)); + if (nodeChanges.length > 0) { + dispatch(nodesChanged(nodeChanges)); + } + if (edgeChanges.length > 0) { + dispatch(edgesChanged(edgeChanges)); + } return node; }, [buildInvocation, store, dispatch, t, toaster] diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/Flow.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/Flow.tsx index 8e67758d62..19f56b7747 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/Flow.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/Flow.tsx @@ -90,15 +90,17 @@ export const Flow = memo(() => { ); const onNodesChange: OnNodesChange = useCallback( - (changes) => { - dispatch(nodesChanged(changes)); + (nodeChanges) => { + dispatch(nodesChanged(nodeChanges)); }, [dispatch] ); const onEdgesChange: OnEdgesChange = useCallback( (changes) => { - dispatch(edgesChanged(changes)); + if (changes.length > 0) { + dispatch(edgesChanged(changes)); + } }, [dispatch] ); @@ -207,14 +209,22 @@ export const Flow = memo(() => { const { nodes, edges } = store.getState().nodes.present; const nodeChanges: NodeChange[] = []; const edgeChanges: EdgeChange[] = []; - nodes.forEach(({ id }) => { - nodeChanges.push({ type: 'select', id, selected: true }); + nodes.forEach(({ id, selected }) => { + if (!selected) { + nodeChanges.push({ type: 'select', id, selected: true }); + } }); - edges.forEach(({ id }) => { - edgeChanges.push({ type: 'select', id, selected: true }); + edges.forEach(({ id, selected }) => { + if (!selected) { + edgeChanges.push({ type: 'select', id, selected: true }); + } }); - dispatch(nodesChanged(nodeChanges)); - dispatch(edgesChanged(edgeChanges)); + if (nodeChanges.length > 0) { + dispatch(nodesChanged(nodeChanges)); + } + if (edgeChanges.length > 0) { + dispatch(edgesChanged(edgeChanges)); + } }, [dispatch, store] ); @@ -275,8 +285,12 @@ export const Flow = memo(() => { .forEach(({ id }) => { edgeChanges.push({ type: 'remove', id }); }); - dispatch(nodesChanged(nodeChanges)); - dispatch(edgesChanged(edgeChanges)); + if (nodeChanges.length > 0) { + dispatch(nodesChanged(nodeChanges)); + } + if (edgeChanges.length > 0) { + dispatch(edgesChanged(edgeChanges)); + } }, [dispatch, store]); useHotkeys(['delete', 'backspace'], onDeleteHotkey); diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/common/NodeWrapper.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/common/NodeWrapper.tsx index a0260c7301..983aee1d48 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/common/NodeWrapper.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/common/NodeWrapper.tsx @@ -40,8 +40,15 @@ const NodeWrapper = (props: NodeWrapperProps) => { (e: MouseEvent) => { if (!e.ctrlKey && !e.altKey && !e.metaKey && !e.shiftKey) { const { nodes } = store.getState().nodes.present; - const nodeChanges: NodeChange[] = nodes.map(({ id }) => ({ type: 'select', id, selected: id === nodeId })); - dispatch(nodesChanged(nodeChanges)); + const nodeChanges: NodeChange[] = []; + nodes.forEach(({ id, selected }) => { + if (selected !== (id === nodeId)) { + nodeChanges.push({ type: 'select', id, selected: id === nodeId }); + } + }); + if (nodeChanges.length > 0) { + dispatch(nodesChanged(nodeChanges)); + } } onCloseGlobal(); }, diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useConnection.ts b/invokeai/frontend/web/src/features/nodes/hooks/useConnection.ts index 36491e80bc..0bca73731e 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useConnection.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useConnection.ts @@ -92,15 +92,15 @@ export const useConnection = () => { ); if (connection) { const newEdge = connectionToEdge(connection); - const changes: EdgeChange[] = [{ type: 'add', item: newEdge }]; + const edgeChanges: EdgeChange[] = [{ type: 'add', item: newEdge }]; const nodesToUpdate = [newEdge.source, newEdge.target]; if (edgePendingUpdate) { $didUpdateEdge.set(true); - changes.push({ type: 'remove', id: edgePendingUpdate.id }); + edgeChanges.push({ type: 'remove', id: edgePendingUpdate.id }); nodesToUpdate.push(edgePendingUpdate.source, edgePendingUpdate.target); } - dispatch(edgesChanged(changes)); + dispatch(edgesChanged(edgeChanges)); updateNodeInternals(nodesToUpdate); } $pendingConnection.set(null); diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useCopyPaste.ts b/invokeai/frontend/web/src/features/nodes/hooks/useCopyPaste.ts index 4ca331d61b..32db806cde 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useCopyPaste.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useCopyPaste.ts @@ -73,12 +73,14 @@ const pasteSelection = (withEdgesToCopiedNodes?: boolean) => { const nodeChanges: NodeChange[] = []; const edgeChanges: EdgeChange[] = []; // Deselect existing nodes - nodes.forEach(({ id }) => { - nodeChanges.push({ - type: 'select', - id, - selected: false, - }); + nodes.forEach(({ id, selected }) => { + if (selected) { + nodeChanges.push({ + type: 'select', + id, + selected: false, + }); + } }); // Add new nodes copiedNodes.forEach((n) => { @@ -88,12 +90,14 @@ const pasteSelection = (withEdgesToCopiedNodes?: boolean) => { }); }); // Deselect existing edges - edges.forEach(({ id }) => { - edgeChanges.push({ - type: 'select', - id, - selected: false, - }); + edges.forEach(({ id, selected }) => { + if (selected) { + edgeChanges.push({ + type: 'select', + id, + selected: false, + }); + } }); // Add new edges copiedEdges.forEach((e) => { @@ -102,8 +106,12 @@ const pasteSelection = (withEdgesToCopiedNodes?: boolean) => { item: e, }); }); - dispatch(nodesChanged(nodeChanges)); - dispatch(edgesChanged(edgeChanges)); + if (nodeChanges.length > 0) { + dispatch(nodesChanged(nodeChanges)); + } + if (edgeChanges.length > 0) { + dispatch(edgesChanged(edgeChanges)); + } }; const api = { copySelection, pasteSelection };