Phase 2 user-admin chat: unify dispute chat message model with NostrEvent and gift wrap storage#501
Phase 2 user-admin chat: unify dispute chat message model with NostrEvent and gift wrap storage#501
Conversation
…rap storage - Replace DisputeChat model with DisputeChatMessage wrapper around NostrEvent - Store gift wrap events (encrypted) on disk, consistent with P2P chat pattern - Reconstruct and unwrap gift wraps on historical message load - Add getAdminSharedKey() for future multimedia support (Phase 3) - Add isFromUser() method to notifier for sender determination - Update dispute_messages_list, dispute_content, and read status service - Update plan doc: Phase 1 and Phase 2 marked as DONE
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
WalkthroughThis change refactors the dispute chat system by introducing a UI-friendly DisputeChatMessage wrapper containing NostrEvent with pending/error state, replacing raw DisputeChat usage. The implementation switches to single-layer p2pWrap encryption, adds persistent storage for encrypted gift-wrap events, and updates related widgets and services accordingly. Changes
Sequence DiagramsequenceDiagram
participant User as User/Network
participant Notifier as DisputeChatNotifier
participant Storage as Disk Storage
participant Service as DisputeReadStatusService
participant UI as UI Widgets
User->>Notifier: New gift-wrap event received (_onChatEvent)
Notifier->>Notifier: Unwrap & extract inner event
Notifier->>Storage: Persist wrapped event
Storage-->>Notifier: Stored
Notifier->>Notifier: Create DisputeChatMessage(event, isPending=false)
Notifier->>Notifier: Update state.messages
Notifier-->>UI: Notify state change
User->>Notifier: Send message (sendMessage)
Notifier->>Notifier: Create DisputeChatMessage(isPending=true)
Notifier->>Notifier: Update state with pending message
Notifier-->>UI: Show pending indicator
Notifier->>Notifier: Wrap via p2pWrap
Notifier->>Notifier: Publish wrapped event
Notifier->>Storage: Persist wrapped event
Storage-->>Notifier: Stored
Notifier->>Notifier: Update message (isPending=false)
Notifier-->>UI: Message confirmed
UI->>Notifier: Load historical messages (_loadHistoricalMessages)
Notifier->>Storage: Fetch stored wrapped events
Storage-->>Notifier: Wrapped events
Notifier->>Notifier: Unwrap all events
Notifier->>Notifier: Create DisputeChatMessage list
Notifier->>Notifier: Update state.messages
Notifier-->>UI: Render message list
UI->>Service: Check unread status (hasUnreadMessages)
Service->>Service: Filter messages using isFromUser predicate
Service-->>UI: Unread status result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/features/disputes/notifiers/dispute_chat_notifier.dart`:
- Line 28: The timestamp getter currently falls back to DateTime.now() which
yields non-deterministic ordering; change the fallback in the timestamp getter
(DateTime get timestamp) to a deterministic value such as
DateTime.fromMillisecondsSinceEpoch(0) or another stable field on event (e.g.,
event.updatedAt or an event ID-derived timestamp) instead of DateTime.now(),
leaving the primary use of event.createdAt intact.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
docs/DISPUTE_CHAT_MULTIMEDIA_PLAN.mdlib/features/disputes/notifiers/dispute_chat_notifier.dartlib/features/disputes/widgets/dispute_content.dartlib/features/disputes/widgets/dispute_messages_list.dartlib/services/dispute_read_status_service.dart
…ring bug - Per-message send errors now stay at message level only - Removed state.error propagation from _updateMessageState - Prevents full-chat error overlay on individual message failures
There was a problem hiding this comment.
Clean refactor that properly unifies the dispute chat model with the P2P chat pattern. Key improvements:
- Encrypted storage: Storing gift wraps (encrypted) on disk instead of decrypted content is the correct approach — consistent with P2P chat and better for privacy.
- DisputeChatMessage wrapper: Thin, focused wrapper around NostrEvent with UI-only state (pending/error) — good separation of concerns.
isFromUser()via pubkey comparison: Better than storingis_from_userflag — single source of truth._updateMessageState()extraction: Eliminates significant duplication in error handling paths.getAdminSharedKey(): Good forward-thinking for Phase 3 multimedia.
CI passes, no conflicts, no unresolved comments. LGTM ✅
Summary by CodeRabbit
New Features
Documentation