Move the two Zustand `persist` stores off browser localStorage and onto a
server-side file (`/data/ui-state.json`) so the config follows the user across
browsers and devices instead of being trapped per-browser.
- backend: `ui_state.py` — a dumb key→string JSON-file store (key = persist
store name, value = its opaque serialized blob), exposed via
`GET/PUT/DELETE /api/ui-state/{key}` (atomic temp-file rewrite, key validated).
- frontend: `lib/serverStorage.ts` — a `StateStorage` backend that reads/writes
those endpoints; failures are swallowed so a network blip can't white-screen
the UI. Includes a one-time self-cleaning migration that seeds the server file
from any leftover localStorage value then clears it.
- point `useSettings` (ai-agent-settings) and the main store (ai-agent-store —
notifKnown/notifNew/notifSeeded + drafts/sidebar) at serverStorage.
- hydration is now async: gate `syncNotifs` on `useStore.persist.hasHydrated()`
(new `lib/useHydrated`) so the notification baseline isn't seeded from empty
defaults before the server value lands.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.4 KiB
2.4 KiB