Skip to content

Conversation

@Catrya
Copy link
Member

@Catrya Catrya commented Dec 11, 2025

fix #358

Remove 48-hour subtraction hack from timeAgoWithLocale() that caused orders to show "in X days" instead of "X time ago". Now uses actual created_at timestamp for accurate relative time display.

  • Remove buggy _timeAgo() method and expiration property
  • Update timeAgoWithLocale() to use _timeAgoFromCreated()
  • Fix broken usage in mostro_message_detail_widget.dart

Summary by CodeRabbit

  • Bug Fixes
    • Improved timestamp accuracy by updating time-ago display logic to reflect message creation time.
    • Standardized order expiration to consistently display 24-hour window.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Walkthrough

The changes fix timestamp display for newly created orders by basing time calculations on creation time rather than expiration time, ensuring consistent display regardless of Mostrod configuration.

Changes

Cohort / File(s) Summary
Time calculation refactoring
lib/data/models/nostr_event.dart
Removed public expiration getter. Replaced _timeAgo helper with new private _timeAgoFromCreated([String? locale]) that calculates relative time from createdAt instead of expiration timestamp. Updated timeAgoWithLocale(locale) to use the new method with default locale 'es'.
Widget message formatting
lib/features/trades/widgets/mostro_message_detail_widget.dart
Removed import of nostr_event.dart. In MostroMessageDetail._getActionText, hardcoded newOrder branch expiration to 24 hours instead of dynamically reading mostroInstance.expiration, with a TODO comment for future use of mostroInstance.expirationHours.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Review focus: Validate that the shift from expiration-based to creation-based time calculation resolves the timestamp display issue across different Mostrod configurations
  • Verify that the default locale 'es' in _timeAgoFromCreated is intentional and consistent with codebase conventions
  • Confirm that hardcoding 24-hour expiration in the widget aligns with expected behavior pending the TODO resolution

Possibly related PRs

  • #354: Introduces new expiresAt getter and shifts countdown logic to use explicit expires_at/createdAt timestamps instead of dynamic expiration-based calculations
  • #235: Adjusts internal time subtraction logic within _timeAgo method—related to the same time-ago functionality being refactored here
  • #150: Modifies expiration value handling in _getActionText for invoice-related cases, similar pattern to the hardcoded 24-hour change in this PR

Suggested reviewers

  • grunch

Poem

🐰 Time tells no lies when createdAt's your guide,
No more does expiration twist the tide,
Orders bloom with truth, "just now" they sing,
Twenty-four and steady, no future fling!

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the primary change: fixing the bug where order creation time display was incorrectly based on expiration hours instead of the actual created_at timestamp.
Linked Issues check ✅ Passed The pull request directly addresses all requirements from issue #358: removes the 48-hour subtraction hack, replaces _timeAgo() with _timeAgoFromCreated() using created_at timestamp, and fixes mostro_message_detail_widget.dart usage.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the order creation time display bug referenced in issue #358; no unrelated modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-created-at

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
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: 1

🧹 Nitpick comments (1)
lib/data/models/nostr_event.dart (1)

63-68: LGTM! Solid implementation with defensive null handling.

The method correctly uses createdAt for time-ago calculation, which resolves the core issue. The null check and default locale handling are appropriate.

Optional: Consider whether allowFromNow: true is needed. Since createdAt should always be in the past for existing orders, this parameter might be unnecessary:

-    return timeago.format(createdAt!, allowFromNow: true, locale: effectiveLocale);
+    return timeago.format(createdAt!, locale: effectiveLocale);

However, keeping it provides defensive handling if createdAt is somehow in the future, so this is a minor style consideration.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c257dc and 27c6558.

📒 Files selected for processing (2)
  • lib/data/models/nostr_event.dart (2 hunks)
  • lib/features/trades/widgets/mostro_message_detail_widget.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{dart,flutter}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{dart,flutter}: Run flutter analyze after any code change - Mandatory before commits to ensure zero linting issues
Run flutter test after any code change - Mandatory before commits to ensure all unit tests pass

Files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
  • lib/data/models/nostr_event.dart
**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.dart: Use Riverpod for all state management - encapsulate business logic in Notifiers and access data only through repository classes
All code comments must be in English - use clear, concise English for variable names, function names, and comments
Always check mounted before using BuildContext after async operations to prevent errors on disposed widgets
Use const constructors where possible for better performance and immutability
Remove unused imports and dependencies to maintain code cleanliness and reduce build size

