Sync - #149
Conversation
Sync engine (sync.rs) connects to a configured relay via WebSocket, authenticates with NIP-42, and subscribes to NIP-CF CHANGES feed for gift-wrapped (NIP-59) events. Notes are encrypted end-to-end — the relay only sees opaque kind:1059 blobs. - SyncManager as Tauri managed state with auto-start on app launch - Note-to-event mapping: notes become kind:30023 rumors, sealed and gift-wrapped to self with NIP-44 encryption - Bidirectional sync: local mutations push to relay with 2s debounce, remote changes upsert locally with last-write-wins resolution - Echo prevention via recently-pushed event ID tracking - Exponential backoff reconnection on disconnect - Sync state reset on relay or identity change - DB migration adds sync_event_id column for deletion targeting - Sync status indicator in sidebar (cloud icons for connected/syncing/error/disconnected) - Seed script updated with stable test keypair and sync_event_id column
The sync_event_id must be read before delete_note_permanently destroys the row, and the deletion push should only fire after the local delete succeeds. Pass the pre-fetched ID through the SyncCommand to avoid a redundant query against a now-missing row.
After the build matrix completes, a release job collects the aarch64 and x86_64 DMGs and publishes them as a GitHub release tagged by commit SHA. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThis PR introduces a WebSocket-based synchronization subsystem using the Nostr protocol. It adds database schema migrations for sync event tracking, new Rust dependencies for WebSocket communication, a comprehensive SyncManager implementation with state management, and integrates sync status display into the sidebar UI. Changes
Sequence Diagram(s)sequenceDiagram
participant Frontend as Frontend (Sidebar)
participant App as Tauri App
participant SyncMgr as SyncManager
participant DB as Database
participant Relay as WebSocket Relay
rect rgba(200, 150, 255, 0.5)
Note over Frontend,Relay: Initialization & Auth
Frontend->>App: get_sync_status()
App->>SyncMgr: state()
SyncMgr-->>App: SyncState::Connecting
App-->>Frontend: Display connecting icon
SyncMgr->>DB: Fetch relay URL & identity
SyncMgr->>Relay: WebSocket connect
Relay-->>SyncMgr: Connected
SyncMgr->>Relay: AUTH handshake
Relay-->>SyncMgr: AUTH success
SyncMgr->>SyncMgr: Update state to Syncing
end
rect rgba(150, 200, 255, 0.5)
Note over SyncMgr,Relay: Sync Loop & Event Processing
SyncMgr->>Relay: Subscribe CHANGES
Relay-->>SyncMgr: EVENT (remote note)
SyncMgr->>DB: Upsert note with sync_event_id
SyncMgr->>App: Emit sync-remote-change
App-->>Frontend: Update remote changes
end
rect rgba(255, 200, 150, 0.5)
Note over Frontend,SyncMgr: Local Mutation & Push
Frontend->>App: save_note()
App->>SyncMgr: push(PushNote)
SyncMgr->>SyncMgr: Debounce & construct event
SyncMgr->>Relay: Send note event
Relay-->>SyncMgr: ACK
SyncMgr->>DB: Update checkpoint
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary by CodeRabbit
New Features
Dependencies
Documentation