url and history
This commit is contained in:
@@ -48,6 +48,32 @@ type ContextMenuState = {
|
||||
y: number;
|
||||
};
|
||||
|
||||
function readSidebarSelectionFromUrl(): SidebarSelection | null {
|
||||
if (typeof window === "undefined") return null;
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const chatId = params.get("chat")?.trim();
|
||||
if (chatId) {
|
||||
return { kind: "chat", id: chatId };
|
||||
}
|
||||
const searchId = params.get("search")?.trim();
|
||||
if (searchId) {
|
||||
return { kind: "search", id: searchId };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function buildWorkspaceUrl(selection: SidebarSelection | null) {
|
||||
if (typeof window === "undefined") return "/";
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
params.delete("chat");
|
||||
params.delete("search");
|
||||
if (selection) {
|
||||
params.set(selection.kind === "chat" ? "chat" : "search", selection.id);
|
||||
}
|
||||
const query = params.toString();
|
||||
return `${window.location.pathname}${query ? `?${query}` : ""}`;
|
||||
}
|
||||
|
||||
const PROVIDER_FALLBACK_MODELS: Record<Provider, string[]> = {
|
||||
openai: ["gpt-4.1-mini"],
|
||||
anthropic: ["claude-3-5-sonnet-latest"],
|
||||
@@ -302,6 +328,8 @@ export default function App() {
|
||||
const searchRunCounterRef = useRef(0);
|
||||
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
|
||||
const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
|
||||
const initialRouteSelectionRef = useRef<SidebarSelection | null>(readSidebarSelectionFromUrl());
|
||||
const hasSyncedSelectionHistoryRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof document === "undefined") return;
|
||||
@@ -417,9 +445,43 @@ export default function App() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) return;
|
||||
void Promise.all([refreshCollections(), refreshModels()]);
|
||||
const preferredSelection = initialRouteSelectionRef.current;
|
||||
initialRouteSelectionRef.current = null;
|
||||
void Promise.all([refreshCollections(preferredSelection ?? undefined), refreshModels()]);
|
||||
}, [isAuthenticated]);
|
||||
|
||||
useEffect(() => {
|
||||
const onPopState = () => {
|
||||
setContextMenu(null);
|
||||
setDraftKind(null);
|
||||
setSelectedItem(readSidebarSelectionFromUrl());
|
||||
setIsMobileSidebarOpen(false);
|
||||
};
|
||||
window.addEventListener("popstate", onPopState);
|
||||
return () => window.removeEventListener("popstate", onPopState);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) {
|
||||
hasSyncedSelectionHistoryRef.current = false;
|
||||
return;
|
||||
}
|
||||
const current = `${window.location.pathname}${window.location.search}`;
|
||||
const next = buildWorkspaceUrl(selectedItem);
|
||||
|
||||
if (!hasSyncedSelectionHistoryRef.current) {
|
||||
hasSyncedSelectionHistoryRef.current = true;
|
||||
if (current !== next) {
|
||||
window.history.replaceState({}, "", next);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (current !== next) {
|
||||
window.history.pushState({}, "", next);
|
||||
}
|
||||
}, [isAuthenticated, selectedItem]);
|
||||
|
||||
const providerModelOptions = useMemo(() => getModelOptions(modelCatalog, provider), [modelCatalog, provider]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user