From 0831ee3865654eb493751d08f72c27527dbd7521 Mon Sep 17 00:00:00 2001 From: Clawdbot Date: Wed, 28 Jan 2026 16:12:32 +0100 Subject: [PATCH] feat(ui): Delete session button in Chat tab Adds a Delete button to the Chat tab with confirmation modal. Features: - Delete button next to Stop/New session (disabled during generation) - Hidden for main session (cannot delete main) - Confirmation modal with session name - Enter key to confirm, Escape to cancel - After deletion: switches to main session and refreshes chat - Archives transcript when deleting (same as Sessions tab) Changes: - ui/src/ui/views/chat.ts: Add delete props, modal overlay, delete button - ui/src/ui/app.ts: Add chatDeleteConfirm state - ui/src/ui/app-render.ts: Wire up delete handlers, hide for main, switch after delete - ui/src/styles/components.css: Styles for confirmation modal --- ui/src/styles/components.css | 46 +++++++++++++++++++++++++++++ ui/src/ui/app-render.ts | 22 ++++++++++++++ ui/src/ui/app.ts | 1 + ui/src/ui/views/chat.ts | 56 +++++++++++++++++++++++++++++++++++- 4 files changed, 124 insertions(+), 1 deletion(-) diff --git a/ui/src/styles/components.css b/ui/src/styles/components.css index 27dfe62d1..8ce1bf51f 100644 --- a/ui/src/styles/components.css +++ b/ui/src/styles/components.css @@ -1484,3 +1484,49 @@ flex-wrap: wrap; gap: 8px; } + +/* Delete session confirmation modal */ +.chat-delete-overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; + backdrop-filter: blur(2px); +} + +.chat-delete-card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: 8px; + padding: 20px 24px; + max-width: 360px; + text-align: center; +} + +.chat-delete-title { + font-size: 16px; + font-weight: 600; + margin-bottom: 8px; +} + +.chat-delete-sub { + font-size: 13px; + color: var(--muted); + margin-bottom: 16px; + word-break: break-word; +} + +.chat-delete-actions { + display: flex; + gap: 8px; + justify-content: center; +} + +.chat-delete-hint { + margin-top: 12px; + font-size: 11px; + color: var(--muted); +} diff --git a/ui/src/ui/app-render.ts b/ui/src/ui/app-render.ts index 422af6863..e950e93be 100644 --- a/ui/src/ui/app-render.ts +++ b/ui/src/ui/app-render.ts @@ -497,6 +497,28 @@ export function renderApp(state: AppViewState) { onSplitRatioChange: (ratio: number) => state.handleSplitRatioChange(ratio), assistantName: state.assistantName, assistantAvatar: state.assistantAvatar, + // Delete session (hidden for main session) + showDeleteConfirm: state.chatDeleteConfirm, + onDeleteClick: + state.sessionKey === "main" || + parseAgentSessionKey(state.sessionKey)?.rest === "main" + ? undefined + : () => (state.chatDeleteConfirm = true), + onDeleteConfirm: async () => { + state.chatDeleteConfirm = false; + const { deleteSession } = await import("./controllers/sessions"); + await deleteSession(state as Parameters[0], state.sessionKey); + // Switch to main session after deletion + const mainKey = state.sessionsResult?.mainSessionKey ?? "main"; + state.sessionKey = mainKey; + state.applySettings({ + ...state.settings, + sessionKey: mainKey, + lastActiveSessionKey: mainKey, + }); + void loadChatHistory(state); + }, + onDeleteCancel: () => (state.chatDeleteConfirm = false), }) : nothing} diff --git a/ui/src/ui/app.ts b/ui/src/ui/app.ts index 50ffcdf76..c4b9e737e 100644 --- a/ui/src/ui/app.ts +++ b/ui/src/ui/app.ts @@ -130,6 +130,7 @@ export class MoltbotApp extends LitElement { @state() chatThinkingLevel: string | null = null; @state() chatQueue: ChatQueueItem[] = []; @state() chatAttachments: ChatAttachment[] = []; + @state() chatDeleteConfirm = false; // Sidebar state for tool output viewing @state() sidebarOpen = false; @state() sidebarContent: string | null = null; diff --git a/ui/src/ui/views/chat.ts b/ui/src/ui/views/chat.ts index f5fb6e80b..31beb8541 100644 --- a/ui/src/ui/views/chat.ts +++ b/ui/src/ui/views/chat.ts @@ -68,6 +68,11 @@ export type ChatProps = { onCloseSidebar?: () => void; onSplitRatioChange?: (ratio: number) => void; onChatScroll?: (event: Event) => void; + // Delete session + showDeleteConfirm?: boolean; + onDeleteClick?: () => void; + onDeleteConfirm?: () => void; + onDeleteCancel?: () => void; }; const COMPACTION_TOAST_DURATION_MS = 5000; @@ -240,7 +245,44 @@ export function renderChat(props: ChatProps) { `; return html` -
+
{ + // Escape to cancel delete confirmation + if (e.key === "Escape" && props.showDeleteConfirm && props.onDeleteCancel) { + e.preventDefault(); + props.onDeleteCancel(); + } + // Enter to confirm delete + if (e.key === "Enter" && props.showDeleteConfirm && props.onDeleteConfirm) { + e.preventDefault(); + props.onDeleteConfirm(); + } + }} + > + ${props.showDeleteConfirm + ? html` + + ` + : nothing} + ${props.disabledReason ? html`
${props.disabledReason}
` : nothing} @@ -361,6 +403,18 @@ export function renderChat(props: ChatProps) { > ${canAbort ? "Stop" : "New session"} + ${props.onDeleteClick + ? html` + + ` + : nothing}