url and history
This commit is contained in:
@@ -48,6 +48,32 @@ type ContextMenuState = {
|
|||||||
y: number;
|
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[]> = {
|
const PROVIDER_FALLBACK_MODELS: Record<Provider, string[]> = {
|
||||||
openai: ["gpt-4.1-mini"],
|
openai: ["gpt-4.1-mini"],
|
||||||
anthropic: ["claude-3-5-sonnet-latest"],
|
anthropic: ["claude-3-5-sonnet-latest"],
|
||||||
@@ -302,6 +328,8 @@ export default function App() {
|
|||||||
const searchRunCounterRef = useRef(0);
|
const searchRunCounterRef = useRef(0);
|
||||||
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
|
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
|
||||||
const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
|
const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
|
||||||
|
const initialRouteSelectionRef = useRef<SidebarSelection | null>(readSidebarSelectionFromUrl());
|
||||||
|
const hasSyncedSelectionHistoryRef = useRef(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof document === "undefined") return;
|
if (typeof document === "undefined") return;
|
||||||
@@ -417,9 +445,43 @@ export default function App() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isAuthenticated) return;
|
if (!isAuthenticated) return;
|
||||||
void Promise.all([refreshCollections(), refreshModels()]);
|
const preferredSelection = initialRouteSelectionRef.current;
|
||||||
|
initialRouteSelectionRef.current = null;
|
||||||
|
void Promise.all([refreshCollections(preferredSelection ?? undefined), refreshModels()]);
|
||||||
}, [isAuthenticated]);
|
}, [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]);
|
const providerModelOptions = useMemo(() => getModelOptions(modelCatalog, provider), [modelCatalog, provider]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user