diff --git a/packages/ui/src/components/directory-browser-dialog.tsx b/packages/ui/src/components/directory-browser-dialog.tsx index ca52bb29..ba18fa55 100644 --- a/packages/ui/src/components/directory-browser-dialog.tsx +++ b/packages/ui/src/components/directory-browser-dialog.tsx @@ -67,6 +67,7 @@ const DirectoryBrowserDialog: Component = (props) = const [rootPath, setRootPath] = createSignal("") const [loading, setLoading] = createSignal(false) const [error, setError] = createSignal(null) + const [pathInput, setPathInput] = createSignal("") const [creatingFolder, setCreatingFolder] = createSignal(false) const [directoryChildren, setDirectoryChildren] = createSignal>(new Map()) const [loadingPaths, setLoadingPaths] = createSignal>(new Set()) @@ -77,10 +78,12 @@ const DirectoryBrowserDialog: Component = (props) = const inFlightRequests = new Map>() function resetState() { + setRootPath("") setDirectoryChildren(new Map()) setLoadingPaths(new Set()) setCurrentPathKey(null) setCurrentMetadata(null) + setPathInput("") metadataCache.clear() inFlightRequests.clear() setError(null) @@ -249,7 +252,36 @@ const DirectoryBrowserDialog: Component = (props) = return metadata.displayPath }) + createEffect(() => { + const absolutePath = currentAbsolutePath() + if (absolutePath) { + setPathInput(absolutePath) + } + }) + const canSelectCurrent = createMemo(() => Boolean(currentAbsolutePath())) + const canSubmitPath = createMemo(() => pathInput().trim().length > 0) + + async function handlePathSubmit() { + const target = pathInput().trim() + if (!target) { + return + } + await navigateTo(target) + } + + async function handleSelectCurrent() { + const target = pathInput().trim() + if (target && target !== currentAbsolutePath()) { + await navigateTo(target) + return + } + + const absolute = currentAbsolutePath() + if (absolute) { + props.onSelect(absolute) + } + } function handleEntrySelect(entry: FileSystemEntry) { const absolutePath = entry.absolutePath @@ -338,19 +370,26 @@ const DirectoryBrowserDialog: Component = (props) =
{t("directoryBrowser.currentFolder")} - {currentAbsolutePath()} + setPathInput(event.currentTarget.value)} + onKeyDown={(event) => { + if (event.key === "Enter") { + event.preventDefault() + void handlePathSubmit() + } + }} + spellcheck={false} + class="selector-input directory-browser-current-path" + />
diff --git a/packages/ui/src/components/folder-selection-view.tsx b/packages/ui/src/components/folder-selection-view.tsx index 90459ada..8bed96ff 100644 --- a/packages/ui/src/components/folder-selection-view.tsx +++ b/packages/ui/src/components/folder-selection-view.tsx @@ -58,6 +58,14 @@ const FolderSelectionView: Component = (props) => { const [isSavingServer, setIsSavingServer] = createSignal(false) const [connectingServerId, setConnectingServerId] = createSignal(null) const nativeDialogsAvailable = supportsNativeDialogs() + const prefersBuiltInFolderBrowser = () => { + if (!nativeDialogsAvailable || typeof navigator === "undefined") { + return false + } + + const platform = ((navigator as any).userAgentData?.platform as string | undefined) ?? navigator.platform ?? navigator.userAgent + return /win/i.test(platform) + } let recentListRef: HTMLDivElement | undefined type LanguageOption = { value: Locale; label: string } @@ -380,7 +388,7 @@ const FolderSelectionView: Component = (props) => { async function handleBrowse() { if (isLoading()) return setFocusMode("new") - if (nativeDialogsAvailable) { + if (nativeDialogsAvailable && !prefersBuiltInFolderBrowser()) { const fallbackPath = folders()[0]?.path const selected = await openNativeFolderDialog({ title: t("folderSelection.dialog.title"),