diff --git a/src/components/FileExplorer.tsx b/src/components/FileExplorer.tsx index eea76a8..f0bbd6b 100644 --- a/src/components/FileExplorer.tsx +++ b/src/components/FileExplorer.tsx @@ -9,7 +9,7 @@ import { ConnectorState, Props } from 'driver/core/FileExplorer' import { platform } from 'platforms' import * as React from 'react' import { useEvent, usePrevious } from 'react-use' -import { FixedSizeList as List, ListChildComponentProps, ListProps } from 'react-window' +import { FixedSizeList, ListChildComponentProps } from 'react-window' import { cx } from 'utils/cx' import { isValidRegexpSource } from 'utils/general' import { useOnLocationChange } from 'utils/hooks/useOnLocationChange' @@ -17,10 +17,19 @@ import { VisibleNodes } from 'utils/VisibleNodesGenerator' import { Icon } from './Icon' import { SizeObserver } from './SizeObserver' -const VisibleNodesContext = React.createContext(null) - const RawFileExplorer: React.FC = function RawFileExplorer(props) { - const { state, visibleNodes, freeze, onNodeClick, searchKey } = props + const { + state, + visibleNodes, + freeze, + onNodeClick, + searchKey, + goTo, + metaData, + expandTo, + setUpTree, + treeRoot, + } = props const { val: { compressSingletonFolder }, } = useConfigs() @@ -33,111 +42,88 @@ const RawFileExplorer: React.FC = function RawFileExplor React.useEffect(() => { const { setUpTree, treeRoot, metaData } = props setUpTree({ treeRoot, metaData, compressSingletonFolder }) - }, [props.setUpTree, props.treeRoot, compressSingletonFolder]) + }, [setUpTree, treeRoot, compressSingletonFolder]) React.useEffect(() => { const { execAfterRender } = props execAfterRender() }) - const renderActions: React.ComponentProps['renderActions'] = React.useCallback( - node => - searchKey ? ( - - ) : null, - [searchKey, props.goTo], - ) - - const renderNode = React.useCallback( - ({ index, style }: ListChildComponentProps) => ( - - ), - [renderActions, onNodeClick, searchKey], - ) - - function renderFiles({ nodes, focusedNode }: VisibleNodes) { - const inSearch = searchKey !== '' - if (inSearch && nodes.length === 0) { - return ( - - No results found. - - ) - } + function renderFiles(visibleNodes: VisibleNodes) { + const inSearch = searchKey !== '' + const { nodes, focusedNode } = visibleNodes + if (inSearch && nodes.length === 0) { return ( - - {({ width = 0, height = 0 }) => ( - - )} - + + No results found. + ) + } + return ( + + {({ width = 0, height = 0 }) => ( + ( + + ) + : undefined + } + visibleNodes={visibleNodes} + expandTo={expandTo} + metaData={metaData} + /> + )} + + ) } - const revealNode = React.useCallback(function revealNode( - goTo: (path: string[]) => void, - node: TreeNode, - ): (event: React.MouseEvent) => void { - return e => { - e.stopPropagation() - e.preventDefault() - goTo(node.path.split('/')) - } - }, - []) - return ( - -
- {state !== 'done' ? ( - - ) : ( - visibleNodes && ( - <> - - {renderFiles(visibleNodes)} - - ) - )} -
-
+
+ {state !== 'done' ? ( + + ) : ( + visibleNodes && ( + <> + + {renderFiles(visibleNodes)} + + ) + )} +
) } @@ -150,21 +136,16 @@ RawFileExplorer.defaultProps = { export const FileExplorer = connect(FileExplorerCore)(RawFileExplorer) -function VirtualNode({ +const VirtualNode = React.memo(function VirtualNode({ index, style, - onNodeClick, - renderActions, - regex, -}: { - index: number - style: React.CSSProperties - onNodeClick: (treeNode: TreeNode) => void - renderActions: ((node: TreeNode) => React.ReactNode) | undefined - regex?: RegExp -}) { - const visibleNodes = React.useContext(VisibleNodesContext) + data, +}: ListChildComponentProps) { + const { searchKey, onNodeClick, renderActions, visibleNodes } = data + const regex = + searchKey && isValidRegexpSource(searchKey) ? new RegExp(searchKey, 'gi') : undefined if (!visibleNodes) return null + const { nodes, depths, focusedNode, expandedNodes } = visibleNodes const node = nodes[index] return ( @@ -180,25 +161,31 @@ function VirtualNode({ regex={regex} /> ) -} +}) function ListView({ nodes, width, height, focusedNode, - renderNode, metaData, expandTo, + searchKey, + onNodeClick, + renderActions, + visibleNodes, }: { nodes: TreeNode[] height: number width: number focusedNode: TreeNode | null - renderNode: ListProps['children'] + searchKey: string + onNodeClick(node: TreeNode): void + renderActions?(node: TreeNode): React.ReactNode + visibleNodes: VisibleNodes } & Pick & Pick) { - const listRef = React.useRef(null) + const listRef = React.useRef(null) React.useEffect(() => { if (focusedNode && listRef.current) { listRef.current.scrollToItem(nodes.indexOf(focusedNode), 'smart') @@ -218,20 +205,18 @@ function ListView({ }, [metaData.branchName]) useOnLocationChange(goToCurrentItem) useEvent('pjax:complete', goToCurrentItem, window) + return ( - { - const node = nodes[index] - return node && node.path - }} - itemData={{ nodes }} + itemKey={(index, { nodes = [] }) => nodes[index]?.path} + itemData={{ nodes, searchKey, onNodeClick, renderActions, visibleNodes }} itemCount={nodes.length} itemSize={36} height={height} width={width} > - {renderNode} - + {VirtualNode} + ) }