feat: focus item on redirect

This commit is contained in:
EnixCoda 2019-12-19 21:55:22 +08:00
parent 4419d02815
commit 6f86fd5b2d
No known key found for this signature in database
GPG key ID: 0C1A07377913A1DD
2 changed files with 29 additions and 11 deletions

View file

@ -6,9 +6,11 @@ import { connect } from 'driver/connect'
import { FileExplorerCore } from 'driver/core'
import { ConnectorState, Props } from 'driver/core/FileExplorer'
import * as React from 'react'
import { useEvent } from 'react-use'
import { FixedSizeList as List, ListChildComponentProps, ListProps } from 'react-window'
import { cx } from 'utils/cx'
import { usePrevious } from 'utils/hooks'
import { useOnLocationChange, usePrevious } from 'utils/hooks'
import { getCurrentPath } from 'utils/URLHelper'
import { TreeNode, VisibleNodes } from 'utils/VisibleNodesGenerator'
import { Icon } from './Icon'
import { SizeObserver } from './SizeObserver'
@ -77,6 +79,8 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
nodes={nodes}
height={height}
width={width}
expandTo={props.expandTo}
metaData={props.metaData}
/>
)}
</SizeObserver>
@ -167,13 +171,16 @@ function ListView({
height,
focusedNode,
renderNode,
metaData,
expandTo,
}: {
nodes: TreeNode[]
height: number
width: number
focusedNode: TreeNode | null
renderNode: ListProps['children']
}) {
} & Pick<Props, 'metaData'> &
Pick<ConnectorState, 'expandTo'>) {
const listRef = React.useRef<List>(null)
React.useEffect(() => {
if (focusedNode && listRef.current) {
@ -187,6 +194,12 @@ function ListView({
listRef.current.scrollTo(0)
}
}, [listRef.current, focusedNode, nodes.length])
const goToCurrentItem = React.useCallback(() => {
expandTo(getCurrentPath(metaData.branchName))
}, [metaData.branchName])
useOnLocationChange(goToCurrentItem)
useEvent('pjax:complete', goToCurrentItem, window)
return (
<List
ref={listRef}

View file

@ -32,6 +32,7 @@ export type ConnectorState = {
onFocusSearchBar: GetCreatedMethod<typeof onFocusSearchBar>
setUpTree: GetCreatedMethod<typeof setUpTree>
goTo: GetCreatedMethod<typeof goTo>
expandTo: GetCreatedMethod<typeof expandTo>
}
type DepthMap = Map<TreeNode, number>
@ -53,7 +54,7 @@ function getVisibleParentNode(nodes: TreeNode[], focusedNode: TreeNode, depths:
}
type Task = () => void
const tasksAfterRender: (Task)[] = []
const tasksAfterRender: Task[] = []
let visibleNodesGenerator: VisibleNodesGenerator
type BoundMethodCreator<Args extends any[] = []> = MethodCreator<Props, ConnectorState, Args>
@ -136,9 +137,9 @@ function handleParsed(root: TreeNode, parsed: Parsed) {
})
}
export const setUpTree: BoundMethodCreator<
[Pick<Props, 'treeData' | 'metaData' | 'accessToken'> & Pick<Config, 'compressSingletonFolder'>]
> = dispatch => async ({ treeData, metaData, compressSingletonFolder, accessToken }) => {
export const setUpTree: BoundMethodCreator<[
Pick<Props, 'treeData' | 'metaData' | 'accessToken'> & Pick<Config, 'compressSingletonFolder'>,
]> = dispatch => async ({ treeData, metaData, compressSingletonFolder, accessToken }) => {
if (!treeData) return
dispatch.call(setStateText, 'Rendering File List...')
const { root, gitModules } = treeParser.parse(treeData, metaData)
@ -299,11 +300,7 @@ export const search: BoundMethodCreator<[string]> = dispatch => searchKey => {
export const goTo: BoundMethodCreator<[string[]]> = dispatch => async currentPath => {
visibleNodesGenerator.search([])
tasksAfterRender.push(() => {
const nodeExpandedTo = visibleNodesGenerator.expandTo(currentPath.join('/'))
if (nodeExpandedTo) {
visibleNodesGenerator.focusNode(nodeExpandedTo)
}
dispatch.call(updateVisibleNodes)
dispatch.call(expandTo, currentPath)
})
dispatch.set({ searchKey: '', searched: false })
}
@ -347,6 +344,14 @@ export const onNodeClick: BoundMethodCreator<[TreeNode]> = dispatch => node => {
}
}
export const expandTo: BoundMethodCreator<[string[]]> = dispatch => currentPath => {
const nodeExpandedTo = visibleNodesGenerator.expandTo(currentPath.join('/'))
if (nodeExpandedTo) {
visibleNodesGenerator.focusNode(nodeExpandedTo)
}
dispatch.call(updateVisibleNodes)
}
export const updateVisibleNodes: BoundMethodCreator = dispatch => () => {
const { visibleNodes } = visibleNodesGenerator
dispatch.set({ visibleNodes })