import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" import { FileIcon } from "@opencode-ai/ui/file-icon" import { List } from "@opencode-ai/ui/list" import { getDirectory, getFilename } from "@opencode-ai/util/path" import { createMemo } from "solid-js" import { useGlobalSDK } from "@/context/global-sdk" import { useGlobalSync } from "@/context/global-sync" interface DialogSelectDirectoryProps { title?: string multiple?: boolean onSelect: (result: string | string[] | null) => void } export function DialogSelectDirectory(props: DialogSelectDirectoryProps) { const sync = useGlobalSync() const sdk = useGlobalSDK() const dialog = useDialog() const home = createMemo(() => sync.data.path.home) const root = createMemo(() => sync.data.path.home || sync.data.path.directory) function join(base: string | undefined, rel: string) { const b = (base ?? "").replace(/[\\/]+$/, "") const r = rel.replace(/^[\\/]+/, "").replace(/[\\/]+$/, "") if (!b) return r if (!r) return b return b + "/" + r } function display(rel: string) { const full = join(root(), rel) const h = home() if (!h) return full if (full === h) return "~" if (full.startsWith(h + "/") || full.startsWith(h + "\\")) { return "~" + full.slice(h.length) } return full } function normalizeQuery(query: string) { const h = home() if (!query) return query if (query.startsWith("~/")) return query.slice(2) if (h) { const lc = query.toLowerCase() const hc = h.toLowerCase() if (lc === hc || lc.startsWith(hc + "/") || lc.startsWith(hc + "\\")) { return query.slice(h.length).replace(/^[\\/]+/, "") } } return query } async function fetchDirs(query: string) { const directory = root() if (!directory) return [] as string[] const results = await sdk.client.find .files({ directory, query, type: "directory", limit: 50 }) .then((x) => x.data ?? []) .catch(() => []) return results.map((x) => x.replace(/[\\/]+$/, "")) } const directories = async (filter: string) => { const query = normalizeQuery(filter.trim()) return fetchDirs(query) } function resolve(rel: string) { const absolute = join(root(), rel) props.onSelect(props.multiple ? [absolute] : absolute) dialog.close() } return ( x} onSelect={(path) => { if (!path) return resolve(path) }} > {(rel) => { const path = display(rel) return (
{getDirectory(path)} {getFilename(path)}
) }}
) }