Chat mode, phase 2: local history, answer actions, motion polish
- Conversations in a versioned IndexedDB store (freezmo-chat v1, zod validated with the same schema backup/sync use, capped at 100 x 300). Settled turns persist (question always; answer when produced, partial stops included); ?c=<id> keeps reloads on the conversation via history.replaceState (no router round-trip mid-chat). - History UI: desktop column, phone sheet (spring, backdrop, Escape), auto titles from the first question, inline rename, delete with an Undo toast, diacritic-folding search over titles and message text. Scope and model are remembered per conversation; history is readable offline. - Assistant actions: Turn into flashcards (New deck with the answer as notes, landing on the options step - deck seed gained step) and Save to notes (appends to the single scoped deck, trimmed at 40k). - Chats travel in the backup export (preview counts them) and in the encrypted sync payload; still never the key. - Motion from lib/motion.ts: message fade-up, sheet springs for the model/context/history sheets, 150ms composer height transition, all skipped under reduced motion. - Tests: chat suite 63 -> 89 checks (history, reload, rename/search/ delete/undo, actions, export, two-device sync round-trip, offline, desktop panel). Full set: 12/12 suites, 513 checks. SW -> freezmo-v33. Also: tests/model-compare.mjs benchmark (diagnostic) for deciding the default text model on numbers; defaults unchanged.
This commit is contained in:
parent
756a6257a2
commit
5ca0de920c
19 changed files with 1107 additions and 113 deletions
28
README.md
28
README.md
|
|
@ -711,6 +711,14 @@ have a step explained without leaving the app.
|
|||
allowlist and never accepts a model name from the client.
|
||||
- **Attachments.** Photos, PDFs and documents go through the existing vision/extraction step first
|
||||
(plain text), so any chat model works — text-only included.
|
||||
- **History.** Conversations live in a local IndexedDB store: a list on the left on desktop, a
|
||||
sheet on phones, with auto titles from your first question, rename, delete (with Undo) and a
|
||||
search across titles and message text. Conversations remember their scope and model, reopen from
|
||||
`?c=<id>` (so a reload continues where you left off), stay readable offline, and are included in
|
||||
the backup export and the encrypted sync — still never the key.
|
||||
- **From an answer.** Every answer can become a deck (**Turn into flashcards** opens New deck with
|
||||
the answer as notes, on the options step) or be appended to the scoped deck's notes (**Save to
|
||||
notes**, only offered when exactly one deck is in scope).
|
||||
- **Streaming and controls.** Tokens stream with a caret and a stop button; auto-scroll pauses when
|
||||
you scroll up and a jump-to-bottom button appears; answers render safe markdown (lists, tables,
|
||||
code blocks with copy — no HTML injection) and KaTeX loads dynamically only when a message
|
||||
|
|
@ -1136,7 +1144,7 @@ Things I chose while building, with the reasoning:
|
|||
limits, the learning engine, homework check/follow-ups). Suites that need a stub Ollama or
|
||||
VAPID keys start their own `next start` instance on a spare port, verify the port is free and
|
||||
kill the process group on exit; test scratch stays in `tests/.tmp/` (gitignored). Twelve suites,
|
||||
487 checks.
|
||||
513 checks.
|
||||
|
||||
46. **The ice orbs are rising bubbles now, composited and cheaper to read through.** The glossy
|
||||
orbs (the glacier blobs stay exactly as they were) rise from below the bottom edge to above the
|
||||
|
|
@ -1183,6 +1191,24 @@ Things I chose while building, with the reasoning:
|
|||
points, streaming, stop, markdown + KaTeX, the model and scope pickers, edit/regenerate,
|
||||
offline, attachments and reduced motion).
|
||||
|
||||
48. **Chat history is local, bounded and part of the backup/sync payload.** Conversations live in
|
||||
their own versioned IndexedDB (`freezmo-chat` v1, store `chats`), validated with the same zod
|
||||
schema the backup and sync use (`chatConversationSchema`), capped at 100 conversations × 300
|
||||
messages, with the in-memory mirror the other stores use. Every settled turn is persisted (the
|
||||
question always, the answer when one was produced — partial answers from a stop included); the
|
||||
URL carries `?c=<id>` so a reload continues the conversation, and that URL tweak uses
|
||||
`history.replaceState` so it never triggers a router round-trip mid-chat. The list (desktop
|
||||
column, phone sheet) has auto titles from the first question, inline rename, delete with an Undo
|
||||
toast, and diacritic-folding search over titles and message text. Chats ride along in the backup
|
||||
file (the import preview counts them) and in the encrypted sync payload — still never the key.
|
||||
Assistant answers also offer **Turn into flashcards** (opens New deck with the answer as notes,
|
||||
landing on the options step) and **Save to notes** (appends to the single scoped deck, trimming
|
||||
at 40k characters). Motion comes from `lib/motion.ts`: message fade-up, sheet springs, a 150 ms
|
||||
composer height transition — all skipped under reduced motion. Verified by the chat suite (89
|
||||
checks: everything from phase 1 plus history persistence, reload, rename/search/delete/undo,
|
||||
both actions, the export payload, a two-device sync round-trip of a chat, offline readability
|
||||
and the desktop panel).
|
||||
|
||||
36. **The mobile declutter pass reshapes, it doesn't fork.** Phones (≤639px) get a 3-step deck
|
||||
flow and a 2-step homework flow that share the exact state and handlers with the desktop
|
||||
cards (one `UploadScreen` / one `HomeworkInput`, two layouts switched by `useIsPhone()`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue