fix(app): file tree performance
This commit is contained in:
@@ -17,6 +17,11 @@ import {
|
|||||||
import { Dynamic } from "solid-js/web"
|
import { Dynamic } from "solid-js/web"
|
||||||
import type { FileNode } from "@opencode-ai/sdk/v2"
|
import type { FileNode } from "@opencode-ai/sdk/v2"
|
||||||
|
|
||||||
|
type Filter = {
|
||||||
|
files: Set<string>
|
||||||
|
dirs: Set<string>
|
||||||
|
}
|
||||||
|
|
||||||
export default function FileTree(props: {
|
export default function FileTree(props: {
|
||||||
path: string
|
path: string
|
||||||
class?: string
|
class?: string
|
||||||
@@ -27,26 +32,19 @@ export default function FileTree(props: {
|
|||||||
draggable?: boolean
|
draggable?: boolean
|
||||||
tooltip?: boolean
|
tooltip?: boolean
|
||||||
onFileClick?: (file: FileNode) => void
|
onFileClick?: (file: FileNode) => void
|
||||||
|
|
||||||
|
_filter?: Filter
|
||||||
|
_marks?: Set<string>
|
||||||
|
_deeps?: Map<string, number>
|
||||||
}) {
|
}) {
|
||||||
const file = useFile()
|
const file = useFile()
|
||||||
const level = props.level ?? 0
|
const level = props.level ?? 0
|
||||||
const draggable = () => props.draggable ?? true
|
const draggable = () => props.draggable ?? true
|
||||||
const tooltip = () => props.tooltip ?? true
|
const tooltip = () => props.tooltip ?? true
|
||||||
|
|
||||||
const maxOpen = (dir: string, lvl: number): number => {
|
|
||||||
const expanded = file.tree.state(dir)?.expanded ?? false
|
|
||||||
if (!expanded) return -1
|
|
||||||
|
|
||||||
const nodes = file.tree.children(dir)
|
|
||||||
const child = nodes.reduce((max, node) => {
|
|
||||||
if (node.type !== "directory") return max
|
|
||||||
return Math.max(max, maxOpen(node.path, lvl + 1))
|
|
||||||
}, -1)
|
|
||||||
|
|
||||||
return Math.max(lvl, child)
|
|
||||||
}
|
|
||||||
|
|
||||||
const filter = createMemo(() => {
|
const filter = createMemo(() => {
|
||||||
|
if (props._filter) return props._filter
|
||||||
|
|
||||||
const allowed = props.allowed
|
const allowed = props.allowed
|
||||||
if (!allowed) return
|
if (!allowed) return
|
||||||
|
|
||||||
@@ -66,11 +64,38 @@ export default function FileTree(props: {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const marks = createMemo(() => {
|
const marks = createMemo(() => {
|
||||||
|
if (props._marks) return props._marks
|
||||||
|
|
||||||
const modified = props.modified
|
const modified = props.modified
|
||||||
if (!modified || modified.length === 0) return
|
if (!modified || modified.length === 0) return
|
||||||
return new Set(modified)
|
return new Set(modified)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const deeps = createMemo(() => {
|
||||||
|
if (props._deeps) return props._deeps
|
||||||
|
|
||||||
|
const out = new Map<string, number>()
|
||||||
|
|
||||||
|
const visit = (dir: string, lvl: number): number => {
|
||||||
|
const expanded = file.tree.state(dir)?.expanded ?? false
|
||||||
|
if (!expanded) return -1
|
||||||
|
|
||||||
|
const nodes = file.tree.children(dir)
|
||||||
|
const max = nodes.reduce((max, node) => {
|
||||||
|
if (node.type !== "directory") return max
|
||||||
|
const open = file.tree.state(node.path)?.expanded ?? false
|
||||||
|
if (!open) return max
|
||||||
|
return Math.max(max, visit(node.path, lvl + 1))
|
||||||
|
}, lvl)
|
||||||
|
|
||||||
|
out.set(dir, max)
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
visit(props.path, level - 1)
|
||||||
|
return out
|
||||||
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const current = filter()
|
const current = filter()
|
||||||
if (!current) return
|
if (!current) return
|
||||||
@@ -84,7 +109,8 @@ export default function FileTree(props: {
|
|||||||
})
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
void file.tree.list(props.path)
|
const path = props.path
|
||||||
|
untrack(() => void file.tree.list(path))
|
||||||
})
|
})
|
||||||
|
|
||||||
const nodes = createMemo(() => {
|
const nodes = createMemo(() => {
|
||||||
@@ -165,7 +191,7 @@ export default function FileTree(props: {
|
|||||||
<For each={nodes()}>
|
<For each={nodes()}>
|
||||||
{(node) => {
|
{(node) => {
|
||||||
const expanded = () => file.tree.state(node.path)?.expanded ?? false
|
const expanded = () => file.tree.state(node.path)?.expanded ?? false
|
||||||
const deep = createMemo(() => (node.type === "directory" ? maxOpen(node.path, level) : -1))
|
const deep = () => deeps().get(node.path) ?? -1
|
||||||
const Wrapper = (p: ParentProps) => {
|
const Wrapper = (p: ParentProps) => {
|
||||||
if (!tooltip()) return p.children
|
if (!tooltip()) return p.children
|
||||||
return (
|
return (
|
||||||
@@ -212,6 +238,9 @@ export default function FileTree(props: {
|
|||||||
draggable={props.draggable}
|
draggable={props.draggable}
|
||||||
tooltip={props.tooltip}
|
tooltip={props.tooltip}
|
||||||
onFileClick={props.onFileClick}
|
onFileClick={props.onFileClick}
|
||||||
|
_filter={filter()}
|
||||||
|
_marks={marks()}
|
||||||
|
_deeps={deeps()}
|
||||||
/>
|
/>
|
||||||
</Collapsible.Content>
|
</Collapsible.Content>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
|
|||||||
Reference in New Issue
Block a user