diff --git a/bun.lock b/bun.lock index 4b927abdb..8a9ce9a96 100644 --- a/bun.lock +++ b/bun.lock @@ -914,6 +914,7 @@ ], "patchedDependencies": { "solid-js@1.9.10": "patches/solid-js@1.9.10.patch", + "@pierre/trees@1.0.0-beta.4": "patches/@pierre%2Ftrees@1.0.0-beta.4.patch", "virtua@0.49.1": "patches/virtua@0.49.1.patch", "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch", "gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch", @@ -923,7 +924,6 @@ "pacote@21.5.0": "patches/pacote@21.5.0.patch", "@npmcli/agent@4.0.2": "patches/@npmcli%2Fagent@4.0.2.patch", "@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch", - "@pierre/trees@1.0.0-beta.4": "patches/@pierre%2Ftrees@1.0.0-beta.4.patch", }, "overrides": { "@opentui/core": "catalog:", diff --git a/packages/app/src/components/dialog-select-directory-v2.tsx b/packages/app/src/components/dialog-select-directory-v2.tsx index 940e427ea..3971ac257 100644 --- a/packages/app/src/components/dialog-select-directory-v2.tsx +++ b/packages/app/src/components/dialog-select-directory-v2.tsx @@ -64,12 +64,21 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) { const missingBase = createMemo(() => !(sync.data.path.home || sync.data.path.directory)) const [fallbackPath] = createResource( () => (missingBase() ? true : undefined), - () => sdk.client.path.get().then((result) => result.data).catch(() => undefined), + () => + sdk.client.path + .get() + .then((result) => result.data) + .catch(() => undefined), { initialValue: undefined }, ) const home = createMemo(() => sync.data.path.home || fallbackPath()?.home || "") const start = createMemo( - () => props.start || sync.data.path.home || sync.data.path.directory || fallbackPath()?.home || fallbackPath()?.directory, + () => + props.start || + sync.data.path.home || + sync.data.path.directory || + fallbackPath()?.home || + fallbackPath()?.directory, ) const search = createDirectorySearch({ sdk, home, base: () => root() || start() }) const [suggestions] = createResource(input, async (value) => { @@ -111,9 +120,7 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) { if (!key) setError(true) return false } - tree?.batch( - policy.entries(key, nodes).map((item) => ({ type: "add", path: item })), - ) + tree?.batch(policy.entries(key, nodes).map((item) => ({ type: "add", path: item }))) if (preload && advanceTreePreload(advanced, key)) { void Promise.all(preloadTreeDirectories(key, nodes).map((directory) => load(directory, generation, false))) } @@ -147,9 +154,7 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) { const value = displayPickerPath(match.absolute, input(), home()) setInput(match.type === "directory" && !value.endsWith("/") ? value + "/" : value) if (match.type === "file") { - setSelected( - policy.selection(root(), pickerFileSearchQuery(root(), match.absolute, home())) ?? "", - ) + setSelected(policy.selection(root(), pickerFileSearchQuery(root(), match.absolute, home())) ?? "") setSuggestionsOpen(false) setActiveSuggestion(-1) } @@ -161,9 +166,7 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) { return } setInput(displayPickerPath(suggestion.absolute, input(), home())) - setSelected( - policy.selection(root(), pickerFileSearchQuery(root(), suggestion.absolute, home())) ?? "", - ) + setSelected(policy.selection(root(), pickerFileSearchQuery(root(), suggestion.absolute, home())) ?? "") setSuggestionsOpen(false) setActiveSuggestion(-1) } @@ -239,7 +242,7 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) { }, onSelectionChange(paths) { const path = paths.at(-1) - setSelected(path ? policy.selection(root(), path) ?? "" : "") + setSelected(path ? (policy.selection(root(), path) ?? "") : "") }, }) if (!container) return @@ -275,11 +278,15 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) { aria-autocomplete="list" aria-expanded={suggestionsOpen()} aria-controls="directory-picker-v2-suggestions" - aria-activedescendant={activeSuggestion() >= 0 ? `directory-picker-v2-suggestion-${activeSuggestion()}` : undefined} + aria-activedescendant={ + activeSuggestion() >= 0 ? `directory-picker-v2-suggestion-${activeSuggestion()}` : undefined + } onKeyDown={handleInputKey} />
- void navigate(home())}>~ + void navigate(home())}> + ~ + void navigate(pickerRoot(root()) || root())}> {language.t("dialog.directory.root")} @@ -315,14 +322,21 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) { ?.getFileTreeContainer() ?.shadowRoot?.querySelector("[data-file-tree-virtualized-scroll]") if (!scroller) return - const next = nextTreeScrollTop(scroller.scrollTop, event.deltaY, scroller.scrollHeight, scroller.clientHeight) + const next = nextTreeScrollTop( + scroller.scrollTop, + event.deltaY, + scroller.scrollHeight, + scroller.clientHeight, + ) if (next === scroller.scrollTop) return event.preventDefault() scroller.scrollTop = next scroller.dispatchEvent(new Event("scroll")) }} > -
{language.t("common.loading")}
+ +
{language.t("common.loading")}
+
{language.t("dialog.directory.readError")}
@@ -330,7 +344,9 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) {
{policy.result(root(), selected(), rootValid())}
- dialog.close()}>{language.t("common.cancel")} + dialog.close()}> + {language.t("common.cancel")} + {action[policy.action]} diff --git a/packages/app/src/components/directory-picker-domain.test.ts b/packages/app/src/components/directory-picker-domain.test.ts index c6888e9e1..d28344c93 100644 --- a/packages/app/src/components/directory-picker-domain.test.ts +++ b/packages/app/src/components/directory-picker-domain.test.ts @@ -86,9 +86,7 @@ test("preserves POSIX case while matching Windows drives case-insensitively", () expect(treePathWithin("/repo", "/Repo")).toBeFalse() expect(treePathWithin("C:/Repo", "c:/repo/src")).toBeTrue() expect(treePathWithin("//Server/Share/Repo", "//server/share/repo/src")).toBeTrue() - expect(pickerMode("file", "//Server/Share/Repo").selection("//server/share/repo/src", "file.ts")).toBe( - "src/file.ts", - ) + expect(pickerMode("file", "//Server/Share/Repo").selection("//server/share/repo/src", "file.ts")).toBe("src/file.ts") expect(treePathWithin("/repo", "/repo/../tmp")).toBeFalse() expect(treePathWithin("/", "/src")).toBeTrue() expect(pickerMode("file", "C:/Repo").selection("c:/repo/src", "file.ts")).toBe("src/file.ts") diff --git a/packages/app/src/components/directory-picker-domain.ts b/packages/app/src/components/directory-picker-domain.ts index af84e9ae9..2faa8cb2e 100644 --- a/packages/app/src/components/directory-picker-domain.ts +++ b/packages/app/src/components/directory-picker-domain.ts @@ -64,7 +64,10 @@ export function pickerMode(mode: "directory" | "file", base?: string) { } export function pickerFileSearchQuery(root: string, input: string, home: string) { - const value = input.replace(/\\/g, "/").replace(/^~(?=\/|$)/, home).replace(/\/+$/, "") + const value = input + .replace(/\\/g, "/") + .replace(/^~(?=\/|$)/, home) + .replace(/\/+$/, "") const base = root.replace(/\\/g, "/").replace(/\/+$/, "") if (value === base) return "" if (value.startsWith(base + "/")) return value.slice(base.length + 1) @@ -110,10 +113,7 @@ export function pickerRelativePath(base: string | undefined, path: string) { return targetPath.slice(prefix.length) } -export function currentPickerSuggestions( - result: { query: string; items: readonly T[] } | undefined, - query: string, -) { +export function currentPickerSuggestions(result: { query: string; items: readonly T[] } | undefined, query: string) { if (result?.query !== query) return [] return result.items }