From 5f500bca184f02b5ca973346fda28352f441a5bf Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Wed, 20 Oct 2021 23:46:47 +0200
Subject: [PATCH] fix: store actions blocking main thread
* map function overwriting nodes causes main thread to be blocked
* instead use splice
---
src/components/Nodes/Node.vue | 66 +++++------
src/container/Flow/Flow.vue | 2 +-
src/container/NodeRenderer/NodeRenderer.vue | 10 +-
src/store/useFlowStore.ts | 124 +++++++++-----------
src/types/actions.ts | 2 +-
5 files changed, 91 insertions(+), 113 deletions(-)
diff --git a/src/components/Nodes/Node.vue b/src/components/Nodes/Node.vue
index 80773a56..c45d759d 100644
--- a/src/components/Nodes/Node.vue
+++ b/src/components/Nodes/Node.vue
@@ -1,28 +1,20 @@
{
`vue-flow__node-${props.node.type}`,
{
selected: props.selected,
- selectable: props.selectable,
+ selectable: selectable,
},
]"
:style="{
zIndex: props.selected ? 10 : 3,
transform: `translate(${props.node.__rf.position.x}px,${props.node.__rf.position.y}px)`,
- pointerEvents: props.selectable || props.draggable ? 'all' : 'none',
+ pointerEvents: selectable || draggable ? 'all' : 'none',
opacity: props.node.__rf.width !== null && props.node.__rf.height !== null ? 1 : 0,
...props.node.style,
}"
@@ -170,7 +166,7 @@ onMounted(() => {
xPos: props.node.__rf.position.x,
yPos: props.node.__rf.position.y,
selected: props.selected,
- connectable: props.connectable,
+ connectable,
sourcePosition: props.node.sourcePosition,
targetPosition: props.node.targetPosition,
dragging: props.node.__rf.isDragging,
@@ -184,7 +180,7 @@ onMounted(() => {
xPos: props.node.__rf.position.x,
yPos: props.node.__rf.position.y,
selected: props.selected,
- connectable: props.connectable,
+ connectable,
sourcePosition: props.node.sourcePosition,
targetPosition: props.node.targetPosition,
dragging: props.node.__rf.isDragging,
diff --git a/src/container/Flow/Flow.vue b/src/container/Flow/Flow.vue
index 81815265..60eefb29 100644
--- a/src/container/Flow/Flow.vue
+++ b/src/container/Flow/Flow.vue
@@ -151,7 +151,7 @@ const edgeTypes = createEdgeTypes({ ...defaultEdgeTypes, ...props.edgeTypes })
:multi-selection-key-code="props.multiSelectionKeyCode"
:selection-key-code="props.selectionKeyCode"
>
-
+
diff --git a/src/container/NodeRenderer/NodeRenderer.vue b/src/container/NodeRenderer/NodeRenderer.vue
index a5d9779c..e64e91e2 100644
--- a/src/container/NodeRenderer/NodeRenderer.vue
+++ b/src/container/NodeRenderer/NodeRenderer.vue
@@ -6,9 +6,12 @@ import { useStore } from '~/composables'
interface NodeRendererProps {
nodeTypes: Record
+ selectNodesOnDrag?: boolean
}
-const props = defineProps()
+const props = withDefaults(defineProps(), {
+ selectNodesOnDrag: true,
+})
const store = useStore()
@@ -49,12 +52,9 @@ const type = (node: TNode) => {
diff --git a/src/store/useFlowStore.ts b/src/store/useFlowStore.ts
index a2af7790..7ba0e166 100644
--- a/src/store/useFlowStore.ts
+++ b/src/store/useFlowStore.ts
@@ -1,6 +1,6 @@
import { setActivePinia, createPinia, defineStore, StoreDefinition } from 'pinia'
import isEqual from 'fast-deep-equal'
-import { Edge, FlowState, Node, NodeDiffUpdate, RevueFlowActions, XYPosition } from '~/types'
+import { Edge, FlowState, Node, RevueFlowActions } from '~/types'
import { clampPosition, getDimensions } from '~/utils'
import { getConnectedEdges, getNodesInside, getRectOfNodes, isEdge, isNode, parseEdge, parseNode } from '~/utils/graph'
import { getHandleBounds } from '~/components/Nodes/utils'
@@ -69,83 +69,70 @@ export default function useFlowStore(preloadedState: FlowState): StoreDefinition
this.nodes = nextNodes
this.edges = nextEdges
},
- updateNodeDimensions(updates) {
- this.nodes = this.nodes.map((node) => {
- const update = updates.find((u) => u.id === node.id)
- if (update) {
- const dimensions = getDimensions(update.nodeElement)
- const doUpdate =
- dimensions.width &&
- dimensions.height &&
- (node.__rf.width !== dimensions.width || node.__rf.height !== dimensions.height || update.forceUpdate)
+ updateNodeDimensions({ id, nodeElement, forceUpdate }) {
+ const i = this.nodes.map((x) => x.id).indexOf(id)
+ const node = this.nodes[i]
+ const dimensions = getDimensions(nodeElement)
+ const doUpdate =
+ dimensions.width &&
+ dimensions.height &&
+ (node.__rf.width !== dimensions.width || node.__rf.height !== dimensions.height || forceUpdate)
- if (doUpdate) {
- const handleBounds = getHandleBounds(update.nodeElement, this.transform[2])
+ if (doUpdate) {
+ const handleBounds = getHandleBounds(nodeElement, this.transform[2])
- return {
- ...node,
- __rf: {
- ...node.__rf,
- ...dimensions,
- handleBounds,
- },
- }
- }
- }
-
- return node
- })
+ this.nodes.splice(i, 1, {
+ ...node,
+ __rf: {
+ ...node.__rf,
+ ...dimensions,
+ handleBounds,
+ },
+ })
+ }
},
- updateNodePos(payload) {
- const { id, pos } = payload
- let position: XYPosition = pos
+ updateNodePos({ id, pos }) {
+ const i = this.nodes.map((x) => x.id).indexOf(id)
+ const node = this.nodes[i]
if (this.snapToGrid) {
const [gridSizeX, gridSizeY] = this.snapGrid
- position = {
+ pos = {
x: gridSizeX * Math.round(pos.x / gridSizeX),
y: gridSizeY * Math.round(pos.y / gridSizeY),
}
}
- this.nodes = this.nodes.map((node) => {
- if (node.id === id) {
- return {
- ...node,
- __rf: {
- ...node.__rf,
- position,
- },
- }
- }
-
- return node
+ this.nodes.splice(i, 1, {
+ ...node,
+ __rf: {
+ ...node.__rf,
+ position: pos,
+ },
})
},
- updateNodePosDiff(payload: NodeDiffUpdate) {
- const { id, diff, isDragging } = payload
+ updateNodePosDiff({ id, diff, isDragging }) {
+ const i = this.nodes.map((x) => x.id || this.selectedElements?.find((sNode) => sNode.id === id)).indexOf(id)
+ const node = this.nodes[i]
- this.nodes = this.nodes.map((node) => {
- if (id === node.id || this.selectedElements?.find((sNode) => sNode.id === node.id)) {
- const updatedNode = {
- ...node,
- __rf: {
- ...node.__rf,
- isDragging,
- },
- }
+ const updatedNode = {
+ ...node,
+ __rf: {
+ ...node.__rf,
+ isDragging,
+ },
+ }
- if (diff) {
- updatedNode.__rf.position = {
- x: node.__rf.position.x + diff.x,
- y: node.__rf.position.y + diff.y,
- }
- }
-
- return updatedNode
+ if (diff) {
+ updatedNode.__rf.position = {
+ x: node.__rf.position.x + diff.x,
+ y: node.__rf.position.y + diff.y,
}
+ }
- return node
+ this.nodes.splice(i, 1, {
+ ...node,
+ ...updatedNode,
})
},
setUserSelection(mousePos) {
@@ -198,26 +185,21 @@ export default function useFlowStore(preloadedState: FlowState): StoreDefinition
const selectedElementsUpdated = !isEqual(selectedElementsArr, this.selectedElements)
this.selectedElements = selectedElementsUpdated ? selectedElementsArr : this.selectedElements
},
- initD3Zoom(payload) {
- const { d3Zoom, d3Selection, d3ZoomHandler } = payload
-
+ initD3Zoom({ d3ZoomHandler, d3Zoom, d3Selection }) {
this.d3Zoom = d3Zoom
this.d3Selection = d3Selection
this.d3ZoomHandler = d3ZoomHandler
},
setMinZoom(minZoom) {
this.d3Zoom?.scaleExtent([minZoom, this.maxZoom])
-
this.minZoom = minZoom
},
setMaxZoom(maxZoom) {
this.d3Zoom?.scaleExtent([this.minZoom, maxZoom])
-
this.maxZoom = maxZoom
},
setTranslateExtent(translateExtent) {
this.d3Zoom?.translateExtent(translateExtent)
-
this.translateExtent = translateExtent
},
setNodeExtent(nodeExtent) {
@@ -241,10 +223,10 @@ export default function useFlowStore(preloadedState: FlowState): StoreDefinition
updateSize(size) {
this.dimensions = size
},
- setConnectionNodeId(payload) {
- this.connectionNodeId = payload.connectionNodeId
- this.connectionHandleId = payload.connectionHandleId
- this.connectionHandleType = payload.connectionHandleType
+ setConnectionNodeId({ connectionHandleId, connectionHandleType, connectionNodeId }) {
+ this.connectionNodeId = connectionNodeId
+ this.connectionHandleId = connectionHandleId
+ this.connectionHandleType = connectionHandleType
},
setInteractive(isInteractive) {
this.nodesDraggable = isInteractive
diff --git a/src/types/actions.ts b/src/types/actions.ts
index 85a11cb2..f1d8fdc2 100644
--- a/src/types/actions.ts
+++ b/src/types/actions.ts
@@ -5,7 +5,7 @@ import { SetConnectionId } from './connection'
export interface RevueFlowActions {
setElements: (elements: Elements) => void
- updateNodeDimensions: (updates: NodeDimensionUpdate[]) => void
+ updateNodeDimensions: (update: NodeDimensionUpdate) => void
updateNodePos: (payload: NodePosUpdate) => void
updateNodePosDiff: (payload: NodeDiffUpdate) => void
setUserSelection: (mousePos: XYPosition) => void