From 8c68d41b51fb1eec09d46ef1be1ab894c75850b0 Mon Sep 17 00:00:00 2001 From: Max <5008@generative.xyz> Date: Wed, 11 Sep 2024 11:15:29 +0700 Subject: [PATCH] update dynamic edge --- src/modules/blockchains/Buy/getEdgeParams.ts | 142 ++++++++++-------- .../Buy/hooks/useLineIssueToken.ts | 15 +- 2 files changed, 90 insertions(+), 67 deletions(-) diff --git a/src/modules/blockchains/Buy/getEdgeParams.ts b/src/modules/blockchains/Buy/getEdgeParams.ts index 24a964db8..bed9896fb 100644 --- a/src/modules/blockchains/Buy/getEdgeParams.ts +++ b/src/modules/blockchains/Buy/getEdgeParams.ts @@ -1,82 +1,100 @@ -import { Position } from '@xyflow/react'; +import { Position, MarkerType } from '@xyflow/react'; -// returns the position (top,right,bottom or right) passed node compared to -function getParams(nodeA: any, nodeB: any) { - const centerA = getNodeCenter(nodeA); - const centerB = getNodeCenter(nodeB); +// this helper function returns the intersection point +// of the line between the center of the intersectionNode and the target node +function getNodeIntersection(intersectionNode: any, targetNode: any) { + // https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a + const { width: intersectionNodeWidth, height: intersectionNodeHeight } = + intersectionNode.measured; + const intersectionNodePosition = intersectionNode.internals.positionAbsolute; + const targetPosition = targetNode.internals.positionAbsolute; - const horizontalDiff = Math.abs(centerA.x - centerB.x); - const verticalDiff = Math.abs(centerA.y - centerB.y); + const w = intersectionNodeWidth / 2; + const h = intersectionNodeHeight / 2; - let position; + const x2 = intersectionNodePosition.x + w; + const y2 = intersectionNodePosition.y + h; + const x1 = targetPosition.x + targetNode.measured.width / 2; + const y1 = targetPosition.y + targetNode.measured.height / 2; - // when the horizontal difference between the nodes is bigger, we use Position.Left or Position.Right for the handle - if (horizontalDiff > verticalDiff) { - position = centerA.x > centerB.x ? Position.Left : Position.Right; - } else { - // here the vertical difference between the nodes is bigger, so we use Position.Top or Position.Bottom for the handle - position = centerA.y > centerB.y ? Position.Top : Position.Bottom; - } + const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h); + const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h); + const a = 1 / (Math.abs(xx1) + Math.abs(yy1)); + const xx3 = a * xx1; + const yy3 = a * yy1; + const x = w * (xx3 + yy3) + x2; + const y = h * (-xx3 + yy3) + y2; - const [x, y] = getHandleCoordsByPosition(nodeA, position); - return [x, y, position]; + return { x, y }; } -function getHandleCoordsByPosition(node: any, handlePosition: any) { - // all handles are from type source, that's why we use handleBounds.source here - const handle = node.internals.handleBounds.source.find( - (h: any) => h.position === handlePosition, - ); - console.log('nodegetHandleCoordsByPosition', node); - let offsetX = handle.width / 2; - let offsetY = handle.height / 2; +// returns the position (top,right,bottom or right) passed node compared to the intersection point +function getEdgePosition(node: any, intersectionPoint: any) { + const n = { ...node.internals.positionAbsolute, ...node }; + const nx = Math.round(n.x); + const ny = Math.round(n.y); + const px = Math.round(intersectionPoint.x); + const py = Math.round(intersectionPoint.y); - // this is a tiny detail to make the markerEnd of an edge visible. - // The handle position that gets calculated has the origin top-left, so depending which side we are using, we add a little offset - // when the handlePosition is Position.Right for example, we need to add an offset as big as the handle itself in order to get the correct position - switch (handlePosition) { - case Position.Left: - offsetX = 0; - console.log('Position Left'); - break; - case Position.Right: - offsetX = handle.width; - console.log('Position Right'); - break; - case Position.Top: - offsetY = 0; - console.log('Position Top'); - break; - case Position.Bottom: - console.log('Position Bottom'); - offsetY = handle.height; - break; + if (px <= nx + 1) { + return Position.Left; + } + if (px >= nx + n.measured.width - 1) { + return Position.Right; + } + if (py <= ny + 1) { + return Position.Top; + } + if (py >= n.y + n.measured.height - 1) { + return Position.Bottom; } - const x = node.internals.positionAbsolute.x + handle.x + offsetX; - const y = node.internals.positionAbsolute.y + handle.y + offsetY; - - return [x, y]; -} - -function getNodeCenter(node: any) { - return { - x: node.internals.positionAbsolute.x + node.measured.width / 2, - y: node.internals.positionAbsolute.y + node.measured.height / 2, - }; + return Position.Top; } // returns the parameters (sx, sy, tx, ty, sourcePos, targetPos) you need to create an edge export function getEdgeParams(source: any, target: any) { - const [sx, sy, sourcePos] = getParams(source, target); - const [tx, ty, targetPos] = getParams(target, source); + const sourceIntersectionPoint = getNodeIntersection(source, target); + const targetIntersectionPoint = getNodeIntersection(target, source); + + const sourcePos = getEdgePosition(source, sourceIntersectionPoint); + const targetPos = getEdgePosition(target, targetIntersectionPoint); return { - sx, - sy, - tx, - ty, + sx: sourceIntersectionPoint.x, + sy: sourceIntersectionPoint.y, + tx: targetIntersectionPoint.x, + ty: targetIntersectionPoint.y, sourcePos, targetPos, }; } + +// export function createNodesAndEdges() { +// const nodes = []; +// const edges = []; +// const center = { x: window.innerWidth / 2, y: window.innerHeight / 2 }; +// +// nodes.push({ id: 'target', data: { label: 'Target' }, position: center }); +// +// for (let i = 0; i < 8; i++) { +// const degrees = i * (360 / 8); +// const radians = degrees * (Math.PI / 180); +// const x = 250 * Math.cos(radians) + center.x; +// const y = 250 * Math.sin(radians) + center.y; +// +// nodes.push({ id: `${i}`, data: { label: 'Source' }, position: { x, y } }); +// +// edges.push({ +// id: `edge-${i}`, +// target: 'target', +// source: `${i}`, +// type: 'floating', +// markerEnd: { +// type: MarkerType.Arrow, +// }, +// }); +// } +// +// return { nodes, edges }; +// } diff --git a/src/modules/blockchains/Buy/hooks/useLineIssueToken.ts b/src/modules/blockchains/Buy/hooks/useLineIssueToken.ts index 43305a749..101f646b6 100644 --- a/src/modules/blockchains/Buy/hooks/useLineIssueToken.ts +++ b/src/modules/blockchains/Buy/hooks/useLineIssueToken.ts @@ -3,13 +3,16 @@ import useFlowStore from '@/modules/blockchains/Buy/stores/useFlowStore'; import { useParams } from 'next/navigation'; import { useAAModule } from '@/modules/blockchains/detail_v4/hook/useAAModule'; import { Edge, MarkerType } from '@xyflow/react'; +import { useChainProvider } from '@/modules/blockchains/detail_v4/provider/ChainProvider.hook'; +import handleStatusEdges from '@utils/helpers'; function useLineIssueToken(): void { const { nodes, edges, setEdges } = useFlowStore() const params = useParams(); const isUpdateFlow = React.useMemo(() => !!params.id, [params.id]); - const { aaInstalledData, } = useAAModule(); - + const { aaInstalledData } = useAAModule(); + const { getAAStatus } = useChainProvider(); + const { lineAAStatus } = useAAModule(); function addLineIssueToken() { if(nodes.length === 0) return; const newEdges: Edge[] = []; @@ -43,8 +46,10 @@ function useLineIssueToken(): void { target: node.id, sourceHandle: `${issueTokenNode.id}-s-account_abstraction`, targetHandle: `account_abstraction-t-${issueTokenNode.id}`, - label: '', - animated: false, + label: handleStatusEdges('', lineAAStatus, 'account_abstraction') + .icon, + animated: handleStatusEdges('', lineAAStatus, 'account_abstraction') + .animate, type: 'customEdge', selectable: false, selected: false, @@ -66,7 +71,7 @@ function useLineIssueToken(): void { // Airdrop Node // @ts-ignore - if(dataNode?.dapp?.id === 'airdrop' && tokenNameOfAirdrop?.options[0].key == tokenNameOfIssueToken?.value) { + if(dataNode?.dapp?.id === 'airdrop' && tokenNameOfAirdrop?.options[0].key == tokenNameOfIssueToken?.value && checkStatusNode(statusNode)) { dataNode.sourceHandles.push(`airdrop-t-${issueTokenNode.id}`); issueTokenNode.data.sourceHandles.push(`${issueTokenNode.id}-s-airdrop`) const issueTokenToAirdrop: Edge = {