tab-close + chat archive/delete + landing-card buttons + 1000px content cap
Feature 1 — Tab close menu (pure local pane state, no API):
- ChatTabBar context menu: Rename / sep / Close / Close others / Close to right / Close all
- Workspace bulk-tab primitives: closeOtherTabs, closeTabsToRight, closeAllTabs (manipulate panes[].chatIds, no fetch)
- Drop in-bar Delete; landing card's name-typed Delete is the canonical destructive path
Feature 2 — Chat archive + delete:
- chats.status vocabulary aligned with projects ('open' | 'archived'); DROP old inline CHECK, UPDATE 'closed' → 'archived', ADD new named chats_status_chk
- POST /api/chats/:id/archive (204) + POST /api/chats/:id/unarchive (200) + GET /api/sessions/:id/chats?status=archived; DELETE publishes chat_deleted; PATCH simplified to name-only
- 3 new WS frames: chat_archived, chat_unarchived, chat_deleted (renamed from chat_closed)
- Same dedup discipline: server-only publish, no local sessionEvents.emit in client
- SessionLandingPage: right-click ContextMenu (Open / Rename / Archive / sep / Delete-destructive), inline rename, archive confirm dialog, delete dialog with name-typed Input gated until typed text === chat.name, Archived chats collapsible section with Restore
- Card-level Archive + Delete icon buttons reusing the same dialog state setters; stopPropagation on both so card click still opens the chat; archived cards keep only Restore
UX — chat content width cap:
- ChatPane content (MessageList, queue chips, stop button, ChatInput) wrapped in inner max-w-[1000px] mx-auto w-full so messages center; outer border-t / scroll containers stay full-width so pane chrome and backgrounds remain edge-to-edge
- No new deps, no media queries (narrow viewports collapse to width naturally)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -117,18 +117,24 @@ export const api = {
|
||||
},
|
||||
|
||||
chats: {
|
||||
listForSession: (sessionId: string) =>
|
||||
request<Chat[]>(`/api/sessions/${sessionId}/chats`),
|
||||
listForSession: (sessionId: string, params?: { status?: 'open' | 'archived' }) =>
|
||||
request<Chat[]>(
|
||||
`/api/sessions/${sessionId}/chats${params?.status ? `?status=${params.status}` : ''}`
|
||||
),
|
||||
create: (sessionId: string, body?: { name?: string }) =>
|
||||
request<Chat>(`/api/sessions/${sessionId}/chats`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body ?? {}),
|
||||
}),
|
||||
update: (chatId: string, body: { name?: string; status?: 'open' | 'closed' }) =>
|
||||
update: (chatId: string, body: { name: string }) =>
|
||||
request<Chat>(`/api/chats/${chatId}`, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
archive: (chatId: string) =>
|
||||
request<void>(`/api/chats/${chatId}/archive`, { method: 'POST' }),
|
||||
unarchive: (chatId: string) =>
|
||||
request<Chat>(`/api/chats/${chatId}/unarchive`, { method: 'POST' }),
|
||||
remove: (chatId: string) =>
|
||||
request<void>(`/api/chats/${chatId}`, { method: 'DELETE' }),
|
||||
messages: (chatId: string) =>
|
||||
|
||||
Reference in New Issue
Block a user