Skip to content

Restore dispute chats#561

Open
BraCR10 wants to merge 5 commits intomainfrom
fix/chat-admin-restore
Open

Restore dispute chats#561
BraCR10 wants to merge 5 commits intomainfrom
fix/chat-admin-restore

Conversation

@BraCR10
Copy link
Copy Markdown
Member

@BraCR10 BraCR10 commented Apr 4, 2026

Once a user restores orders that contain disputes and those disputes have solvers, the dispute chat must be re-established

Changes

  • Introduced adminPubkey field in RestoreResponse model to retrieve dispute solver's public key from server response Include solver_pubkey in restore disputes response mostro#690
  • Updated restore manager to parse and store admin public key in session objects during account recovery
  • Guaranteed dispute solver's public key persists in sessions after restoration completes
  • Migrated DisputeChatNotifier to use centralized SubscriptionManager for event handling (aligning with Chat P2P pattern)
  • Added early initialization of DisputeChatNotifier during restore when orders contain admin keys (matching Chat P2P behavior)
  • Reordered message loading to fetch historical data before establishing live event subscriptions (consistent with Chat P2P flow)
  • Fixed message loss during restoration by activating notifier before events arrive (following Chat P2P approach)
  • Established dedicated dispute_chat_provider.dart file to consolidate provider setup and initialization
  • Added _initializeDisputeChatSafely() helper with error handling and mounted state verification matching P2P chat pattern
  • Restored dispute initiator detection using server-provided initiator field rather than client-side trade-index calculation (originally added in Check initiator to restored dispute data #497, removed in feat: implement NIP-13 proof-of-work mining for Mostro events #519)
  • Extended restoration delay period to capture complete message history before marking restore complete
  • Populated disputeId field in session objects during restore when disputes exist
  • Built sessionForDisputeProvider using synchronous lookup through in-memory session list filtered by disputeId
  • Eliminated async disputeDetailsProvider dependency that created timing issues during app initialization
  • Converted session retrieval from async FutureProvider approach to synchronous Provider approach (matching P2P chat design)
  • Resolved premature exit in _loadHistoricalMessages() that occurred when session was null during async provider loading

Summary by CodeRabbit

  • New Features

    • Disputes now include solver public key information.
  • Improvements

    • Enhanced dispute chat initialization with improved state tracking.
    • Refactored dispute chat subscription management for better reliability.
    • Updated dispute restoration process with optimized message loading timing.
    • Simplified dispute initiator detection using server-provided data.

BraCR10 and others added 5 commits April 2, 2026 03:29
When restoring an account, ensure that the dispute solver's pubkey is recovered and associated with the session. This allows the user to continue dispute chats with the assigned admin after the restoration process.
Refactor DisputeChatNotifier to use a centralized SubscriptionManager for event handling and ensure the notifier is active during the account restore process. This prevents missing historical messages when restoring disputes with assigned admins.

- Use SubscriptionManager for dispute chat subscriptions.
- Pre-initialize DisputeChatNotifier in RestoreService when admin keys are present.
- Load historical messages before subscribing to the live event stream.
- Centralize dispute chat providers and safe initialization handling into a dedicated provider file.
- Simplify dispute initiator detection during account restoration by using the server-provided initiator field instead of manual trade-index comparisons.
- Improve dispute chat subscription management and increase the restoration delay to ensure all historical messages are captured.
- Update dart_nostr and websocket dependencies.
Changes:
- Assign disputeId to sessions during restore to enable direct lookup
- Change sessionForDisputeProvider to use synchronous search by disputeId instead of async disputeDetailsProvider
- Remove dependency on FutureProvider that caused race condition during initialization

This fixes the issue where dispute chat messages would not appear after killing and reopening the app, as the async provider dependency prevented finding the session during initial load.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

Walkthrough

A solverPubkey field is added to the RestoredDispute model. The dispute chat notifier is refactored to use a centralized provider-based session lookup (sessionForDisputeProvider) and consolidated subscription manager instead of direct per-notifier subscriptions. Multiple dispute widgets and services are updated to import from a new dispute_chat_provider.dart module. The restore flow is enhanced to initialize dispute chat listeners with server-provided session metadata during restoration.

Changes

Cohort / File(s) Summary
Dispute Model Enhancement
lib/data/models/restore_response.dart
Added optional solverPubkey field to RestoredDispute class; updated constructor, fromJson, and toJson to handle nullable string mapping.
Dispute Chat Notifier Refactoring
lib/features/disputes/notifiers/dispute_chat_notifier.dart
Removed session discovery imports and _getSessionForDispute() method; replaced with ref.read(sessionForDisputeProvider(disputeId)) calls; transitioned from per-notifier Nostr subscription logic to centralized SubscriptionManager stream source; updated session-list listening from global sessionNotifierProvider to individual sessionForDisputeProvider; added public subscribe() method; removed exported disputeChatNotifierProvider.
Dispute Chat Provider Module
lib/features/disputes/notifiers/dispute_chat_provider.dart
New file introducing sessionForDisputeProvider, disputeChatNotifierProvider, and disputeChatInitializedProvider; implements safe initialization via _initializeDisputeChatSafely with try/catch logging and mounted-state checks.
Dispute Widgets Import Migration
lib/features/disputes/widgets/dispute_content.dart, lib/features/disputes/widgets/dispute_message_bubble.dart, lib/features/disputes/widgets/dispute_message_input.dart, lib/features/disputes/widgets/dispute_messages_list.dart
Updated imports from dispute_chat_notifier.dart to dispute_chat_provider.dart; provider references remain syntactically unchanged.
Restore Manager Integration
lib/features/restore/restore_manager.dart
Added dispute_chat_provider.dart dependency; integrated dispute-chat listener initialization when solverPubkey is present; extended session creation to include adminPubkey and disputeId from restored dispute metadata; replaced local dispute-initiator detection with server-provided initiator field comparison; increased historical-message wait from 10 to 15 seconds.
Service Import Update
lib/services/dispute_read_status_service.dart
Updated import from dispute_chat_notifier.dart to dispute_chat_provider.dart for DisputeChatMessage definition.

Sequence Diagram

sequenceDiagram
    participant RM as RestoreManager
    participant SP as sessionForDisputeProvider
    participant SN as sessionNotifierProvider
    participant DCN as DisputeChatNotifier
    participant SM as SubscriptionManager
    
    RM->>RM: restore(restoredDisputes)
    RM->>SP: Derive session for disputeId
    SP->>SN: Scan sessionNotifierProvider
    SN-->>SP: Match session by disputeId
    SP-->>RM: Return Session?
    
    alt Session with adminSharedKey available
        RM->>DCN: initialize()
        DCN->>SP: ref.read(sessionForDisputeProvider)
        SP-->>DCN: Session?
        
        DCN->>DCN: _loadHistoricalMessages
        DCN->>SM: disputeChat.listen(_onChatEvent)
        SM-->>DCN: Chat event stream
        DCN->>DCN: _onChatEvent (validate kind 1059, p tag)
    else solverPubkey present
        RM->>DCN: subscribe()
        DCN->>SM: Attach listener
    end
    
    RM-->>RM: Restore complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • Dispute chat messages cannot be sent/received after account restore #508: Changes directly address the session/key reconstruction and dispute-chat resubscription code paths reported in the restore-time chat failure by introducing solverPubkey field, centralizing session lookup via sessionForDisputeProvider, and initializing dispute chat listeners during restore with server-provided metadata.

Possibly related PRs

Suggested reviewers

  • Catrya
  • mostronatorcoder
  • grunch

Poem

🐰 Whiskers twitch with glee—
Sessions sync, disputes now flow,
Provider wires bright, restore's anew,
Chat streams listen, solverKeys gleam,
Hops forward through the digital green! 🌿

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Restore dispute chats' directly describes the main objective of the PR—restoring dispute chat functionality during account recovery—and accurately reflects the primary changes across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/chat-admin-restore

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
lib/features/disputes/notifiers/dispute_chat_provider.dart (1)

1-35: Move this provider module under features/disputes/providers/.

This file introduces Riverpod providers from the notifiers/ tree, which makes provider wiring harder to discover and diverges from the repository layout.

As per coding guidelines, "Use Riverpod for all state management and organize providers by feature in features/{feature}/providers/".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/features/disputes/notifiers/dispute_chat_provider.dart` around lines 1 -
35, Move this provider module out of features/disputes/notifiers and into
features/disputes/providers to follow the repository layout; update any imports
that reference this file accordingly. Ensure the exported symbols
(sessionForDisputeProvider, disputeChatNotifierProvider,
disputeChatInitializedProvider) and the internal initializer usage
(_initializeDisputeChatSafely and DisputeChatNotifier) still resolve after the
move by adjusting import paths for
mostro_mobile/features/disputes/notifiers/dispute_chat_notifier.dart (where
DisputeChatNotifier and the initializer live) and any files that currently
import this provider file. Keep the re-export of dispute_chat_notifier.dart
consistent (exporting the notifier types) and run a project-wide search to
update all import locations to the new
features/disputes/providers/<filename>.dart path.
🤖 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`:
- Around line 129-133: The notifier currently creates a second independent
listener by calling subscriptionManager.disputeChat.listen(_onChatEvent)
directly, which can lead to duplicate event processing; replace those direct
listens with a call to the notifier's existing _subscribe() method so the
notifier maintains a single subscription (update the block using
subscriptionManager.disputeChat and the similar block at 145-157 to call
_subscribe() instead of assigning _subscription =
subscriptionManager.disputeChat.listen(...)), ensuring _subscription and
_onChatEvent remain the single source of truth for subscription lifecycle.

In `@lib/features/disputes/notifiers/dispute_chat_provider.dart`:
- Around line 47-50: The mounted check currently re-reads
disputeChatNotifierProvider(disputeId).notifier which can create a new notifier;
instead use the existing notifier parameter directly (notifier.mounted) when
gating initialization and state updates; update both checks that read
ref.container.read(disputeChatNotifierProvider(disputeId).notifier).mounted to
use notifier.mounted and then set
ref.read(disputeChatInitializedProvider(disputeId).notifier).state = true only
when notifier.mounted is true.
- Around line 22-35: The family providers for dispute chats are not being torn
down and leave stale notifiers with active subscriptions across restore; update
disputeChatNotifierProvider and disputeChatInitializedProvider to be
auto-disposed (add .autoDispose() to their declarations) so Riverpod will clean
them up automatically, or alternatively implement tracking of active dispute IDs
and call ref.invalidate for each tracked dispute notifier
(ref.invalidate(disputeChatNotifierProvider(id)) and
ref.invalidate(disputeChatInitializedProvider(id))) inside _clearAll() before
restore() runs to ensure all notifiers are unsubscribed and disposed; locate the
symbols disputeChatNotifierProvider, disputeChatInitializedProvider,
_clearAll(), restore(), and the call to .subscribe() to apply the chosen fix.

In `@lib/features/restore/restore_manager.dart`:
- Around line 624-625: Remove the explicit subscribe() call: when adminPubkey
and restoredDispute are non-null simply read the provider to trigger
_initializeDisputeChatSafely(); do not call
ref.read(disputeChatNotifierProvider(restoredDispute.disputeId).notifier).subscribe()
because _initializeDisputeChatSafely() (invoked by reading the provider) already
awaits notifier.initialize(), and initialize() calls _subscribe() internally—so
delete the subscribe() invocation to avoid the race condition between
subscribe() and initialize() for disputeChatNotifierProvider,
_initializeDisputeChatSafely, initialize, and _subscribe.

---

Nitpick comments:
In `@lib/features/disputes/notifiers/dispute_chat_provider.dart`:
- Around line 1-35: Move this provider module out of features/disputes/notifiers
and into features/disputes/providers to follow the repository layout; update any
imports that reference this file accordingly. Ensure the exported symbols
(sessionForDisputeProvider, disputeChatNotifierProvider,
disputeChatInitializedProvider) and the internal initializer usage
(_initializeDisputeChatSafely and DisputeChatNotifier) still resolve after the
move by adjusting import paths for
mostro_mobile/features/disputes/notifiers/dispute_chat_notifier.dart (where
DisputeChatNotifier and the initializer live) and any files that currently
import this provider file. Keep the re-export of dispute_chat_notifier.dart
consistent (exporting the notifier types) and run a project-wide search to
update all import locations to the new
features/disputes/providers/<filename>.dart path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c451ba63-46cc-416c-8b24-6c922fccdd87

📥 Commits

Reviewing files that changed from the base of the PR and between fca09d4 and 4b77116.

📒 Files selected for processing (9)
  • lib/data/models/restore_response.dart
  • lib/features/disputes/notifiers/dispute_chat_notifier.dart
  • lib/features/disputes/notifiers/dispute_chat_provider.dart
  • lib/features/disputes/widgets/dispute_content.dart
  • lib/features/disputes/widgets/dispute_message_bubble.dart
  • lib/features/disputes/widgets/dispute_message_input.dart
  • lib/features/disputes/widgets/dispute_messages_list.dart
  • lib/features/restore/restore_manager.dart
  • lib/services/dispute_read_status_service.dart

Comment on lines +129 to +133
// Use SubscriptionManager to subscribe to dispute chat events
// This is managed centrally and handles all sessions with adminSharedKey
final subscriptionManager = ref.read(subscriptionManagerProvider);
_subscription = subscriptionManager.disputeChat.listen(_onChatEvent);
logger.i('Subscribed to dispute chat via SubscriptionManager for dispute: $disputeId');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Re-use _subscribe() here to keep the notifier single-subscribed.

There are now two independent disputeChat.listen(_onChatEvent) paths. Since SubscriptionManager.disputeChat is broadcast (lib/features/subscriptions/subscription_manager.dart:26-31), a restore-triggered subscribe() can overlap with this callback and the same live event will be processed twice by this notifier.

♻️ Proposed fix
           unawaited(() async {
             await _loadHistoricalMessages();
             if (!mounted) return;
-            final subscriptionManager = ref.read(subscriptionManagerProvider);
-            _subscription = subscriptionManager.disputeChat.listen(_onChatEvent);
+            await _subscribe();
           }());

Also applies to: 145-157

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/features/disputes/notifiers/dispute_chat_notifier.dart` around lines 129
- 133, The notifier currently creates a second independent listener by calling
subscriptionManager.disputeChat.listen(_onChatEvent) directly, which can lead to
duplicate event processing; replace those direct listens with a call to the
notifier's existing _subscribe() method so the notifier maintains a single
subscription (update the block using subscriptionManager.disputeChat and the
similar block at 145-157 to call _subscribe() instead of assigning _subscription
= subscriptionManager.disputeChat.listen(...)), ensuring _subscription and
_onChatEvent remain the single source of truth for subscription lifecycle.

Comment on lines +22 to +35
final disputeChatNotifierProvider =
StateNotifierProvider.family<DisputeChatNotifier, DisputeChatState, String>(
(ref, disputeId) {
final notifier = DisputeChatNotifier(disputeId, ref);

// Initialize the notifier with proper error handling and safety checks
_initializeDisputeChatSafely(ref, notifier, disputeId);

return notifier;
},
);

// Provider to track initialization status of dispute chats
final disputeChatInitializedProvider = StateProvider.family<bool, String>((ref, disputeId) => false);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Expectation: either these providers are auto-disposed, or restore cleanup explicitly invalidates them.
printf '\n--- dispute chat provider declarations ---\n'
sed -n '15,38p' lib/features/disputes/notifiers/dispute_chat_provider.dart
printf '\n--- restore cleanup ---\n'
sed -n '78,105p' lib/features/restore/restore_manager.dart

Repository: MostroP2P/mobile

Length of output: 2179


🏁 Script executed:

#!/bin/bash
# Check the full provider declarations for autoDispose usage
printf '\n--- Full dispute chat provider file ---\n'
cat -n lib/features/disputes/notifiers/dispute_chat_provider.dart | head -50

printf '\n--- Search for disputeChatNotifier invalidations ---\n'
rg -i 'disputeChat.*invalidate|invalidate.*disputeChat' -A 2 -B 2

printf '\n--- Search for autoDispose in dispute providers ---\n'
rg 'autoDispose' lib/features/disputes/notifiers/dispute_chat_provider.dart

printf '\n--- Check if there is any active dispute tracking ---\n'
rg -i 'activeDispute|dispute.*id.*list|track.*dispute' lib/features/disputes/ -A 2 | head -30

Repository: MostroP2P/mobile

Length of output: 4963


🏁 Script executed:

#!/bin/bash
# Check restore_manager.dart for dispute-related restoration and cleanup
printf '\n--- Full restore_manager.dart cleanup section ---\n'
cat -n lib/features/restore/restore_manager.dart | grep -A 50 '_clearAll'

printf '\n--- Search for dispute restoration in restore_manager ---\n'
rg -i 'dispute|chat.*restore' lib/features/restore/restore_manager.dart -B 2 -A 2

printf '\n--- Check DisputeChatNotifier for subscription cleanup ---\n'
grep -n 'dispose\|subscription\|stream' lib/features/disputes/notifiers/dispute_chat_notifier.dart

Repository: MostroP2P/mobile

Length of output: 11978


Add an explicit teardown strategy for dispute chat family providers.

These family providers lack autoDispose() and are not cleaned up during restore. When restore() is called, it subscribes to dispute chat notifiers via ref.read(disputeChatNotifierProvider(restoredDispute.disputeId).notifier).subscribe() for each restored dispute, but _clearAll() only invalidates chat room providers—not dispute providers. This leaves stale dispute notifiers with active subscriptions in memory across restores, creating a resource leak.

Either add .autoDispose() to both disputeChatNotifierProvider and disputeChatInitializedProvider, or track active dispute IDs and explicitly invalidate them in _clearAll() before restore.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/features/disputes/notifiers/dispute_chat_provider.dart` around lines 22 -
35, The family providers for dispute chats are not being torn down and leave
stale notifiers with active subscriptions across restore; update
disputeChatNotifierProvider and disputeChatInitializedProvider to be
auto-disposed (add .autoDispose() to their declarations) so Riverpod will clean
them up automatically, or alternatively implement tracking of active dispute IDs
and call ref.invalidate for each tracked dispute notifier
(ref.invalidate(disputeChatNotifierProvider(id)) and
ref.invalidate(disputeChatInitializedProvider(id))) inside _clearAll() before
restore() runs to ensure all notifiers are unsubscribed and disposed; locate the
symbols disputeChatNotifierProvider, disputeChatInitializedProvider,
_clearAll(), restore(), and the call to .subscribe() to apply the chosen fix.

Comment on lines +47 to +50
// Check if the provider is still mounted before updating state
// This prevents state updates on disposed objects
if (ref.container.read(disputeChatNotifierProvider(disputeId).notifier).mounted) {
ref.read(disputeChatInitializedProvider(disputeId).notifier).state = true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Expectation: mounted checks should use the notifier already in hand, not recreate/read the provider again.
rg -n -C3 'container\.read\(disputeChatNotifierProvider\(disputeId\)\.notifier\)\.mounted|_initializeDisputeChatSafely' lib/features/disputes/notifiers/dispute_chat_provider.dart

Repository: MostroP2P/mobile

Length of output: 1336


Use the notifier parameter directly instead of re-reading the provider for mounted checks.

The code re-reads disputeChatNotifierProvider(disputeId).notifier to check if it's mounted, which can instantiate a fresh notifier after disposal. Since the notifier is already available as a function parameter, use notifier.mounted directly. Re-reading the provider may succeed on a new notifier and incorrectly rerun initialization logic.

Apply at lines 49 and 64:

  • Replace ref.container.read(disputeChatNotifierProvider(disputeId).notifier).mounted with notifier.mounted
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/features/disputes/notifiers/dispute_chat_provider.dart` around lines 47 -
50, The mounted check currently re-reads
disputeChatNotifierProvider(disputeId).notifier which can create a new notifier;
instead use the existing notifier parameter directly (notifier.mounted) when
gating initialization and state updates; update both checks that read
ref.container.read(disputeChatNotifierProvider(disputeId).notifier).mounted to
use notifier.mounted and then set
ref.read(disputeChatInitializedProvider(disputeId).notifier).state = true only
when notifier.mounted is true.

Comment on lines +624 to +625
if (adminPubkey != null && restoredDispute != null) {
ref.read(disputeChatNotifierProvider(restoredDispute.disputeId).notifier).subscribe();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Expectation: if `initialize()` already subscribes (directly or via SubscriptionManager),
# restore should only instantiate/read the provider here, not call `subscribe()` again.
printf '\n--- provider bootstrap ---\n'
sed -n '21,34p' lib/features/disputes/notifiers/dispute_chat_provider.dart
printf '\n--- initialize/subscribe definitions ---\n'
rg -n -C3 '\bFuture<.*initialize\b|\bvoid\s+subscribe\b|\bsubscribe\s*\(' lib/features/disputes/notifiers/dispute_chat_notifier.dart

Repository: MostroP2P/mobile

Length of output: 1163


🏁 Script executed:

#!/bin/bash
# Find the _initializeDisputeChatSafely function implementation
printf '\n--- _initializeDisputeChatSafely implementation ---\n'
rg -n -A 15 '_initializeDisputeChatSafely' lib/features/disputes/notifiers/dispute_chat_provider.dart

printf '\n--- Full DisputeChatNotifier initialize and _subscribe methods ---\n'
rg -n -A 10 'Future<void> initialize|void _subscribe|Future<void> subscribe' lib/features/disputes/notifiers/dispute_chat_notifier.dart

Repository: MostroP2P/mobile

Length of output: 1986


🏁 Script executed:

#!/bin/bash
# Check _subscribe implementation for duplicate call safeguards
printf '\n--- _subscribe implementation (full) ---\n'
rg -n -A 30 'Future<void> _subscribe' lib/features/disputes/notifiers/dispute_chat_notifier.dart | head -50

# Check if there are any subscription state guards
printf '\n--- Check for subscription state tracking ---\n'
rg -n '_subscription|_isSubscribed|_subscriptionId' lib/features/disputes/notifiers/dispute_chat_notifier.dart

Repository: MostroP2P/mobile

Length of output: 1840


Remove the explicit subscribe() call since _initializeDisputeChatSafely() already subscribes via initialize().

When you read the provider, _initializeDisputeChatSafely() is fired (though not awaited in the factory), which calls await notifier.initialize(). The initialize() method already calls _subscribe() internally, so the explicit subscribe() call creates a race condition. If subscribe() executes before initialization completes, it may subscribe before historical messages are loaded. If it executes after, it unnecessarily cancels and recreates the subscription. Simply reading the provider is sufficient to trigger initialization.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/features/restore/restore_manager.dart` around lines 624 - 625, Remove the
explicit subscribe() call: when adminPubkey and restoredDispute are non-null
simply read the provider to trigger _initializeDisputeChatSafely(); do not call
ref.read(disputeChatNotifierProvider(restoredDispute.disputeId).notifier).subscribe()
because _initializeDisputeChatSafely() (invoked by reading the provider) already
awaits notifier.initialize(), and initialize() calls _subscribe() internally—so
delete the subscribe() invocation to avoid the race condition between
subscribe() and initialize() for disputeChatNotifierProvider,
_initializeDisputeChatSafely, initialize, and _subscribe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant