mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
refactor: prevent rendering multiple times on search
This commit is contained in:
parent
3203f9426e
commit
b0bcb7130c
4 changed files with 71 additions and 38 deletions
|
|
@ -42,9 +42,30 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
|
|||
if (visibleNodes?.focusedNode) focusFileExplorer()
|
||||
})
|
||||
|
||||
const renderActions: ((node: TreeNode) => React.ReactNode) | undefined = React.useMemo(
|
||||
() =>
|
||||
visibleNodes?.lastMatch?.match.searchKey
|
||||
? node => (
|
||||
<button
|
||||
title={'Reveal in file tree'}
|
||||
className={'go-to-button'}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
goTo(node.path.split('/'))
|
||||
}}
|
||||
>
|
||||
<Icon type="go-to" />
|
||||
</button>
|
||||
)
|
||||
: undefined,
|
||||
[visibleNodes, goTo],
|
||||
)
|
||||
|
||||
function renderFiles(visibleNodes: VisibleNodes) {
|
||||
const inSearch = searchKey !== ''
|
||||
const { nodes } = visibleNodes
|
||||
const searchKey = visibleNodes.lastMatch?.match.searchKey
|
||||
const inSearch = searchKey !== ''
|
||||
if (inSearch && nodes.length === 0) {
|
||||
return (
|
||||
<Text marginTop={6} textAlign="center" color="text.gray">
|
||||
|
|
@ -58,25 +79,8 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
|
|||
<ListView
|
||||
height={height}
|
||||
width={width}
|
||||
searchKey={searchKey}
|
||||
onNodeClick={onNodeClick}
|
||||
renderActions={
|
||||
searchKey
|
||||
? node => (
|
||||
<button
|
||||
title={'Reveal in file tree'}
|
||||
className={'go-to-button'}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
goTo(node.path.split('/'))
|
||||
}}
|
||||
>
|
||||
<Icon type="go-to" />
|
||||
</button>
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
renderActions={renderActions}
|
||||
visibleNodes={visibleNodes}
|
||||
expandTo={expandTo}
|
||||
metaData={metaData}
|
||||
|
|
@ -132,11 +136,19 @@ const VirtualNode = React.memo(function VirtualNode({
|
|||
style,
|
||||
data,
|
||||
}: ListChildComponentProps) {
|
||||
const { regex, onNodeClick, renderActions, visibleNodes } = data
|
||||
const { onNodeClick, renderActions, visibleNodes } = data
|
||||
if (!visibleNodes) return null
|
||||
|
||||
const { nodes, focusedNode, expandedNodes, loading, depths } = visibleNodes as VisibleNodes
|
||||
const {
|
||||
lastMatch,
|
||||
nodes,
|
||||
focusedNode,
|
||||
expandedNodes,
|
||||
loading,
|
||||
depths,
|
||||
} = visibleNodes as VisibleNodes
|
||||
const node = nodes[index]
|
||||
const searchKey = lastMatch?.match.searchKey
|
||||
return (
|
||||
<Node
|
||||
style={style}
|
||||
|
|
@ -148,7 +160,7 @@ const VirtualNode = React.memo(function VirtualNode({
|
|||
expanded={expandedNodes.has(node.path)}
|
||||
onClick={onNodeClick}
|
||||
renderActions={renderActions}
|
||||
regex={regex}
|
||||
regex={searchKey && isValidRegexpSource(searchKey) ? new RegExp(searchKey, 'gi') : undefined}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
|
@ -156,7 +168,6 @@ const VirtualNode = React.memo(function VirtualNode({
|
|||
type ListViewProps = {
|
||||
height: number
|
||||
width: number
|
||||
searchKey: string
|
||||
onNodeClick(event: React.MouseEvent<HTMLElement, MouseEvent>, node: TreeNode): void
|
||||
renderActions?(node: TreeNode): React.ReactNode
|
||||
visibleNodes: VisibleNodes
|
||||
|
|
@ -167,7 +178,6 @@ function ListView({
|
|||
height,
|
||||
metaData,
|
||||
expandTo,
|
||||
searchKey,
|
||||
onNodeClick,
|
||||
renderActions,
|
||||
visibleNodes,
|
||||
|
|
@ -193,12 +203,11 @@ function ListView({
|
|||
|
||||
const itemData = React.useMemo(
|
||||
() => ({
|
||||
regex: searchKey && isValidRegexpSource(searchKey) ? new RegExp(searchKey, 'gi') : undefined,
|
||||
onNodeClick,
|
||||
renderActions,
|
||||
visibleNodes,
|
||||
}),
|
||||
[searchKey, onNodeClick, renderActions, visibleNodes],
|
||||
[onNodeClick, renderActions, visibleNodes],
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -137,7 +137,12 @@ type Props = {
|
|||
onClick?: (event: React.MouseEvent<HTMLElement>) => void
|
||||
} & IconProps
|
||||
|
||||
export function Icon({ type, className = undefined, placeholder, ...otherProps }: Props) {
|
||||
export const Icon = React.memo(function Icon({
|
||||
type,
|
||||
className = undefined,
|
||||
placeholder,
|
||||
...otherProps
|
||||
}: Props) {
|
||||
let children: React.ReactNode = null
|
||||
if (!placeholder) {
|
||||
const { name, IconComponent } = getSVGIconComponent(type)
|
||||
|
|
@ -148,4 +153,4 @@ export function Icon({ type, className = undefined, placeholder, ...otherProps }
|
|||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { GetCreatedMethod, MethodCreator } from 'driver/connect'
|
|||
import { platform } from 'platforms'
|
||||
import { Config } from 'utils/configHelper'
|
||||
import * as DOMHelper from 'utils/DOMHelper'
|
||||
import { searchKeyToRegexp } from 'utils/general'
|
||||
import { VisibleNodes, VisibleNodesGenerator } from 'utils/VisibleNodesGenerator'
|
||||
|
||||
export type Props = {
|
||||
|
|
@ -182,8 +181,7 @@ export const onFocusSearchBar: BoundMethodCreator = dispatch => () => dispatch.c
|
|||
|
||||
export const search: BoundMethodCreator<[string]> = dispatch => searchKey => {
|
||||
dispatch.set({ searchKey, searched: searchKey !== '' })
|
||||
const regexp = searchKeyToRegexp(searchKey)
|
||||
visibleNodesGenerator.search(regexp && (node => regexp.test(node.name)))
|
||||
visibleNodesGenerator.search({ searchKey })
|
||||
}
|
||||
|
||||
export const goTo: BoundMethodCreator<[string[]]> = dispatch => currentPath => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { EventHub } from './EventHub'
|
||||
import { findNode, traverse, withEffect } from './general'
|
||||
import { findNode, searchKeyToRegexp, traverse, withEffect } from './general'
|
||||
|
||||
function search(
|
||||
root: TreeNode,
|
||||
|
|
@ -131,12 +131,27 @@ class ShakeLayer extends BaseLayer {
|
|||
}
|
||||
|
||||
shake = withEffect(
|
||||
(p?: { match: (node: TreeNode) => boolean; onChildMatch: (node: TreeNode) => void }) => {
|
||||
(p?: {
|
||||
match: {
|
||||
// shape in object for better extensibility
|
||||
searchKey: string
|
||||
}
|
||||
onChildMatch: (node: TreeNode) => void
|
||||
}) => {
|
||||
this.lastMatch = p
|
||||
if (p) {
|
||||
const { match, onChildMatch } = p
|
||||
this.shackedRoot = search(this.baseRoot, match, onChildMatch)
|
||||
} else this.shackedRoot = this.baseRoot
|
||||
const {
|
||||
match: { searchKey },
|
||||
onChildMatch,
|
||||
} = p
|
||||
|
||||
const regexp = searchKeyToRegexp(searchKey)
|
||||
if (regexp) {
|
||||
this.shackedRoot = search(this.baseRoot, node => regexp.test(node.name), onChildMatch)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.shackedRoot = this.baseRoot
|
||||
},
|
||||
() => this.shakeHub.emit('emit', this.shackedRoot),
|
||||
)
|
||||
|
|
@ -232,7 +247,7 @@ class FlattenLayer extends CompressLayer {
|
|||
|
||||
focusNode = (node: TreeNode | null) => {
|
||||
if (this.focusedNode !== node) {
|
||||
this.focusedNode = node
|
||||
this.focusedNode = node
|
||||
this.flattenHub.emit('emit', null)
|
||||
}
|
||||
}
|
||||
|
|
@ -284,7 +299,11 @@ class FlattenLayer extends CompressLayer {
|
|||
}
|
||||
}, this.generateVisibleNodes)
|
||||
|
||||
search = (match: ((node: TreeNode) => boolean) | null) => {
|
||||
search = (
|
||||
match: {
|
||||
searchKey: string
|
||||
} | null,
|
||||
) => {
|
||||
// this.focusNode(null)
|
||||
this.shake(
|
||||
match
|
||||
|
|
@ -305,6 +324,7 @@ type Options = {
|
|||
|
||||
export type VisibleNodes = {
|
||||
loading: BaseLayer['loading']
|
||||
lastMatch: ShakeLayer['lastMatch']
|
||||
depths: CompressLayer['depths']
|
||||
nodes: FlattenLayer['nodes']
|
||||
expandedNodes: FlattenLayer['expandedNodes']
|
||||
|
|
@ -333,6 +353,7 @@ export class VisibleNodesGenerator extends FlattenLayer {
|
|||
get visibleNodes(): VisibleNodes {
|
||||
return {
|
||||
nodes: this.nodes,
|
||||
lastMatch: this.lastMatch,
|
||||
depths: this.depths,
|
||||
expandedNodes: this.expandedNodes,
|
||||
focusedNode: this.focusedNode,
|
||||
|
|
|
|||
Loading…
Reference in a new issue