@@ -4,9 +4,9 @@ import { FileTreeNode as RawFileTreeNode } from "../actions";
44import { ScrollArea , ScrollBar } from "@/components/ui/scroll-area" ;
55import React , { useCallback , useMemo , useState , useEffect , useRef } from "react" ;
66import { FileTreeItemComponent } from "./fileTreeItemComponent" ;
7- import { useBrowseNavigation } from "@/app/[domain]/browse/hooks/useBrowseNavigation" ;
7+ import { getBrowsePath } from "@/app/[domain]/browse/hooks/useBrowseNavigation" ;
88import { useBrowseParams } from "@/app/[domain]/browse/hooks/useBrowseParams" ;
9-
9+ import { useDomain } from "@/hooks/useDomain" ;
1010
1111export type FileTreeNode = Omit < RawFileTreeNode , 'children' > & {
1212 isCollapsed : boolean ;
@@ -41,8 +41,8 @@ interface PureFileTreePanelProps {
4141export const PureFileTreePanel = ( { tree : _tree , path } : PureFileTreePanelProps ) => {
4242 const [ tree , setTree ] = useState < FileTreeNode > ( buildCollapsibleTree ( _tree ) ) ;
4343 const scrollAreaRef = useRef < HTMLDivElement > ( null ) ;
44- const { navigateToPath } = useBrowseNavigation ( ) ;
4544 const { repoName, revisionName } = useBrowseParams ( ) ;
45+ const domain = useDomain ( ) ;
4646
4747 // @note : When `_tree` changes, it indicates that a new tree has been loaded.
4848 // In that case, we need to rebuild the collapsible tree.
@@ -72,35 +72,42 @@ export const PureFileTreePanel = ({ tree: _tree, path }: PureFileTreePanelProps)
7272 }
7373 } , [ path , setIsCollapsed ] ) ;
7474
75- const onNodeClicked = useCallback ( ( node : FileTreeNode ) => {
76- if ( node . type === 'tree' ) {
77- setIsCollapsed ( node . path , ! node . isCollapsed ) ;
78- }
79- else if ( node . type === 'blob' ) {
80- navigateToPath ( {
81- repoName : repoName ,
82- revisionName : revisionName ,
83- path : node . path ,
84- pathType : 'blob' ,
85- } ) ;
86-
87- }
88- } , [ setIsCollapsed , navigateToPath , repoName , revisionName ] ) ;
89-
9075 const renderTree = useCallback ( ( nodes : FileTreeNode , depth = 0 ) : React . ReactNode => {
9176 return (
9277 < >
9378 { nodes . children . map ( ( node ) => {
9479 return (
9580 < React . Fragment key = { node . path } >
9681 < FileTreeItemComponent
82+ href = { getBrowsePath ( {
83+ repoName,
84+ revisionName,
85+ path : node . path ,
86+ pathType : node . type === 'tree' ? 'tree' : 'blob' ,
87+ domain,
88+ } ) }
9789 key = { node . path }
9890 node = { node }
9991 isActive = { node . path === path }
10092 depth = { depth }
10193 isCollapsed = { node . isCollapsed }
10294 isCollapseChevronVisible = { node . type === 'tree' }
103- onClick = { ( ) => onNodeClicked ( node ) }
95+ // Only collapse the tree when a regular click happens.
96+ // (i.e., not ctrl/cmd click).
97+ onClick = { ( e ) => {
98+ const isMetaOrCtrlKey = e . metaKey || e . ctrlKey ;
99+ if ( node . type === 'tree' && ! isMetaOrCtrlKey ) {
100+ setIsCollapsed ( node . path , ! node . isCollapsed ) ;
101+ }
102+ } }
103+ // @note : onNavigate _won't_ be called when the user ctrl/cmd clicks on a tree node.
104+ // So when a regular click happens, we want to prevent the navigation from happening
105+ // and instead collapse the tree.
106+ onNavigate = { ( e ) => {
107+ if ( node . type === 'tree' ) {
108+ e . preventDefault ( ) ;
109+ }
110+ } }
104111 parentRef = { scrollAreaRef }
105112 />
106113 { node . children . length > 0 && ! node . isCollapsed && renderTree ( node , depth + 1 ) }
@@ -109,7 +116,7 @@ export const PureFileTreePanel = ({ tree: _tree, path }: PureFileTreePanelProps)
109116 } ) }
110117 </ >
111118 ) ;
112- } , [ path , onNodeClicked ] ) ;
119+ } , [ path ] ) ;
113120
114121 const renderedTree = useMemo ( ( ) => renderTree ( tree ) , [ tree , renderTree ] ) ;
115122
0 commit comments