From 0d8163c45efacb9ffc521c56080ec7cd03d75726 Mon Sep 17 00:00:00 2001 From: Omkar Phansopkar Date: Sun, 3 Sep 2023 00:31:26 +0530 Subject: [PATCH] Fixed #590 scrolling irregularities in deeply nested filetree Signed-off-by: Omkar Phansopkar --- src/components/FileTree/FileTree.css | 2 +- src/components/FileTree/FileTree.tsx | 39 ++++++++++++++++++---------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/components/FileTree/FileTree.css b/src/components/FileTree/FileTree.css index 0209d71f..4d8d2d5b 100644 --- a/src/components/FileTree/FileTree.css +++ b/src/components/FileTree/FileTree.css @@ -18,7 +18,7 @@ } .filetree-node-wrapper { - scroll-margin-left: 150px; + scroll-margin-left: 50px; scroll-margin-top: 150px; scroll-margin-bottom: 150px; } diff --git a/src/components/FileTree/FileTree.tsx b/src/components/FileTree/FileTree.tsx index 3d60fa22..a2abd1ab 100644 --- a/src/components/FileTree/FileTree.tsx +++ b/src/components/FileTree/FileTree.tsx @@ -1,6 +1,6 @@ import RcTree from "rc-tree"; import { Key } from "rc-tree/lib/interface"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useLayoutEffect, useState } from "react"; import { Element } from "react-scroll"; import EllipticLoader from "../EllipticLoader"; @@ -10,6 +10,8 @@ import { FileDataNode } from "../../services/workbenchDB"; import "./FileTree.css"; +const FOCUS_ATTEMPT_DELAY = 500; + const FileTree = (props: React.HTMLProps) => { const { db, @@ -22,26 +24,38 @@ const FileTree = (props: React.HTMLProps) => { const [treeData, setTreeData] = useState(null); const [expandedKeys, setExpandedKeys] = useState([]); - useEffect(() => { + useLayoutEffect(() => { + if (currentPath.length === 0) return; + setExpandedKeys((keys) => { return [...keys, currentPath.substring(0, currentPath.lastIndexOf("/"))]; }); - if (currentPath.length) { - setTimeout(() => { - const targetNode = document.getElementsByName(currentPath)[0]; - if (targetNode) { + + // Timeout ensures that targetNode is accessed only after its rendered + let pendingTimeoutId: NodeJS.Timeout; + pendingTimeoutId = setTimeout(() => { + const targetNode = document.getElementsByName(currentPath)[0]; + if (targetNode) { + pendingTimeoutId = setTimeout(() => { targetNode.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "start", }); - } - }, 1500); - } + }, FOCUS_ATTEMPT_DELAY); + } + }); + + return () => { + clearTimeout(pendingTimeoutId); + }; }, [currentPath]); useEffect(() => { - if (!initialized || !db || !importedSqliteFilePath) return; + if (!initialized || !db || !importedSqliteFilePath) { + setTreeData(null); + return; + } db.findAllJSTree().then((treeData) => { // Wrap with react-scroll wrapper @@ -98,10 +112,7 @@ const FileTree = (props: React.HTMLProps) => { selectedKeys={[currentPath]} onSelect={(keys, info) => { if (keys && keys[0]) { - selectPath( - keys[0].toString(), - (info.node as any as FileDataNode).type as PathType - ); + selectPath(keys[0].toString(), info.node.type as PathType); } }} motion={{