fix(viewer): hand off transcript ID only, fetch row from SQLite on mount

HistoryPage previously serialised the full TranscriptDto — text, segments,
manual + LLM tags, audio path — into `localStorage["kon_viewer_item"]` so
the viewer window could pick it up on mount. On a multi-hour transcript
that's MB-scale of user voice content sitting in storage that any
same-origin script in any open Kon window can read.

Hand off only `{ id }` (and a timestamp on re-saves). The viewer fetches
the canonical row from SQLite via the existing `get_transcript` Tauri
command and hydrates via the now-exported `mapTranscriptRow`. Cross-window
sync via the `storage` event still works — the receiving window re-fetches
on event instead of trusting the payload.

- HistoryPage `openViewer` + `openEditor`: write `{ id }` only.
- viewer `onMount` + `handleStorageChange`: route through new
  `loadFromHandoff` which calls `invoke("get_transcript", { id })`.
- viewer `saveItemToHistory`: re-stamp localStorage with `{ id, stamp }`
  to retrigger the storage event in sibling windows without leaking
  content.
- `mapTranscriptRow` exported from page.svelte.ts for the viewer's use.

Backward-compatible at the parse layer: the `{ id }` shape extracts cleanly
from a stale full-DTO payload (TranscriptEntry already carries `id` at top
level), so a session that survives the upgrade picks up the new path on
next handoff without manual cleanup.

https://claude.ai/code/session_0189xUb6ie6t9qHkzatGZ9Rb
This commit is contained in:
Claude
2026-04-25 08:47:12 +00:00
parent 3d568148b8
commit ab3bb9370c
3 changed files with 46 additions and 14 deletions

View File

@@ -140,7 +140,7 @@ export function saveProfiles() {
export const history = $state<TranscriptEntry[]>([]);
function mapTranscriptRow(row: TranscriptDto): TranscriptEntry {
export function mapTranscriptRow(row: TranscriptDto): TranscriptEntry {
const text = row.text ?? "";
const rawTags = row.manualTags ?? "";
const manualTags = rawTags ? rawTags.split(",").filter(Boolean) : [];