Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
danielhanchen
f973657b3f studio/frontend: switch to TanStack Router function-form search
Address gemini review on #5633: use `search: () => ({...})` instead
of merging with explicit `undefined`. The function form is the
documented idiom for replacing (not merging) search state, and is
clearer about intent. Also clear `activeThreadId` and close mobile
sidebar in the delete-handler callback to match the other two sites.
2026-05-19 21:35:59 +00:00
danielhanchen
b4ec1b9ab5 studio/frontend: clear stale thread/compare search after sidebar navigation
The sidebar's "delete active chat", "New Chat", and Unsloth-home-logo
all call `navigate({to: "/chat", search: {new: nonce}})`. TanStack
Router merges search params by default, so passing only `{new}` leaves
the prior `thread=<id>` (or `compare=<id>`) in the URL. The recovery
useEffect in chat-page.tsx only fires when `search.thread` changes,
which it doesn't here, so the in-tab address bar stays stale until a
hard reload kicks in.

Visible impact: deleting the currently-open chat correctly removes the
row from the sidebar, but the URL still references the deleted id.
A copied share link is broken; opening a new tab to the same URL
trips the "Chat not found" recovery toast.

Fix: pass `thread: undefined, compare: undefined` alongside `new` so
the merged search ends up as just `{new: nonce}`. This is the
documented TanStack Router idiom for removing keys.

Probe + repro: scripts/r6_sidebar_delete_chat_probe.py and
scripts/r6_repro_active_delete_url.py.
2026-05-19 21:14:50 +00:00

View file

@ -249,10 +249,16 @@ export function AppSidebar() {
async function handleDeleteThread(item: Parameters<typeof deleteChatItem>[0]) {
await deleteChatItem(item, activeThreadId, (view) => {
navigate({
// Function-form search replaces (not merges) so the deleted
// thread / compare id can't survive in the URL. The recovery
// useEffect in chat-page only fires on hard reload, which is
// why the in-tab address bar stays stale otherwise.
setActiveThreadId(null);
void navigate({
to: "/chat",
search: { new: view.newThreadNonce },
search: () => ({ new: view.newThreadNonce }),
});
closeMobileIfOpen();
});
}
@ -362,7 +368,7 @@ export function AppSidebar() {
closeMobileIfOpen();
void navigate({
to: "/chat",
search: { new: createNavigationNonce() },
search: () => ({ new: createNavigationNonce() }),
});
}}
className="flex items-center gap-[6px] select-none"
@ -440,7 +446,10 @@ export function AppSidebar() {
onClick={() => {
if (chatDisabled) return;
setActiveThreadId(null);
navigate({ to: "/chat", search: { new: createNavigationNonce() } });
navigate({
to: "/chat",
search: () => ({ new: createNavigationNonce() }),
});
closeMobileIfOpen();
}}
/>