From 3ebcd49c404ed287a97af159ac8adfa63d572849 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Tue, 2 Jun 2026 14:43:16 +0900 Subject: feat(tabs): drag-reorder + double-click rename + per-tab chat draft - TabBar: HTML5 drag-and-drop to reorder user tabs (subagent tabs untouched); double-click a tab title to rename (Enter/blur confirm, Escape cancel). - Store: add reorderTabs/renameTab/setDraft; per-tab in-memory `draft` and `manualTitle` fields. Manual rename suppresses first-message auto-title. - ChatInput: bind to the active tab's draft so switching tabs saves/restores unsent text instead of clobbering it. - Backend: updateTabPositions() + PATCH /tabs/reorder persist tab order to the existing `position` column; tabs without a stored position fall to the end then get explicit positions on first reorder. - Tests: store reorder/rename/auto-title-guard/draft coverage; core updateTabPositions coverage (FakeDatabase extended with transaction support). --- packages/api/src/routes/tabs.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'packages/api/src') diff --git a/packages/api/src/routes/tabs.ts b/packages/api/src/routes/tabs.ts index f52ee99..28a89f1 100644 --- a/packages/api/src/routes/tabs.ts +++ b/packages/api/src/routes/tabs.ts @@ -11,6 +11,7 @@ import { listOpenTabs, setSetting, updateTabModel, + updateTabPositions, updateTabStatus, updateTabTitle, } from "@dispatch/core"; @@ -63,6 +64,18 @@ tabsRoutes.put("/settings/title-model", async (c) => { return c.json({ success: true }); }); +// Reorder open tabs. Body `{ ids }` is the new left-to-right order of tab ids; +// each tab's `position` is rewritten to its index. Must be declared before the +// `/:id` routes so "reorder" isn't captured as an id param. +tabsRoutes.patch("/reorder", async (c) => { + const body = await c.req.json<{ ids?: string[] }>(); + if (!Array.isArray(body.ids) || body.ids.some((id) => typeof id !== "string")) { + return c.json({ error: "ids must be an array of strings" }, 400); + } + updateTabPositions(body.ids); + return c.json({ success: true }); +}); + tabsRoutes.get("/:id", (c) => { const id = c.req.param("id"); const tab = getTab(id); -- cgit v1.2.3