import { Text } from '@primer/components' import { LoadingIndicator } from 'components/LoadingIndicator' import { Node } from 'components/Node' import { SearchBar } from 'components/SearchBar' import { useConfigs } from 'containers/ConfigsContext' import { connect } from 'driver/connect' import { FileExplorerCore } from 'driver/core' import { ConnectorState, Props } from 'driver/core/FileExplorer' import { platform } from 'platforms' import * as React from 'react' import { FixedSizeList, ListChildComponentProps } from 'react-window' import { cx } from 'utils/cx' import { focusFileExplorer } from 'utils/DOMHelper' import { isValidRegexpSource } from 'utils/general' import { useOnLocationChange } from 'utils/hooks/useOnLocationChange' import { useOnPJAXDone } from 'utils/hooks/usePJAX' import { VisibleNodes } from 'utils/VisibleNodesGenerator' import { Icon } from './Icon' import { SizeObserver } from './SizeObserver' const RawFileExplorer: React.FC = function RawFileExplorer(props) { const { state, visibleNodes, freeze, onNodeClick, searchKey, goTo, metaData, expandTo, setUpTree, treeRoot, defer, } = props const { val: config } = useConfigs() React.useEffect(() => { const { setUpTree, treeRoot, metaData } = props setUpTree({ treeRoot, metaData, config }) }, [setUpTree, treeRoot, config.compressSingletonFolder, config.access_token]) React.useEffect(() => { if (visibleNodes?.focusedNode) focusFileExplorer() }) const renderActions: ((node: TreeNode) => React.ReactNode) | undefined = React.useMemo( () => visibleNodes?.lastMatch?.match.searchKey ? node => ( ) : undefined, [visibleNodes, goTo], ) return (
{state !== 'done' ? ( ) : ( visibleNodes && ( <> {visibleNodes.lastMatch?.match.searchKey !== '' && visibleNodes.nodes.length === 0 && ( <> No results found. {defer && ( Lazy mode is ON. Search results are limited to loaded folders. )} )} {({ width = 0, height = 0 }) => ( )} ) )}
) } RawFileExplorer.defaultProps = { freeze: false, state: 'pulling', searchKey: '', visibleNodes: null, } export const FileExplorer = connect(FileExplorerCore)(RawFileExplorer) const VirtualNode = React.memo(function VirtualNode({ index, style, data, }: ListChildComponentProps) { const { onNodeClick, renderActions, visibleNodes } = data if (!visibleNodes) return null const { lastMatch, nodes, focusedNode, expandedNodes, loading, depths, } = visibleNodes as VisibleNodes const node = nodes[index] const searchKey = lastMatch?.match.searchKey return ( ) }) type ListViewProps = { height: number width: number onNodeClick(event: React.MouseEvent, node: TreeNode): void renderActions?(node: TreeNode): React.ReactNode visibleNodes: VisibleNodes } function ListView({ width, height, metaData, expandTo, onNodeClick, renderActions, visibleNodes, }: ListViewProps & Pick & Pick) { const listRef = React.useRef(null) // the change of depths indicates switch into/from search state React.useEffect(() => { const { focusedNode, nodes } = visibleNodes if (listRef.current && focusedNode?.path) { const index = nodes.findIndex(node => node.path === focusedNode.path) if (index !== -1) { listRef.current.scrollToItem(index, 'smart') } } }, [visibleNodes]) // For some reason, removing the deps array above results in bug: // If scroll fast and far, then clicking on items would result in redirect // Not know the reason :( const goToCurrentItem = React.useCallback(() => { const targetPath = platform.getCurrentPath(metaData.branchName) if (targetPath) expandTo(targetPath) }, [metaData.branchName]) useOnLocationChange(goToCurrentItem) useOnPJAXDone(goToCurrentItem) const itemData = React.useMemo( () => ({ onNodeClick, renderActions, visibleNodes, }), [onNodeClick, renderActions, visibleNodes], ) return ( visibleNodes?.nodes[index]?.path} itemData={itemData} itemCount={visibleNodes.nodes.length} itemSize={36} height={height} width={width} > {VirtualNode} ) }