feat: implement file browser context and dialog for directory selection

- Introduced a new FileBrowserProvider to manage file browsing state and functionality.
- Added FileBrowserDialog component for user interface to navigate and select directories.
- Updated Home component to utilize the file browser context and provide global access.
- Enhanced HttpApiClient to use the new file browser for directory and file selection.
- Implemented server-side route for browsing directories, including drive detection on Windows.
This commit is contained in:
Kacper
2025-12-12 19:20:32 +01:00
parent c079b3ef88
commit 0bb774375e
5 changed files with 415 additions and 7 deletions

View File

@@ -0,0 +1,68 @@
"use client";
import { createContext, useContext, useState, useCallback, type ReactNode } from "react";
import { FileBrowserDialog } from "@/components/dialogs/file-browser-dialog";
interface FileBrowserContextValue {
openFileBrowser: () => Promise<string | null>;
}
const FileBrowserContext = createContext<FileBrowserContextValue | null>(null);
export function FileBrowserProvider({ children }: { children: ReactNode }) {
const [isOpen, setIsOpen] = useState(false);
const [resolver, setResolver] = useState<((value: string | null) => void) | null>(null);
const openFileBrowser = useCallback((): Promise<string | null> => {
return new Promise((resolve) => {
setIsOpen(true);
setResolver(() => resolve);
});
}, []);
const handleSelect = useCallback((path: string) => {
if (resolver) {
resolver(path);
setResolver(null);
}
setIsOpen(false);
}, [resolver]);
const handleOpenChange = useCallback((open: boolean) => {
if (!open && resolver) {
resolver(null);
setResolver(null);
}
setIsOpen(open);
}, [resolver]);
return (
<FileBrowserContext.Provider value={{ openFileBrowser }}>
{children}
<FileBrowserDialog
open={isOpen}
onOpenChange={handleOpenChange}
onSelect={handleSelect}
/>
</FileBrowserContext.Provider>
);
}
export function useFileBrowser() {
const context = useContext(FileBrowserContext);
if (!context) {
throw new Error("useFileBrowser must be used within FileBrowserProvider");
}
return context;
}
// Global reference for non-React code (like HttpApiClient)
let globalFileBrowserFn: (() => Promise<string | null>) | null = null;
export function setGlobalFileBrowser(fn: () => Promise<string | null>) {
globalFileBrowserFn = fn;
}
export function getGlobalFileBrowser() {
return globalFileBrowserFn;
}