mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-07 09:58:34 +00:00
fix(webui): name temporary chats from first message
This commit is contained in:
parent
4d77189d9c
commit
325f7b0367
@ -64,6 +64,7 @@ import {
|
|||||||
import { projectNameFromPath, scopeWithAccessMode } from "@/lib/workspace";
|
import { projectNameFromPath, scopeWithAccessMode } from "@/lib/workspace";
|
||||||
import {
|
import {
|
||||||
createTemporaryChatSession,
|
createTemporaryChatSession,
|
||||||
|
deriveTemporaryChatTitle,
|
||||||
} from "@/lib/temporary-chat";
|
} from "@/lib/temporary-chat";
|
||||||
|
|
||||||
type BootState =
|
type BootState =
|
||||||
@ -2069,7 +2070,7 @@ function Shell({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const headerTitle = temporaryChatActive
|
const headerTitle = temporaryChatActive
|
||||||
? t("temporaryChat.title")
|
? deriveTemporaryChatTitle(activeSession?.preview, t("temporaryChat.title"))
|
||||||
: activeSession
|
: activeSession
|
||||||
? sidebarState.title_overrides[activeSession.key] ||
|
? sidebarState.title_overrides[activeSession.key] ||
|
||||||
activeSession.title ||
|
activeSession.title ||
|
||||||
|
|||||||
@ -44,6 +44,7 @@ import {
|
|||||||
type ChatGroupLabels,
|
type ChatGroupLabels,
|
||||||
} from "@/lib/chat-groups";
|
} from "@/lib/chat-groups";
|
||||||
import { clearDraggedSession, writeDraggedSession } from "@/lib/session-drag";
|
import { clearDraggedSession, writeDraggedSession } from "@/lib/session-drag";
|
||||||
|
import { deriveTemporaryChatTitle } from "@/lib/temporary-chat";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import type { ChatSummary, SidebarDensity, SidebarSortMode } from "@/lib/types";
|
import type { ChatSummary, SidebarDensity, SidebarSortMode } from "@/lib/types";
|
||||||
|
|
||||||
@ -537,7 +538,7 @@ function TemporaryChatSection({
|
|||||||
<ul className="space-y-0.5">
|
<ul className="space-y-0.5">
|
||||||
{sessions.map((session) => {
|
{sessions.map((session) => {
|
||||||
const active = session.key === activeKey;
|
const active = session.key === activeKey;
|
||||||
const title = deriveTitle(session.preview, t("temporaryChat.title"));
|
const title = deriveTemporaryChatTitle(session.preview, t("temporaryChat.title"));
|
||||||
return (
|
return (
|
||||||
<li key={session.key} className="min-w-0">
|
<li key={session.key} className="min-w-0">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -2,6 +2,15 @@ import type { ChatSummary } from "./types";
|
|||||||
|
|
||||||
const WEBSOCKET_SESSION_KEY_PREFIX = "websocket:";
|
const WEBSOCKET_SESSION_KEY_PREFIX = "websocket:";
|
||||||
|
|
||||||
|
export function deriveTemporaryChatTitle(
|
||||||
|
firstMessage: string | undefined,
|
||||||
|
fallback: string,
|
||||||
|
): string {
|
||||||
|
const oneLine = firstMessage?.replace(/\s+/g, " ").trim() ?? "";
|
||||||
|
if (!oneLine) return fallback;
|
||||||
|
return oneLine.length > 60 ? `${oneLine.slice(0, 57)}…` : oneLine;
|
||||||
|
}
|
||||||
|
|
||||||
export function createTemporaryChatSession(chatId: string): ChatSummary {
|
export function createTemporaryChatSession(chatId: string): ChatSummary {
|
||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -466,7 +466,10 @@ describe("App layout", () => {
|
|||||||
name: "first private message",
|
name: "first private message",
|
||||||
}));
|
}));
|
||||||
await waitFor(() => expect(window.location.hash).toBe(firstHash));
|
await waitFor(() => expect(window.location.hash).toBe(firstHash));
|
||||||
expect(screen.getByText("Temporary chat")).toBeInTheDocument();
|
expect(within(screen.getByTestId("thread-header")).getByText(
|
||||||
|
"first private message",
|
||||||
|
)).toBeInTheDocument();
|
||||||
|
await waitFor(() => expect(document.title).toBe("first private message · nanobot"));
|
||||||
expect(screen.queryByRole("button", { name: "Temporary chat" })).not.toBeInTheDocument();
|
expect(screen.queryByRole("button", { name: "Temporary chat" })).not.toBeInTheDocument();
|
||||||
|
|
||||||
fireEvent.click(within(sidebar).getByRole("button", {
|
fireEvent.click(within(sidebar).getByRole("button", {
|
||||||
|
|||||||
@ -156,7 +156,7 @@ describe("ChatList", () => {
|
|||||||
const temporarySession = session({
|
const temporarySession = session({
|
||||||
key: "temporary:temporary-one",
|
key: "temporary:temporary-one",
|
||||||
chatId: "temporary-one",
|
chatId: "temporary-one",
|
||||||
preview: "Private planning",
|
preview: "hi",
|
||||||
});
|
});
|
||||||
const onSelect = vi.fn();
|
const onSelect = vi.fn();
|
||||||
const onClose = vi.fn();
|
const onClose = vi.fn();
|
||||||
@ -176,11 +176,11 @@ describe("ChatList", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const section = screen.getByRole("region", { name: "Temporary chats" });
|
const section = screen.getByRole("region", { name: "Temporary chats" });
|
||||||
fireEvent.click(within(section).getByRole("button", { name: "Private planning" }));
|
fireEvent.click(within(section).getByRole("button", { name: "hi" }));
|
||||||
expect(onSelect).toHaveBeenCalledWith("temporary:temporary-one");
|
expect(onSelect).toHaveBeenCalledWith("temporary:temporary-one");
|
||||||
|
|
||||||
fireEvent.click(within(section).getByRole("button", {
|
fireEvent.click(within(section).getByRole("button", {
|
||||||
name: "Close temporary chat: Private planning",
|
name: "Close temporary chat: hi",
|
||||||
}));
|
}));
|
||||||
expect(onClose).toHaveBeenCalledWith("temporary:temporary-one");
|
expect(onClose).toHaveBeenCalledWith("temporary:temporary-one");
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user