mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-05-20 16:42:25 +00:00
fix(webui): default to new chat on load and preserve scroll on settings return
- Remove auto-selection of the most recent session on initial load, so the app opens to a blank new-chat page instead of the last session. - Preserve active session state when navigating to/from settings: keep ThreadShell mounted (hidden via CSS) so scroll position, message cache, and streaming state are not lost. - Update onBackToChat to return to blank page when no session was active instead of falling back to the most recent session. - Update related test expectations to match the new navigation behavior.
This commit is contained in:
parent
9e15925cf4
commit
00597fccd6
@ -250,7 +250,6 @@ function Shell({ onModelNameChange, onLogout }: { onModelNameChange: (modelName:
|
|||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const lastSessionsLen = useRef(0);
|
|
||||||
const restartSawDisconnectRef = useRef(false);
|
const restartSawDisconnectRef = useRef(false);
|
||||||
const [restartToast, setRestartToast] = useState<string | null>(null);
|
const [restartToast, setRestartToast] = useState<string | null>(null);
|
||||||
const [isRestarting, setIsRestarting] = useState(false);
|
const [isRestarting, setIsRestarting] = useState(false);
|
||||||
@ -266,13 +265,7 @@ function Shell({ onModelNameChange, onLogout }: { onModelNameChange: (modelName:
|
|||||||
}
|
}
|
||||||
}, [desktopSidebarOpen]);
|
}, [desktopSidebarOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (activeKey) return;
|
|
||||||
if (sessions.length > 0 && lastSessionsLen.current === 0) {
|
|
||||||
setActiveKey(sessions[0].key);
|
|
||||||
}
|
|
||||||
lastSessionsLen.current = sessions.length;
|
|
||||||
}, [sessions, activeKey]);
|
|
||||||
|
|
||||||
const activeSession = useMemo<ChatSummary | null>(() => {
|
const activeSession = useMemo<ChatSummary | null>(() => {
|
||||||
if (!activeKey) return null;
|
if (!activeKey) return null;
|
||||||
@ -335,9 +328,8 @@ function Shell({ onModelNameChange, onLogout }: { onModelNameChange: (modelName:
|
|||||||
setView("chat");
|
setView("chat");
|
||||||
setMobileSidebarOpen(false);
|
setMobileSidebarOpen(false);
|
||||||
setActiveKey((current) => {
|
setActiveKey((current) => {
|
||||||
if (current && sessions.some((session) => session.key === current)) {
|
if (!current) return null;
|
||||||
return current;
|
if (sessions.some((session) => session.key === current)) return current;
|
||||||
}
|
|
||||||
return sessions[0]?.key ?? null;
|
return sessions[0]?.key ?? null;
|
||||||
});
|
});
|
||||||
}, [sessions]);
|
}, [sessions]);
|
||||||
@ -479,18 +471,13 @@ function Shell({ onModelNameChange, onLogout }: { onModelNameChange: (modelName:
|
|||||||
</Sheet>
|
</Sheet>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<main className="flex h-full min-w-0 flex-1 flex-col">
|
<main className="relative flex h-full min-w-0 flex-1 flex-col">
|
||||||
{view === "settings" ? (
|
<div
|
||||||
<SettingsView
|
className={cn(
|
||||||
theme={theme}
|
"absolute inset-0 flex flex-col",
|
||||||
onToggleTheme={toggle}
|
view === "settings" && "invisible pointer-events-none",
|
||||||
onBackToChat={onBackToChat}
|
)}
|
||||||
onModelNameChange={onModelNameChange}
|
>
|
||||||
onLogout={onLogout}
|
|
||||||
onRestart={onRestart}
|
|
||||||
isRestarting={isRestarting}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ThreadShell
|
<ThreadShell
|
||||||
session={activeSession}
|
session={activeSession}
|
||||||
title={headerTitle}
|
title={headerTitle}
|
||||||
@ -502,6 +489,19 @@ function Shell({ onModelNameChange, onLogout }: { onModelNameChange: (modelName:
|
|||||||
onToggleTheme={toggle}
|
onToggleTheme={toggle}
|
||||||
hideSidebarToggleOnDesktop={desktopSidebarOpen}
|
hideSidebarToggleOnDesktop={desktopSidebarOpen}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
{view === "settings" && (
|
||||||
|
<div className="absolute inset-0 flex flex-col">
|
||||||
|
<SettingsView
|
||||||
|
theme={theme}
|
||||||
|
onToggleTheme={toggle}
|
||||||
|
onBackToChat={onBackToChat}
|
||||||
|
onModelNameChange={onModelNameChange}
|
||||||
|
onLogout={onLogout}
|
||||||
|
onRestart={onRestart}
|
||||||
|
isRestarting={isRestarting}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@ -265,7 +265,7 @@ describe("App layout", () => {
|
|||||||
expect(screen.queryByDisplayValue("unsaved-brave-key")).not.toBeInTheDocument();
|
expect(screen.queryByDisplayValue("unsaved-brave-key")).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns from settings to an available chat instead of the blank start page", async () => {
|
it("returns from settings to the blank start page when no session was active", async () => {
|
||||||
mockSessions = [
|
mockSessions = [
|
||||||
{
|
{
|
||||||
key: "websocket:chat-a",
|
key: "websocket:chat-a",
|
||||||
@ -330,10 +330,8 @@ describe("App layout", () => {
|
|||||||
expect(await screen.findByRole("heading", { name: "General" })).toBeInTheDocument();
|
expect(await screen.findByRole("heading", { name: "General" })).toBeInTheDocument();
|
||||||
fireEvent.click(screen.getByRole("button", { name: "Back to chat" }));
|
fireEvent.click(screen.getByRole("button", { name: "Back to chat" }));
|
||||||
|
|
||||||
await waitFor(() => expect(document.title).toBe("First chat · nanobot"));
|
await waitFor(() => expect(document.title).toBe("nanobot"));
|
||||||
const restoredSidebar = screen.getByRole("navigation", { name: "Sidebar navigation" });
|
expect(screen.getByText("What can I do for you?")).toBeInTheDocument();
|
||||||
fireEvent.click(within(restoredSidebar).getByRole("button", { name: /^Second chat$/ }));
|
|
||||||
await waitFor(() => expect(document.title).toBe("Second chat · nanobot"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("filters sidebar sessions through the lightweight search row", async () => {
|
it("filters sidebar sessions through the lightweight search row", async () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user