-
Notifications
You must be signed in to change notification settings - Fork 16
Enhanced Notifications #216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Fix #79 1. Full Message Decryption Integration - ✅ Added Riverpod integration to access session management - ✅ Implemented complete message decryption using existing unWrap method - ✅ Added session matching logic to find correct trade keys for decryption - ✅ Integrated with MostroMessage parsing for action extraction 2. Action-Based Notification System - ✅ Created comprehensive action-to-title mapping with user-friendly titles: - "Order Published", "Payment Required", "Bitcoin Released", etc. - ✅ Implemented protocol-compliant message content following Mostro suggestions: - "Your offer has been published! Please wait until another user picks your order." - "Please pay the hold invoice of 1000 Sats" - "Bitcoin has been released! Your invoice should be paid shortly." 3. Enhanced Payload & Deep Linking - ✅ Rich notification payload with action context: { "eventId": "abc123", "kind": "1059", "orderId": "order_456", "action": "release" } 4. Robust Error Handling - ✅ Graceful fallback to generic messages when: - Session not found for decryption - Message decryption fails - MostroMessage parsing errors - ✅ Comprehensive logging for debugging 5. Background Service Integration - ✅ Created showSimpleNotification() for background isolates without Riverpod - ✅ Updated both desktop and mobile background services - ✅ Maintained functionality when app is in background 🔧 Key Features Implemented: Smart Session Matching // Finds the correct trade key by matching event target pubkey Session? _findSessionForEvent(NostrEvent event, List<Session> sessions) Complete Message Decryption Flow // 1. Find session with matching trade key // 2. Decrypt using event.unWrap(session.tradeKey.private) // 3. Parse MostroMessage from decrypted JSON // 4. Extract action and payload for notification content Dynamic Content Generation - Payment Actions: Extract amounts from PaymentRequest/Order payloads - Error Actions: Extract specific error reasons from CantDo payloads - Status Updates: Context-aware messages for all trade states 📱 User Experience Improvements: Before: - Generic "New Mostro Event" for all notifications - No context about what action occurred - No payload for deep linking After: - Action-specific titles: "Payment Required", "Bitcoin Released" - Rich context messages: "Please pay the hold invoice of 1000 Sats" - Deep linking ready: Full payload with action and order details - Graceful degradation: Falls back to generic message if decryption fails 🔒 Security & Privacy: - Only kind 1059 events: Filters out all other event types - Session-based decryption: Uses correct trade keys for each order - No key exposure: Leverages existing secure key management - Error resilience: Never exposes sensitive data in error states Added New Localization Keys to ARB Files - English (intl_en.arb): Added 22+ new notification-specific keys including: - notificationChannelName, notificationChannelDescription - notificationOrderPublished, notificationOrderTaken, notificationPaymentRequired - notificationInvoiceRequired, notificationPaymentSent, notificationBitcoinReleased - notificationOrderCanceled, notificationDisputeStarted, notificationTradeComplete - And many more notification-specific strings with proper parameterization - Spanish (intl_es.arb): Added complete Spanish translations for all notification keys - Italian (intl_it.arb): Added complete Italian translations for all notification keys Updated Notification Service to Use Localized Strings - Modified lib/notifications/notification_service.dart to use Flutter's localization system - Implemented locale-aware notifications using ui.PlatformDispatcher.instance.locale - Updated all hardcoded strings to use proper localized methods - Both generic and action-based notifications now support multiple languages
WalkthroughThe changes overhaul the notification system to provide event-specific, localized, and context-aware notifications for Nostr events, especially of kind 1059. Notification logic now distinguishes between foreground and background app states, uses session data for decryption and message parsing, and supports richer notification content and payloads. Localization strings for notifications were added in English, Spanish, and Italian. Changes
Sequence Diagram(s)sequenceDiagram
participant App
participant MostroService
participant NotificationService
participant User
App->>MostroService: Receives Nostr event
MostroService->>NotificationService: showLocalNotificationFromService(event, ref)
NotificationService->>NotificationService: Check event kind (1059)
NotificationService->>NotificationService: Find session & decrypt content
NotificationService->>NotificationService: Parse message, determine action
NotificationService->>NotificationService: Generate localized title/message
NotificationService->>User: Show notification with payload
Estimated code review effort3 (~45 minutes) Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (8)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used📓 Path-based instructions (5)lib/**/*.dart📄 CodeRabbit Inference Engine (CLAUDE.md)
Files:
**/*.dart📄 CodeRabbit Inference Engine (CLAUDE.md)
Files:
lib/l10n/intl_{en,es,it}.arb📄 CodeRabbit Inference Engine (CLAUDE.md)
Files:
lib/l10n/*.arb📄 CodeRabbit Inference Engine (CLAUDE.md)
Files:
lib/l10n/**📄 CodeRabbit Inference Engine (CLAUDE.md)
Files:
🧠 Learnings (7)📓 Common learningslib/features/chat/screens/chat_rooms_list.dart (1)Learnt from: chebizarro lib/features/trades/widgets/mostro_message_detail_widget.dart (5)Learnt from: chebizarro Learnt from: CR Learnt from: CR Learnt from: chebizarro Learnt from: chebizarro lib/features/chat/screens/chat_room_screen.dart (1)Learnt from: chebizarro lib/notifications/notification_service.dart (19)Learnt from: CR Learnt from: CR Learnt from: chebizarro Learnt from: Catrya Learnt from: Catrya Learnt from: Catrya Learnt from: CR Learnt from: chebizarro Learnt from: chebizarro Learnt from: chebizarro Learnt from: CR Learnt from: CR Learnt from: CR Learnt from: CR Learnt from: CR Learnt from: CR Learnt from: CR Learnt from: CR Learnt from: CR lib/l10n/intl_es.arb (2)Learnt from: CR Learnt from: CR lib/l10n/intl_it.arb (2)Learnt from: CR Learnt from: CR 🪛 RuboCop (1.76.1)lib/l10n/intl_es.arb[warning] 736-736: Duplicated key in hash literal. (Lint/DuplicateHashKey) lib/l10n/intl_it.arb[warning] 744-744: Duplicated key in hash literal. (Lint/DuplicateHashKey) 🔇 Additional comments (17)
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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 (2)
lib/notifications/notification_service.dart (2)
89-119: Well-implemented retry logic with exponential backoff.The retry mechanism provides good resilience with configurable attempts and exponential backoff. The TODO comment about persistent queue is a good future enhancement.
Consider implementing the persistent queue for failed notifications to handle app crashes or long background periods:
+import 'package:shared_preferences/shared_preferences.dart'; + +class FailedNotificationQueue { + static const String _queueKey = 'failed_notifications'; + + static Future<void> add(String eventId) async { + final prefs = await SharedPreferences.getInstance(); + final queue = prefs.getStringList(_queueKey) ?? []; + if (!queue.contains(eventId)) { + queue.add(eventId); + await prefs.setStringList(_queueKey, queue); + } + } + + static Future<List<String>> getAndClear() async { + final prefs = await SharedPreferences.getInstance(); + final queue = prefs.getStringList(_queueKey) ?? []; + await prefs.remove(_queueKey); + return queue; + } +} // Optionally store failed notifications for later retry when app returns to foreground if (!success) { - // Store the event ID in a persistent queue for later retry - // await failedNotificationsQueue.add(event.id!); + await FailedNotificationQueue.add(event.id!); }
140-226: Excellent notification display implementation with proper localization.The notification functions correctly:
- Load localized strings based on platform locale
- Include rich payloads for notification tap handling
- Configure platform-specific settings appropriately
- Set high priority for trade-related notifications
Consider extracting the notification channel configuration to reduce duplication:
+NotificationDetails _getNotificationDetails(S localizations) { + return NotificationDetails( + android: AndroidNotificationDetails( + 'mostro_channel', + localizations.notificationChannelName, + channelDescription: localizations.notificationChannelDescription, + importance: Importance.max, + priority: Priority.high, + visibility: NotificationVisibility.public, + playSound: true, + enableVibration: true, + ticker: 'ticker', + icon: '@drawable/ic_notification', + ), + iOS: DarwinNotificationDetails( + presentAlert: true, + presentBadge: true, + presentSound: true, + interruptionLevel: InterruptionLevel.critical, + ), + ); +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
lib/background/background.dart(1 hunks)lib/background/desktop_background_service.dart(2 hunks)lib/l10n/intl_en.arb(1 hunks)lib/l10n/intl_es.arb(1 hunks)lib/l10n/intl_it.arb(1 hunks)lib/notifications/notification_service.dart(3 hunks)lib/services/mostro_service.dart(2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
lib/**/*.dart
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- CLAUDE.md
**/*.dart
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- CLAUDE.md
lib/background/**/*.dart
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- CLAUDE.md
lib/l10n/intl_{en,es,it}.arb
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- CLAUDE.md
lib/l10n/*.arb
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- CLAUDE.md
lib/l10n/**
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- CLAUDE.md
🧠 Learnings (8)
📓 Common learnings
Learnt from: chebizarro
PR: MostroP2P/mobile#127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/background/background.dart:74-77
Timestamp: 2025-05-08T16:29:52.154Z
Learning: In the Mostro Mobile background service architecture, events aren't stored by the background process. Instead, the background service only checks if events exist in the eventStore and sends notifications for new ones, while the foreground process is responsible for storing and processing events. This is an intentional design decision to separate concerns.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Encapsulate business logic in Notifiers
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/data/models/nostr_event.dart : Custom `timeAgoWithLocale()` method is implemented in the NostrEvent extension
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/features/*/notifiers/**/*.dart : Notifiers for complex state logic are placed in `features/{feature}/notifiers/`
lib/background/desktop_background_service.dart (14)
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/background/**/*.dart : Background services are implemented in the `background/` directory
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/features/*/notifiers/**/*.dart : Notifiers for complex state logic are placed in `features/{feature}/notifiers/`
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/services/nostr_service.dart : Nostr protocol interactions go through `services/nostr_service.dart`
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.305Z
Learning: Applies to test/mocks.mocks.dart : DO NOT modify `test/mocks.mocks.dart` - it already has file-level ignores
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/background/background.dart:74-77
Timestamp: 2025-05-08T16:29:52.154Z
Learning: In the Mostro Mobile background service architecture, events aren't stored by the background process. Instead, the background service only checks if events exist in the eventStore and sends notifications for new ones, while the foreground process is responsible for storing and processing events. This is an intentional design decision to separate concerns.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/shared/providers/mostro_database_provider.dart : Database initialization is in `shared/providers/mostro_database_provider.dart`
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, `eventStorageProvider` is exported from `package:mostro_mobile/shared/providers/mostro_service_provider.dart` and not from a separate `event_storage_provider.dart` file.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/data/models.dart : Models should be exported through `data/models.dart`
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, Riverpod code generation is used with `@Riverpod` annotations. Providers like `eventStorageProvider` are generated in `.g.dart` files from annotated functions in the main provider files. These providers are accessible by importing the main provider file (e.g., `mostro_service_provider.dart`), not by importing a separate provider file.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/data/repositories/**/*.dart : All data access should go through repository classes in `data/repositories/`
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/features/*/providers/**/*.dart : Providers are organized by feature in `features/{feature}/providers/`
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
lib/services/mostro_service.dart (13)
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, `eventStorageProvider` is exported from `package:mostro_mobile/shared/providers/mostro_service_provider.dart` and not from a separate `event_storage_provider.dart` file.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/services/nostr_service.dart : Nostr protocol interactions go through `services/nostr_service.dart`
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/background/background.dart:74-77
Timestamp: 2025-05-08T16:29:52.154Z
Learning: In the Mostro Mobile background service architecture, events aren't stored by the background process. Instead, the background service only checks if events exist in the eventStore and sends notifications for new ones, while the foreground process is responsible for storing and processing events. This is an intentional design decision to separate concerns.
Learnt from: chebizarro
PR: MostroP2P/mobile#127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/features/*/notifiers/**/*.dart : Notifiers for complex state logic are placed in `features/{feature}/notifiers/`
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/background/**/*.dart : Background services are implemented in the `background/` directory
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, Riverpod code generation is used with `@Riverpod` annotations. Providers like `eventStorageProvider` are generated in `.g.dart` files from annotated functions in the main provider files. These providers are accessible by importing the main provider file (e.g., `mostro_service_provider.dart`), not by importing a separate provider file.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/shared/providers/mostro_database_provider.dart : Database initialization is in `shared/providers/mostro_database_provider.dart`
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/features/*/providers/**/*.dart : Providers are organized by feature in `features/{feature}/providers/`
Learnt from: chebizarro
PR: MostroP2P/mobile#110
File: test/notifiers/take_order_notifier_test.dart:72-74
Timestamp: 2025-06-04T19:35:20.209Z
Learning: MostroService methods like takeBuyOrder() and takeSellOrder() return Future<void> and trigger side effects through other mechanisms rather than direct return values. When testing these methods, focus on verifying method calls and testing state changes through the provider system rather than mocking return values.
lib/background/background.dart (9)
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/background/background.dart:74-77
Timestamp: 2025-05-08T16:29:52.154Z
Learning: In the Mostro Mobile background service architecture, events aren't stored by the background process. Instead, the background service only checks if events exist in the eventStore and sends notifications for new ones, while the foreground process is responsible for storing and processing events. This is an intentional design decision to separate concerns.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/background/**/*.dart : Background services are implemented in the `background/` directory
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/features/*/notifiers/**/*.dart : Notifiers for complex state logic are placed in `features/{feature}/notifiers/`
Learnt from: chebizarro
PR: MostroP2P/mobile#127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/notifications/notification_service.dart:54-59
Timestamp: 2025-05-08T16:31:29.582Z
Learning: In the Nostr protocol, event.id will never be null in events returned by relay subscriptions, so null safety checks for this property are unnecessary.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.305Z
Learning: Applies to test/mocks.mocks.dart : DO NOT modify `test/mocks.mocks.dart` - it already has file-level ignores
lib/l10n/intl_en.arb (3)
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/l10n/intl_{en,es,it}.arb : Add new localization keys to all three ARB files (`intl_en.arb`, `intl_es.arb`, `intl_it.arb`)
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/l10n/*.arb : Use proper ARB metadata for parameterized strings
Learnt from: chebizarro
PR: MostroP2P/mobile#127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.
lib/notifications/notification_service.dart (16)
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/features/*/notifiers/**/*.dart : Notifiers for complex state logic are placed in `features/{feature}/notifiers/`
Learnt from: chebizarro
PR: MostroP2P/mobile#127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/services/nostr_service.dart : Nostr protocol interactions go through `services/nostr_service.dart`
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.659Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/data/models/nostr_event.dart : Custom `timeAgoWithLocale()` method is implemented in the NostrEvent extension
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/background/background.dart:74-77
Timestamp: 2025-05-08T16:29:52.154Z
Learning: In the Mostro Mobile background service architecture, events aren't stored by the background process. Instead, the background service only checks if events exist in the eventStore and sends notifications for new ones, while the foreground process is responsible for storing and processing events. This is an intentional design decision to separate concerns.
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, Riverpod code generation is used with `@Riverpod` annotations. Providers like `eventStorageProvider` are generated in `.g.dart` files from annotated functions in the main provider files. These providers are accessible by importing the main provider file (e.g., `mostro_service_provider.dart`), not by importing a separate provider file.
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, `eventStorageProvider` is exported from `package:mostro_mobile/shared/providers/mostro_service_provider.dart` and not from a separate `event_storage_provider.dart` file.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/shared/providers/mostro_database_provider.dart : Database initialization is in `shared/providers/mostro_database_provider.dart`
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/core/mostro_fsm.dart : Order state transitions are managed by `core/mostro_fsm.dart`
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.305Z
Learning: Applies to test/mocks.mocks.dart : DO NOT modify `test/mocks.mocks.dart` - it already has file-level ignores
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/main.dart : Locales for the `timeago` package are configured in `main.dart` with `timeago.setLocaleMessages()`
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Use Riverpod for all state management
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/notifications/notification_service.dart:54-59
Timestamp: 2025-05-08T16:31:29.582Z
Learning: In the Nostr protocol, event.id will never be null in events returned by relay subscriptions, so null safety checks for this property are unnecessary.
lib/l10n/intl_es.arb (3)
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/l10n/intl_{en,es,it}.arb : Add new localization keys to all three ARB files (`intl_en.arb`, `intl_es.arb`, `intl_it.arb`)
Learnt from: chebizarro
PR: MostroP2P/mobile#127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/l10n/*.arb : Use proper ARB metadata for parameterized strings
lib/l10n/intl_it.arb (2)
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T01:48:43.306Z
Learning: Applies to lib/l10n/intl_{en,es,it}.arb : Add new localization keys to all three ARB files (`intl_en.arb`, `intl_es.arb`, `intl_it.arb`)
Learnt from: chebizarro
PR: MostroP2P/mobile#127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.
🪛 RuboCop (1.76.1)
lib/l10n/intl_es.arb
[warning] 732-732: Duplicated key in hash literal.
(Lint/DuplicateHashKey)
[warning] 733-733: Duplicated key in hash literal.
(Lint/DuplicateHashKey)
lib/l10n/intl_it.arb
[warning] 740-740: Duplicated key in hash literal.
(Lint/DuplicateHashKey)
[warning] 741-741: Duplicated key in hash literal.
(Lint/DuplicateHashKey)
🔇 Additional comments (9)
lib/background/desktop_background_service.dart (1)
9-9: LGTM! Proper notification handling for background isolate.The implementation correctly uses
showSimpleNotificationwhich is designed for background services without Riverpod context. The conditional check ensures notifications are only shown when the app is in the background, maintaining proper separation of concerns as per the architecture.Also applies to: 78-80
lib/services/mostro_service.dart (1)
14-14: LGTM! Well-integrated foreground notification handling.The notification trigger is properly placed after message storage and uses the correct
showLocalNotificationFromServiceoverload for services. The error handling ensures notification failures don't interrupt the core message processing flow.Also applies to: 98-103
lib/background/background.dart (1)
72-74: LGTM! Consistent background notification handling.The implementation correctly uses
showSimpleNotificationand only triggers notifications when the app is in the background. This maintains consistency with the desktop background service and aligns with the architectural principle of separation between foreground and background notification handling.lib/notifications/notification_service.dart (4)
37-44: Excellent API design with proper overloading.The dual API supporting both
WidgetRefandRefprovides flexibility for different contexts (UI components vs services) while maintaining a single implementation through delegation. This design maintains backward compatibility and reduces code duplication.
46-87: Robust notification processing with excellent error handling.The implementation correctly:
- Filters for kind 1059 events as per Nostr protocol
- Implements graceful degradation at each processing step
- Ensures users always receive notifications (generic fallback)
- Provides detailed error logging for debugging
The multi-step approach (session lookup → decryption → parsing → display) aligns perfectly with the PR objectives for enhanced notifications.
122-137: Correct session matching implementation.The function properly extracts the target public key from Nostr event tags and matches it against session trade keys. The use of
elementAtOrNulland try-catch ensures safe handling of malformed events.
341-348: Perfect implementation for background notification handling.The
showSimpleNotificationfunction provides exactly what background services need - a simple way to show generic notifications for kind 1059 events without requiring Riverpod context or session information.lib/l10n/intl_it.arb (1)
697-757: Comprehensive notification localization successfully added.The Italian notification strings are well-structured with proper ARB metadata and placeholder support. The translations provide appropriate context for various trade lifecycle events, payment statuses, and system notifications, aligning perfectly with the enhanced notification system objectives.
lib/l10n/intl_es.arb (1)
689-749: Excellent Spanish notification localization implementation.The Spanish notification strings are comprehensive and well-translated, providing clear and contextual messages for all notification scenarios. The ARB metadata is properly structured with appropriate placeholders for dynamic content, supporting the enhanced notification system's multilingual capabilities.
1. Fixed null amount values: Updated payInvoice and addInvoice cases to properly extract amount, fiatAmount, and fiatCode from the PaymentRequest and Order payloads 2. Added expandable notifications: Implemented BigTextStyleInformation for both action-based and generic notifications so users can see complete messages 3. Proper data extraction: The code now correctly accesses nested data structures (PaymentRequest.order.fiatCode, etc.) with proper null safety
1. Input Validation & Error Handling: Enhanced deterministicHandleFromHexKey function with:
- Null/empty string validation
- Hex character validation with regex
- Automatic padding/truncation for different string lengths
- Try-catch error handling around BigInt.parse()
- Fallback nickname generation using string hash
2. Null Safety Improvements: Updated multiple widgets to safely handle peer data:
- MostroMessageDetail widget: Added _getSafeNickname helper method
- ChatListItem widget: Safe access to peer publicKey
- ChatRoomScreen widget: Safe session and peer handling
- Replaced all unsafe session!.peer!.publicKey patterns with null-safe alternatives
3. Comprehensive Coverage: Fixed similar issues in all files that use nickname generation:
- lib/shared/providers/legible_handle_provider.dart
- lib/features/trades/widgets/mostro_message_detail_widget.dart
- lib/features/chat/screens/chat_rooms_list.dart
- lib/features/chat/screens/chat_room_screen.dart
✅ Results:
- No more "Could not parse BigInt" crashes when viewing trade details
- Graceful degradation with fallback nicknames for invalid/corrupted peer data
- Consistent user experience even when backend data has quality issues
- All Flutter analyze checks pass without errors
The app will now handle cases where:
- Peer public keys are null, empty, or contain invalid characters
- Public keys are shorter/longer than expected (64 characters)
- Session data is incomplete or corrupted
- Any BigInt parsing operation fails for any reason
Users like Alice can now view trade details without crashes, and the app will show
appropriate fallback nicknames when peer data is problematic.
|
closing in favor of #297 |
Fix #79
"eventId": "abc123", "kind": "1059", "orderId": "order_456", "action": "release" }
🔧 Key Features Implemented:
Smart Session Matching
// Finds the correct trade key by matching event target pubkey Session? _findSessionForEvent(NostrEvent event, List sessions)
Complete Message Decryption Flow
// 1. Find session with matching trade key
// 2. Decrypt using event.unWrap(session.tradeKey.private) // 3. Parse MostroMessage from decrypted JSON
// 4. Extract action and payload for notification content
Dynamic Content Generation
📱 User Experience Improvements:
Before:
After:
🔒 Security & Privacy:
Added New Localization Keys to ARB Files
Updated Notification Service to Use Localized Strings
Summary by CodeRabbit
New Features
Bug Fixes
Documentation