Archived chats: a page to find them again, Restore chat, delete
Archive was one-way in the app. Archived (sidebar, under Files) reads
GET /api/v2/chats?archived=true, newest first and paged; a row opens the
chat, Restore chat PATCHes archived:false and reads the sidebar again, and
the row's menu deletes. An open archived chat says so in its header, with
Restore chat there and in its menu. The words are the web's own ("Archived",
"Restore chat"). Tests: D2 at 1280 and 390 px.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
10 files changed
+323
-3
No files matched your search
+13
-1
@@ -18,6 +18,7 @@ import { readyIds, sending, sent, discard } from "./attach.js"
|
||||
import { watchActivity, activityChanged, planList, activityButton, treeChanged } from "./activity.js"
|
||||
import { agentBlock, agentReady, agentState, onAgentChange } from "./agent.js"
|
||||
import { folderName } from "./list.js"
|
||||
import { unarchive } from "./archived.js"
|
||||
import { isProgress, progressLine, progressTicks } from "./progress.js"
|
||||
import { aimTerminal, terminalButton, terminalOpen, toggleTerminal } from "./terminal.js"
|
||||
|
||||
@@ -691,6 +692,8 @@ function renderHead(chat) {
|
||||
// "Continue in a terminal" stays in the chat's menu.
|
||||
if (deviceOf(chat.device.token_id)?.terminal) tools.append(terminalButton())
|
||||
}
|
||||
// An archived chat says so where it is read, with the way back into the sidebar.
|
||||
if (chat.archived) tools.append(h("button", { type: "button", class: "btn btn--sm head__unarchive", text: t("Restore chat"), title: t("Archived"), onclick: () => unarchiveChat(open?.chat || chat) }))
|
||||
tools.append(activityButton())
|
||||
tools.append(h("button", { type: "button", class: "tool", "aria-label": t("More"), title: t("More"), onclick: (e) => chatMenu(e.currentTarget, open?.chat || chat) }, icon(ICONS.more)))
|
||||
}
|
||||
@@ -947,7 +950,7 @@ export function chatMenu(anchor, chat) {
|
||||
const items = [{ label: t("Rename…"), run: () => renameChat(chat) }]
|
||||
if (chat.kind === "agent" && chat.device_session_id) items.push({ label: t("Continue in a terminal…"), run: () => continueInTerminal(chat) })
|
||||
if (base) items.push({ label: t("Open in the web interface"), run: () => openLink(`${base}/chat/${encodeURIComponent(chat.id)}`) })
|
||||
items.push(null, { label: t("Archive chat"), run: () => archiveChat(chat) })
|
||||
items.push(null, chat.archived ? { label: t("Restore chat"), run: () => unarchiveChat(chat) } : { label: t("Archive chat"), run: () => archiveChat(chat) })
|
||||
if (mayDelete) items.push({ label: t("Delete chat"), danger: true, run: () => deleteChat(chat) })
|
||||
menu(anchor, items)
|
||||
}
|
||||
@@ -1004,6 +1007,15 @@ async function archiveChat(chat) {
|
||||
}
|
||||
}
|
||||
|
||||
/** An archived chat, open or in its page's menu, back into the sidebar. */
|
||||
async function unarchiveChat(chat) {
|
||||
if (!(await unarchive(chat))) return
|
||||
if (open?.chat?.id === chat.id) {
|
||||
open.chat = { ...open.chat, archived: false }
|
||||
renderHead(open.chat)
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteChat(chat) {
|
||||
const yes = await ask({
|
||||
title: t("Delete this chat?"),
|
||||
|
||||
Reference in new issue
Block a user