2
0

perf(editor): ️ Improve graph transition perf

This commit is contained in:
Baptiste Arnaud
2022-02-14 18:56:29 +01:00
parent e7d1f5d674
commit 714f7c8ce5
9 changed files with 61 additions and 42 deletions

View File

@@ -59,7 +59,6 @@ export const PreviewDrawer = () => {
useEffect(() => {
const onMessageFromBot = (event: MessageEvent) => {
console.log(event)
if (event.data.typebotInfo) {
toast({ description: event.data.typebotInfo })
}

View File

@@ -18,6 +18,7 @@ export const DrawingEdge = () => {
sourceEndpoints,
targetEndpoints,
blocksCoordinates,
graphOffsetY,
} = useGraph()
const { createEdge } = useTypebot()
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 })
@@ -30,22 +31,20 @@ export const DrawingEdge = () => {
const sourceTop = useMemo(() => {
if (!connectingIds) return 0
return getEndpointTopOffset(
graphPosition,
sourceEndpoints,
graphOffsetY,
connectingIds.source.itemId ?? connectingIds.source.stepId
)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [graphPosition, sourceEndpoints, connectingIds])
}, [connectingIds, sourceEndpoints, graphOffsetY])
const targetTop = useMemo(() => {
if (!connectingIds) return 0
return getEndpointTopOffset(
graphPosition,
targetEndpoints,
graphOffsetY,
connectingIds.target?.stepId
)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [graphPosition, targetEndpoints, connectingIds])
}, [connectingIds, targetEndpoints, graphOffsetY])
const path = useMemo(() => {
if (!sourceTop || !sourceBlockCoordinates) return ``

View File

@@ -24,7 +24,7 @@ export const DropOffEdge = ({
onUnlockProPlanClick,
}: Props) => {
const { user } = useUser()
const { sourceEndpoints, graphPosition, blocksCoordinates } = useGraph()
const { sourceEndpoints, blocksCoordinates, graphOffsetY } = useGraph()
const { publishedTypebot } = useTypebot()
const isUserOnFreePlan = isFreePlan(user)
@@ -59,13 +59,12 @@ export const DropOffEdge = ({
const sourceTop = useMemo(
() =>
getEndpointTopOffset(
graphPosition,
sourceEndpoints,
block?.steps[block.steps.length - 1].id,
true
graphOffsetY,
block?.steps[block.steps.length - 1].id
),
// eslint-disable-next-line react-hooks/exhaustive-deps
[block?.steps, graphPosition, sourceEndpoints, blocksCoordinates]
[block?.steps, sourceEndpoints, blocksCoordinates]
)
const labelCoordinates = useMemo(() => {

View File

@@ -20,9 +20,8 @@ export const Edge = ({ edge }: { edge: EdgeProps }) => {
previewingEdge,
sourceEndpoints,
targetEndpoints,
graphPosition,
blocksCoordinates,
isReadOnly,
graphOffsetY,
} = useGraph()
const isPreviewing = previewingEdge?.id === edge.id
@@ -34,25 +33,27 @@ export const Edge = ({ edge }: { edge: EdgeProps }) => {
const sourceTop = useMemo(
() =>
getEndpointTopOffset(
graphPosition,
sourceEndpoints,
getSourceEndpointId(edge),
isReadOnly
graphOffsetY,
getSourceEndpointId(edge)
),
// eslint-disable-next-line react-hooks/exhaustive-deps
[edge, graphPosition, sourceEndpoints, sourceBlockCoordinates?.y]
[
sourceBlockCoordinates?.x,
sourceBlockCoordinates?.y,
edge,
sourceEndpoints,
]
)
const targetTop = useMemo(
() =>
getEndpointTopOffset(
graphPosition,
targetEndpoints,
edge?.to.stepId,
isReadOnly
),
() => getEndpointTopOffset(targetEndpoints, graphOffsetY, edge?.to.stepId),
// eslint-disable-next-line react-hooks/exhaustive-deps
[graphPosition, targetEndpoints, edge?.to.stepId, targetBlockCoordinates?.y]
[
targetBlockCoordinates?.x,
targetBlockCoordinates?.y,
edge?.to.stepId,
targetEndpoints,
]
)
const path = useMemo(() => {

View File

@@ -24,6 +24,8 @@ export const Edges = ({
pos="absolute"
left="0"
top="0"
pointerEvents="none"
shape-rendering="geometricPrecision"
>
<DrawingEdge />
{edges.map((edge) => (

View File

@@ -9,6 +9,7 @@ import { headerHeight } from 'components/shared/TypebotHeader/TypebotHeader'
import { Block, DraggableStepType, PublicTypebot, Typebot } from 'models'
import { generate } from 'short-uuid'
import { AnswersCount } from 'services/analytics'
import { useDebounce } from 'use-debounce'
export const Graph = ({
typebot,
@@ -30,7 +31,9 @@ export const Graph = ({
setGraphPosition,
setOpenedStepId,
updateBlockCoordinates,
setGraphOffsetY,
} = useGraph()
const [debouncedGraphPosition] = useDebounce(graphPosition, 200)
const transform = useMemo(
() =>
`translate(${graphPosition.x}px, ${graphPosition.y}px) scale(${graphPosition.scale})`,
@@ -42,8 +45,18 @@ export const Graph = ({
editorContainerRef.current = document.getElementById(
'editor-container'
) as HTMLDivElement
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
useEffect(() => {
if (!graphContainerRef.current) return
setGraphOffsetY(
graphContainerRef.current.getBoundingClientRect().top +
debouncedGraphPosition.y
)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [debouncedGraphPosition])
const handleMouseWheel = (e: WheelEvent) => {
e.preventDefault()
const isPinchingTrackpad = e.ctrlKey
@@ -112,15 +125,19 @@ export const Graph = ({
ref={graphContainerRef}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
position="relative"
{...props}
>
<Flex
flex="1"
boxSize={'200px'}
maxW={'200px'}
w="full"
h="full"
position="absolute"
style={{
transform,
}}
willChange="transform"
transformOrigin="0px 0px 0px"
>
<Edges
edges={typebot?.edges ?? []}

View File

@@ -41,7 +41,7 @@ export type Node = Omit<Block, 'steps'> & {
})[]
}
const graphPositionDefaultValue = { x: 400, y: 100, scale: 1 }
export const graphPositionDefaultValue = { x: 400, y: 100, scale: 1 }
export type ConnectingIds = {
source: Source
@@ -73,6 +73,8 @@ const graphContext = createContext<{
openedStepId?: string
setOpenedStepId: Dispatch<SetStateAction<string | undefined>>
isReadOnly: boolean
graphOffsetY: number
setGraphOffsetY: Dispatch<SetStateAction<number>>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
}>({
@@ -98,6 +100,7 @@ export const GraphProvider = ({
const [blocksCoordinates, setBlocksCoordinates] = useState<BlocksCoordinates>(
{}
)
const [graphOffsetY, setGraphOffsetY] = useState(0)
useEffect(() => {
setBlocksCoordinates(
@@ -150,6 +153,8 @@ export const GraphProvider = ({
blocksCoordinates,
updateBlockCoordinates,
isReadOnly,
graphOffsetY,
setGraphOffsetY,
}}
>
{children}

View File

@@ -8,7 +8,6 @@ import {
Coordinates,
} from 'contexts/GraphContext'
import { roundCorners } from 'svg-round-corners'
import { headerHeight } from 'components/shared/TypebotHeader'
export const computeDropOffPath = (
sourcePosition: Coordinates,
@@ -274,20 +273,18 @@ export const computeEdgePathToMouse = ({
}
export const getEndpointTopOffset = (
graphPosition: Coordinates,
endpoints: IdMap<Endpoint>,
endpointId?: string,
isAnalytics?: boolean
graphOffsetY: number,
endpointId?: string
): number | undefined => {
if (!endpointId) return
const endpointRef = endpoints[endpointId]?.ref
if (!endpointRef) return
if (!endpointRef?.current) return
const endpointHeight = 18
return (
8 +
(endpointRef.current?.getBoundingClientRect().top ?? 0) -
graphPosition.y -
headerHeight -
(isAnalytics ? 60 : 0)
endpointRef.current.getBoundingClientRect().top +
endpointHeight / 2 -
graphOffsetY
)
}