From 4293c749c487612c7ab1f6e1d1b59d71a9f5eaaf Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Tue, 11 Jun 2024 14:28:17 -0700 Subject: [PATCH] Only generate a preview image on first onPointerEnter event (#37) This resolves a noticeable delay when the first paint required generating multiple preview images --- frontend/faraday/lib/TileLayout.tsx | 36 ++++++++++++++++++----------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/frontend/faraday/lib/TileLayout.tsx b/frontend/faraday/lib/TileLayout.tsx index e42326ec3..0ce91b8fd 100644 --- a/frontend/faraday/lib/TileLayout.tsx +++ b/frontend/faraday/lib/TileLayout.tsx @@ -268,6 +268,13 @@ const TileNode = ({ useEffect(() => { if (isDragging) { console.log("drag start", layoutNode.id, layoutNode, dragItem); + if (previewRef.current) { + toPng(previewRef.current).then((url) => { + const img = new Image(); + img.src = url; + img.onload = () => dragPreview(img); + }); + } } }, [isDragging]); @@ -284,20 +291,20 @@ const TileNode = ({ ); }, []); - // Once the preview div is mounted, grab it and render a PNG, then register it with the DnD system. I noticed that if I call this immediately, it occasionally captures an empty HTMLElement. - // I found a hacky workaround of just adding a timeout so the capture doesn't happen until after the first paint. - useEffect( - debounce(() => { - if (previewRef.current) { - toPng(previewRef.current).then((url) => { - const img = new Image(); - img.src = url; - dragPreview(img); - }); - } - }, 50), - [previewRef] - ); + const [previewImageSet, setPreviewImageSet] = useState(false); + + // When a user first mouses over a node, generate a preview image and set it as the drag preview. + const generatePreviewImage = useCallback(() => { + console.log("generatePreviewImage", layoutNode.id); + if (!previewImageSet && previewRef.current) { + toPng(previewRef.current).then((url) => { + const img = new Image(); + img.src = url; + img.onload = () => dragPreview(img); + setPreviewImageSet(true); + }); + } + }, [previewRef, previewImageSet, dragPreview]); // Register the tile item as a draggable component useEffect(() => { @@ -328,6 +335,7 @@ const TileNode = ({ flexBasis: layoutNode.size, ...transform, }} + onPointerEnter={generatePreviewImage} > {leafContent} {preview}