Adopt PosterChan's "encrypted events are the datastore" idea for two per-browser bits of state, so they follow the user's npub across devices. New shared engine (src/hooks/useSyncedAppData.ts): - Stores one encrypted kind-30078 (NIP-78) event per d-tag, NIP-44 encrypt-to-self, modeled on the proven useStash pattern. - Clobber-guard: re-fetch + re-decrypt the freshest remote copy and MERGE the local patch in before publishing (never overwrites a field another device just set). - Debounced publisher (coalesces rapid writes, flushes on pagehide/ beforeunload) so frequent read-marker changes don't spam relays. - No-op for anon / non-NIP-44 signers. Read-state sync (src/hooks/useReadState.ts), d-tag skatespots:read-state: - Unifies the four previously localStorage-only markers (notification bell, DMs, crew chat, newsletter) into one synced blob. - Merge = field-wise MAX (markers only move forward → commutative, safe). - The four legacy hooks now re-export drop-in replacements with identical signatures, so NO consumer component changed. localStorage stays as the instant/offline/anon fast path; the relay copy hydrates and max-merges. - Fixes the real bug where clearing a badge on one device left it lit on another. Preference sync (src/hooks/usePreferences.ts), d-tag skatespots:preferences: - Mobile + desktop nav layouts now sync (language field wired for later). - Merge = last-write-wins by updatedAt (a pref replaces, not accumulates). - useNavPreferences / useDesktopNavPreferences adopt a synced layout when present and mirror changes; public APIs unchanged, localStorage fallback intact. Docs: NIP.md gains a "Cross-device app data (kind 30078, encrypted)" section documenting both d-tags, their content shapes, merge policies, and the clobber-guard/debounce/anon safety notes. Build + typecheck pass. Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
9 lines
390 B
TypeScript
9 lines
390 B
TypeScript
/**
|
|
* Newsletter mailbox read state.
|
|
*
|
|
* Implementation moved to `useReadState` (cross-device sync via an encrypted
|
|
* `kind-30078` event) while preserving the same instant localStorage fast-path
|
|
* and the same public API (`{ lastRead, markNewsletterRead }`). Re-exported
|
|
* here so existing imports keep working unchanged.
|
|
*/
|
|
export { useNewsletterRead } from '@/hooks/useReadState';
|