summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/components
diff options
context:
space:
mode:
authoradamelmore <[email protected]>2026-01-25 21:57:30 -0600
committeradamelmore <[email protected]>2026-01-26 11:07:51 -0600
commitebeed03115b61f812c56c66785a09be61be35468 (patch)
tree8838b6a7a3533c9783e6f7bdd03e1b1795fa8a2a /packages/app/src/components
parentd9eed4c6cacf59089e6b6d6101deff58c7bd5040 (diff)
downloadopencode-ebeed03115b61f812c56c66785a09be61be35468.tar.gz
opencode-ebeed03115b61f812c56c66785a09be61be35468.zip
wip(app): file tree mode
Diffstat (limited to 'packages/app/src/components')
-rw-r--r--packages/app/src/components/file-tree.tsx50
1 files changed, 47 insertions, 3 deletions
diff --git a/packages/app/src/components/file-tree.tsx b/packages/app/src/components/file-tree.tsx
index 791b33b4a..ac435095d 100644
--- a/packages/app/src/components/file-tree.tsx
+++ b/packages/app/src/components/file-tree.tsx
@@ -2,7 +2,16 @@ import { useFile } from "@/context/file"
import { Collapsible } from "@opencode-ai/ui/collapsible"
import { FileIcon } from "@opencode-ai/ui/file-icon"
import { Tooltip } from "@opencode-ai/ui/tooltip"
-import { createEffect, For, Match, splitProps, Switch, type ComponentProps, type ParentProps } from "solid-js"
+import {
+ createEffect,
+ createMemo,
+ For,
+ Match,
+ splitProps,
+ Switch,
+ type ComponentProps,
+ type ParentProps,
+} from "solid-js"
import { Dynamic } from "solid-js/web"
import type { FileNode } from "@opencode-ai/sdk/v2"
@@ -11,15 +20,45 @@ export default function FileTree(props: {
class?: string
nodeClass?: string
level?: number
+ allowed?: readonly string[]
onFileClick?: (file: FileNode) => void
}) {
const file = useFile()
const level = props.level ?? 0
+ const filter = createMemo(() => {
+ const allowed = props.allowed
+ if (!allowed) return
+
+ const files = new Set(allowed)
+ const dirs = new Set<string>()
+
+ for (const item of allowed) {
+ const parts = item.split("/")
+ const parents = parts.slice(0, -1)
+ for (const [idx] of parents.entries()) {
+ const dir = parents.slice(0, idx + 1).join("/")
+ if (dir) dirs.add(dir)
+ }
+ }
+
+ return { files, dirs }
+ })
+
createEffect(() => {
void file.tree.list(props.path)
})
+ const nodes = createMemo(() => {
+ const nodes = file.tree.children(props.path)
+ const current = filter()
+ if (!current) return nodes
+ return nodes.filter((node) => {
+ if (node.type === "file") return current.files.has(node.path)
+ return current.dirs.has(node.path)
+ })
+ })
+
const Node = (
p: ParentProps &
ComponentProps<"div"> &
@@ -81,7 +120,7 @@ export default function FileTree(props: {
return (
<div class={`flex flex-col ${props.class ?? ""}`}>
- <For each={file.tree.children(props.path)}>
+ <For each={nodes()}>
{(node) => {
const expanded = () => file.tree.state(node.path)?.expanded ?? false
return (
@@ -102,7 +141,12 @@ export default function FileTree(props: {
</Node>
</Collapsible.Trigger>
<Collapsible.Content>
- <FileTree path={node.path} level={level + 1} onFileClick={props.onFileClick} />
+ <FileTree
+ path={node.path}
+ level={level + 1}
+ allowed={props.allowed}
+ onFileClick={props.onFileClick}
+ />
</Collapsible.Content>
</Collapsible>
</Match>