Pull requests / #504

#504 web: saved chats in a sidebar, kept in localStorage (#361)

closed · @homeofe · 0 comments · View on GitHub

Setup & installServer & APIAMD / HIPWindows

Description

## Problem

The chat page keeps one conversation (`strata.chat`), and "New chat" clears it (with a short Undo). #361 asked for a chat history sidebar; you noted it there and wrote that a PR is welcome, with the conversations in `localStorage` (`serve/web/app.js`).

## Change

Only `serve/web/app.js`, `index.html` and `app.css`. No server change, nothing leaves the browser.

- **Storage:** `strata.chats` is the list `[{id, title, time, named}]`, newest first. `strata.chat.<id>` holds a chat's messages, in the same shape `saveChat` already wrote: pictures and files keep only their names. `strata.chat_open` is the chat shown. A chat is kept from its first answer, so an empty "New chat" leaves nothing behind.
- **Migration:** an existing `strata.chat` becomes the first entry on the first load, and the old key is removed once the list is written.
- **Sidebar ("Chats"):** new chat, open, rename (inline; Enter saves, Esc cancels), delete with Undo. The title is the first question's first 60 characters until the chat is renamed.
  - On wide screens the list sits beside the chat and is shown or hidden as last chosen. When hidden, a small button where the list was brings it back.
  - Below 1000 px it opens over the chat like the Sampling drawer (scrim, Esc, closes when a chat is picked). Rename/delete stay visible without hover on touch screens.
- **"New chat"** now starts a new chat and keeps the last one in the list, instead of clearing it.
- **`/?q=...`** starts a new chat, so it no longer appends to the last one opened.
- **Storage full or blocked:** `store.set` now reports failure. When a chat can't be stored, a toast says so once instead of losing it silently. `store.del` was added.
- **Other tabs:** a `storage` event refreshes the list; the open chat in this tab stays as it is.
- **The rename icon** is an inline symbol in `index.html`, drawn in the sprite's style. `web/sprite.svg` carries a signed manifest, so I left it untouched.

Not included, to keep it small: search, folders/projects, and sync across browsers (still per browser and origin, like before).

## Tests

- `python -m unittest serve.test_server serve.test_monitor serve.test_mcp`: OK on the branch.
- **A browser test** (Playwright + Chromium, headless) against `python serve/server.py --engine mock --port 8899`. 38 of 38 checks pass, with no page or console errors:
  - migrating an old `strata.chat`;
  - new chat; an empty one is not listed; reordering on a follow-up;
  - switching;
  - rename, and Esc to cancel;
  - reload keeping the list and the open chat;
  - delete and Undo;
  - `?q=`;
  - hide, show and remember;
  - the storage-full toast;
  - at 390 px: the overlay, scrim, Esc, closing on pick, no horizontal scroll, the button not covering the first message.

  The script isn't part of this PR (the repo has no browser tests); I can add it under `tools/` if you want it.
- Checked by hand in a real install on Windows 11 (RX 9070 XT, the ready-made AMD engine, `--host 0.0.0.0` with an API key).

**Overlap with #350:** both PRs touch the same lines in `app.js` (the `let messages = ...` setup) and in `index.html` (the composer bar), so the second one to land needs a small rebase. #350's one-time marker fix on load would then run per chat, wherever a chat is read from `strata.chat.<id>`. I'm happy to rebase onto whichever you merge first.

## Test machine

- **Browser test:** Ubuntu 24.04, Chromium (Playwright 1.x), the server on the mock engine.
- **By hand:** Windows 11 Pro, AMD Radeon RX 9070 XT 16 GB, Strata 0.1.35 (`d9ab843` + this branch).

Related on strata.com

Editorial links to help you install, pick models, or read release notes — not part of the upstream thread.