**/*.dart: Application code should be organized under lib/, grouped by domain with lib/features/<feature>/ structure, shared utilities in lib/shared/, dependency wiring in lib/core/, and services in lib/services/
Persistence, APIs, and background jobs should live in lib/data/ and lib/background/; generated localization output must be in lib/generated/ and must stay untouched
Apply flutter format . to enforce canonical Dart formatting (two-space indentation, trailing commas) before committing
Resolve every analyzer warning in Dart code
Name Riverpod providers using the <Feature>Provider or <Feature>Notifier convention
Localize all user-facing strings via ARB files and access them with S.of(context) rather than hard-coded literals

Files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
  • lib/data/models/nostr_event.dart
🧠 Learnings (21)
📓 Common learnings
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/shared/widgets/dynamic_countdown_widget.dart : Use exact `order_expires_at` timestamps from Mostro protocol for DynamicCountdownWidget precision and localize display with `S.of(context)!.timeLeftLabel()`
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/shared/widgets/dynamic_countdown_widget.dart : Use exact `order_expires_at` timestamps from Mostro protocol for DynamicCountdownWidget precision and localize display with `S.of(context)!.timeLeftLabel()`

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
  • lib/data/models/nostr_event.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/auth/notifiers/abstract_mostro_notifier.dart : Start 10-second cleanup timer automatically when taking orders via `startSessionTimeoutCleanup()` to prevent orphan sessions

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/orders/notifiers/add_order_notifier.dart : Start session timeout cleanup in `submitOrder()` method to prevent orphan sessions when Mostro doesn't respond within 10 seconds

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/auth/notifiers/abstract_mostro_notifier.dart : Use `startSessionTimeoutCleanupForRequestId()` for order creation timeout protection and cancel timer automatically when any Mostro response received

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/shared/widgets/dynamic_countdown_widget.dart : Implement DynamicCountdownWidget with automatic day/hour scaling: day scale (>24h) shows 'd h m' format, hour scale (≤24h) shows HH:MM:SS format

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/core/mostro_fsm.dart : Use MostroFSM for managing order state transitions - all state changes must go through FSM state methods

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-10-14T21:12:06.887Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:141-154
Timestamp: 2025-10-14T21:12:06.887Z
Learning: In the MostroP2P mobile codebase, the notification system uses a two-layer localization pattern: providers/notifiers (without BuildContext access) call `showCustomMessage()` with string keys (e.g., 'orderTimeoutMaker', 'orderCanceled'), and the UI layer's `NotificationListenerWidget` has a switch statement that maps these keys to localized strings using `S.of(context)`. This architectural pattern properly separates concerns while maintaining full localization support for all user-facing messages.

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-10-21T21:47:03.451Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-06-26T15:03:23.529Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 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.

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to **/*.dart : Use Riverpod for all state management - encapsulate business logic in Notifiers and access data only through repository classes

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-05-06T15:49:26.443Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 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.

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/**/providers/**/*.dart : Organize Riverpod providers by feature in `features/{feature}/providers/` using Notifier pattern for complex state logic

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/**/providers/**/*.dart : Use Notifier pattern instead of simple StateNotifier for complex state logic requiring business rule encapsulation

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-05-06T15:49:26.443Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 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.

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/**/notifiers/**/*.dart : Encapsulate business logic in Notifiers - Notifiers should expose state via providers and handle all complex state transitions

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:26.407Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-27T12:10:26.407Z
Learning: Applies to **/*.dart : Name Riverpod providers using the `<Feature>Provider` or `<Feature>Notifier` convention

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-06-04T19:35:20.209Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 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.

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-05-08T16:06:33.665Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/features/trades/models/trade_state.dart:1-15
Timestamp: 2025-05-08T16:06:33.665Z
Learning: In the context of the Mostro Mobile app, the `TradeState` class is specifically constructed using the `tradeStateProvider`. While some fields are nullable (`lastAction` and `orderPayload`), they are still marked as required parameters to ensure they are explicitly considered during state construction.

Applied to files:

  • lib/features/trades/widgets/mostro_message_detail_widget.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/main.dart : Configure timeago package locales in app initialization for proper relative time formatting (e.g., 'hace X horas' vs 'hours ago')

Applied to files:

  • lib/data/models/nostr_event.dart
📚 Learning: 2025-11-27T12:10:12.082Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/core/models/relay_list_event.dart : Parse NIP-65 (kind 10002) events with robust handling of different timestamp formats and null-safe parsing for malformed events

Applied to files:

  • lib/data/models/nostr_event.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (1)
lib/data/models/nostr_event.dart (1)

38-39: LGTM! Core bug fix implemented correctly.

The delegation to _timeAgoFromCreated(locale) ensures time-ago strings are now calculated from the actual createdAt timestamp rather than expiration-based logic, which fixes the future-relative display bug.

Comment on lines +62 to +63
final expHrs = 24; // TODO: use mostroInstance.expirationHours when available
return S.of(context)!.newOrder(expHrs);
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 11, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Temporary workaround: hardcoded expiration hours may not match actual Mostrod configuration.

The hardcoded value of 24 hours decouples the displayed message from the actual expiration_hours setting in Mostrod. If the instance uses a different value (e.g., 40 hours as mentioned in issue #358), the message will be inconsistent with the actual order expiration.

While this is preferable to the previous bug (showing future-relative times), please ensure the TODO is tracked. Do you want me to help verify when mostroInstance.expirationHours will be available, or open an issue to track this technical debt?

Note: Other actions in this file successfully use mostroInstance?.expirationSeconds (lines 67-71, 80-84, etc.), suggesting the issue is specifically with the availability of an expirationHours field rather than access to mostroInstance itself.

🤖 Prompt for AI Agents
lib/features/trades/widgets/mostro_message_detail_widget.dart lines 62-63:
replace the hardcoded expHrs=24 by deriving the value from the available
mostroInstance fields — if mostroInstance.expirationHours exists use it,
otherwise compute hours = (mostroInstance?.expirationSeconds ??
defaultSeconds)/3600 and use that as the displayed expiration; update the TODO
to track the technical debt (create an issue or add a clear TODO comment
referencing issue #358) and ensure null-safe access (use the nullable
mostroInstance) and a sensible default fallback so the displayed message always
reflects the instance configuration.

Copy link
Member Author

Choose a reason for hiding this comment

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

The hardcoded 24 hours maintains the existing behavior - before this PR, the buggy code was already always displaying 24 hours regardless of the actual mostroInstance configuration due to parsing expiration as a relative time string instead of using the proper expirationSeconds field.

This PR only fixes the critical "in X days" timestamp bug. The proper mostroInstance.expirationSeconds integration will be handled in a separate PR to avoid mixing concerns.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Catrya, thank you for the clarification! That makes sense—if the previous code was already displaying 24 hours regardless of configuration, then maintaining that behavior while fixing the critical timestamp bug is a reasonable approach. Separating the timestamp fix from the expiration hours integration keeps the PRs focused and easier to review.

The TODO comment in the code will serve as a reminder for the follow-up work. If you'd like, I can help track this by opening a GitHub issue to capture the technical debt (integrating mostroInstance.expirationSeconds for the newOrder action), but that's entirely optional.

Thanks for the context on the existing behavior! 👍


🧠 Learnings used
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/shared/widgets/dynamic_countdown_widget.dart : Use exact `order_expires_at` timestamps from Mostro protocol for DynamicCountdownWidget precision and localize display with `S.of(context)!.timeLeftLabel()`

Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 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.

Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/auth/notifiers/abstract_mostro_notifier.dart : Use `startSessionTimeoutCleanupForRequestId()` for order creation timeout protection and cancel timer automatically when any Mostro response received

Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/orders/notifiers/add_order_notifier.dart : Start session timeout cleanup in `submitOrder()` method to prevent orphan sessions when Mostro doesn't respond within 10 seconds

Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/core/mostro_fsm.dart : Use MostroFSM for managing order state transitions - all state changes must go through FSM state methods

Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T12:10:12.082Z
Learning: Applies to lib/features/auth/notifiers/abstract_mostro_notifier.dart : Start 10-second cleanup timer automatically when taking orders via `startSessionTimeoutCleanup()` to prevent orphan sessions

Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.

Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/features/trades/models/trade_state.dart:1-15
Timestamp: 2025-05-08T16:06:33.665Z
Learning: In the context of the Mostro Mobile app, the `TradeState` class is specifically constructed using the `tradeStateProvider`. While some fields are nullable (`lastAction` and `orderPayload`), they are still marked as required parameters to ensure they are explicitly considered during state construction.

Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:141-154
Timestamp: 2025-10-14T21:12:06.887Z
Learning: In the MostroP2P mobile codebase, the notification system uses a two-layer localization pattern: providers/notifiers (without BuildContext access) call `showCustomMessage()` with string keys (e.g., 'orderTimeoutMaker', 'orderCanceled'), and the UI layer's `NotificationListenerWidget` has a switch statement that maps these keys to localized strings using `S.of(context)`. This architectural pattern properly separates concerns while maintaining full localization support for all user-facing messages.

Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 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.

@Catrya Catrya requested a review from grunch December 18, 2025 18:54
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.

Error displaying when an order was created

2 participants