Skip to content

Add backup account reminder notification system#383

Merged
grunch merged 3 commits into
mainfrom
backup-notification
Dec 18, 2025
Merged

Add backup account reminder notification system#383
grunch merged 3 commits into
mainfrom
backup-notification

Conversation

@Catrya

@Catrya Catrya commented Dec 9, 2025

Copy link
Copy Markdown
Member

fix #363

  • Implement backup reminder notification that appears first in notifications list
  • Trigger reminder on first app launch and new user creation
  • Dismiss reminder only when user views seed phrase
  • Integrate with existing notification system without breaking functionality
  • Persist reminder state across app restarts using SharedPreferences
  • Add animated notification bell with shake animation when backup needed

Summary by CodeRabbit

  • New Features
    • Backup reminder prompts users to secure their account at key moments (registration, first run, after key generation).
    • Reminder appears in Notifications as a tappable item that navigates to key management.
    • Revealing the seed dismisses the reminder; users can also dismiss it and persist that choice.
    • Notification bell animates and shows a red cue/dot when a backup is pending.
    • Added English, Spanish, and Italian localization strings.

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

@coderabbitai

coderabbitai Bot commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a persisted BackupReminder state notifier and integrates a backup reminder UI and behavior across registration, walkthrough, key management, notifications list, and the notification bell; shows, animates, and persists dismissal of the reminder.

Changes

Cohort / File(s) Summary
Backup Reminder Provider
lib/features/notifications/providers/backup_reminder_provider.dart
New BackupReminderNotifier (StateNotifier) and backupReminderProvider; loads persisted dismissal flag from SharedPreferencesAsync, exposes showBackupReminder() and dismissBackupReminder(), and derives shouldShowBackupReminder.
Authentication & Onboarding
lib/features/auth/screens/register_screen.dart, lib/features/walkthrough/screens/walkthrough_screen.dart, lib/features/key_manager/key_management_screen.dart
Call backupReminderProvider.notifier.showBackupReminder() after key generation/registration/walkthrough completion; dismiss reminder when revealing seed phrase in key manager.
Notification UI Integration
lib/features/notifications/screens/notifications_screen.dart, lib/features/notifications/widgets/backup_reminder_notification.dart
Adds BackupReminderNotification widget; notifications screen accounts for the reminder item (adjusts itemCount, index mapping, and empty-state logic) and inserts the reminder at index 0 when active.
Notification Bell Widget
lib/shared/widgets/notification_history_bell_widget.dart
Converted NotificationBellWidget from ConsumerWidget to ConsumerStatefulWidget; adds an AnimationController and shake animation tied to backup reminder state, shows a red dot when reminder active and no unread notifications, and manages lifecycle/listener updates.
Localization
lib/l10n/intl_en.arb, lib/l10n/intl_es.arb, lib/l10n/intl_it.arb
Adds backupAccountReminder, backupAccountReminderMessage and comment keys; adjusted trailing commas to include new entries.

Sequence Diagram(s)

sequenceDiagram
    participant Screen as Auth/KeyMgmt/Walkthrough\nScreen
    participant Provider as BackupReminder\n(StateNotifier)
    participant SharedPrefs as SharedPreferencesAsync
    participant UI as Notifications\nScreen & Bell

    Note over Screen,Provider: user completes onboarding / generates key
    Screen->>Provider: showBackupReminder()
    Provider->>SharedPrefs: read/determine dismissed flag
    Provider-->>Provider: state = true (if not dismissed)

    Note over Provider,UI: UI observes provider state
    UI->>Provider: watch backupReminderProvider
    Provider-->>UI: state = true
    UI->>UI: render BackupReminderNotification\nstart bell shake animation

    alt user reveals seed phrase or taps dismiss
        Screen->>Provider: dismissBackupReminder()
        Provider->>SharedPrefs: persist dismissed = true
        Provider-->>UI: state = false
        UI->>UI: hide reminder\nstop animation
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review async initialization and persistence logic in backup_reminder_provider.dart.
  • Verify animation lifecycle, ref.listen usage, and disposal in notification_history_bell_widget.dart.
  • Validate notifications list index mapping, itemCount, and empty-state condition in notifications_screen.dart.
  • Check navigation handling in backup_reminder_notification.dart and that localization keys match ARB entries.

Possibly related PRs

  • Account screen redesigned #208 — touches lib/features/key_manager/key_management_screen.dart and secret-words visibility; likely related to key-generation/reveal behavior changes.
  • feat : notifications screen #257 — modifies notifications UI and bell behavior; directly related to integrating the BackupReminderNotifier and reminder item.

Suggested reviewers

  • grunch

Poem

🐇 I thumped my foot and tapped a key,

"Back up your words," I sing with glee.
A card will call, a bell will shake,
Keep seeds safe for safety's sake.
Hop secure — don't let them flake. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add backup account reminder notification system' accurately reflects the main objective of the PR, which implements a backup reminder notification feature integrated into the app's notification system.
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.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch backup-notification

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.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (3)
lib/features/key_manager/key_management_screen.dart (1)

12-12: Backup reminder wiring in key management matches the desired lifecycle

  • Calling showBackupReminder() after generating and storing a new master key ensures new users immediately get the reminder, even after storage is cleared.
  • Dismissing via dismissBackupReminder() only when _showSecretWords flips to true is a good proxy for “user has viewed their seed phrase”, and the guard prevents dismissing when hiding again.

You might optionally also guard the dismissal with a simple _mnemonic != null check, but it’s not strictly necessary.

Also applies to: 78-80, 290-293

lib/shared/widgets/notification_history_bell_widget.dart (1)

28-34: Consider a smoother curve for the repeating shake animation.

Curves.elasticIn has overshoot behavior at the beginning that may appear jarring when repeated continuously. For a repeating shake effect, Curves.easeInOut or Curves.elasticInOut would provide a smoother visual experience.

     _shakeAnimation = Tween<double>(
       begin: -0.05,
       end: 0.05,
     ).animate(CurvedAnimation(
       parent: _animationController,
-      curve: Curves.elasticIn,
+      curve: Curves.easeInOut,
     ));
lib/features/notifications/providers/backup_reminder_provider.dart (1)

32-34: Remove the redundant getter.

The shouldShowBackupReminder getter simply returns state, which is already exposed by StateNotifier and accessible via backupReminderProvider. This adds unnecessary API surface without providing additional value.

-  /// Checks if the backup reminder should be shown
-  bool get shouldShowBackupReminder => state;

Consumers can directly watch ref.watch(backupReminderProvider) instead of ref.watch(backupReminderProvider.notifier).shouldShowBackupReminder.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc881cf and faa5029.

📒 Files selected for processing (10)
  • lib/features/auth/screens/register_screen.dart (2 hunks)
  • lib/features/key_manager/key_management_screen.dart (3 hunks)
  • lib/features/notifications/providers/backup_reminder_provider.dart (1 hunks)
  • lib/features/notifications/screens/notifications_screen.dart (4 hunks)
  • lib/features/notifications/widgets/backup_reminder_notification.dart (1 hunks)
  • lib/features/walkthrough/screens/walkthrough_screen.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/shared/widgets/notification_history_bell_widget.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/widgets/backup_reminder_notification.dart
  • lib/shared/widgets/notification_history_bell_widget.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/widgets/backup_reminder_notification.dart
  • lib/shared/widgets/notification_history_bell_widget.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.dart
lib/features/**/screens/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

lib/features/**/screens/**/*.dart: Keep UI code declarative and side-effect free - use post-frame callbacks for side effects like SnackBars/dialogs
Use S.of(context)!.yourKey for all user-facing strings instead of hardcoded text

Files:

  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
lib/l10n/**/*.arb

📄 CodeRabbit inference engine (CLAUDE.md)

Add new localization keys to all three ARB files (en, es, it) - use S.of(context)!.keyName for all user-facing strings

Files:

  • lib/l10n/intl_en.arb
  • lib/l10n/intl_es.arb
  • lib/l10n/intl_it.arb
lib/shared/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

Follow existing feature patterns when adding new shared utilities - refer to order, chat, and auth features as implementation examples

Files:

  • lib/shared/widgets/notification_history_bell_widget.dart
lib/features/**/providers/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

lib/features/**/providers/**/*.dart: Organize Riverpod providers by feature in features/{feature}/providers/ using Notifier pattern for complex state logic
Use Notifier pattern instead of simple StateNotifier for complex state logic requiring business rule encapsulation

Files:

  • lib/features/notifications/providers/backup_reminder_provider.dart
🧠 Learnings (14)
📚 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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/widgets/backup_reminder_notification.dart
  • lib/shared/widgets/notification_history_bell_widget.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/widgets/backup_reminder_notification.dart
  • lib/shared/widgets/notification_history_bell_widget.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/widgets/backup_reminder_notification.dart
  • lib/shared/widgets/notification_history_bell_widget.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/widgets/backup_reminder_notification.dart
  • lib/shared/widgets/notification_history_bell_widget.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/relays/**/*.dart : Use dual storage strategy: store Mostro/default relays in `settings.relays` and user relays in `settings.userRelays` with full JSON metadata via `toJson()`/`fromJson()`

Applied to files:

  • lib/features/key_manager/key_management_screen.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/key_manager/key_management_screen.dart
  • lib/features/auth/screens/register_screen.dart
  • lib/features/notifications/screens/notifications_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/**/screens/**/*.dart : Use `S.of(context)!.yourKey` for all user-facing strings instead of hardcoded text

Applied to files:

  • lib/features/auth/screens/register_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.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/**/screens/**/*.dart : Keep UI code declarative and side-effect free - use post-frame callbacks for side effects like SnackBars/dialogs

Applied to files:

  • lib/features/auth/screens/register_screen.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/auth/screens/register_screen.dart
  • lib/features/notifications/widgets/backup_reminder_notification.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.dart
📚 Learning: 2025-08-21T14:45:43.974Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 272
File: lib/features/relays/widgets/relay_selector.dart:13-15
Timestamp: 2025-08-21T14:45:43.974Z
Learning: In the Mostro mobile app's RelaySelector widget (lib/features/relays/widgets/relay_selector.dart), watching relaysProvider.notifier correctly triggers rebuilds because the relaysProvider itself depends on settingsProvider (line 8 in relays_provider.dart). When blacklist changes via toggleMostroRelayBlacklist(), the settingsProvider updates, causing relaysProvider to rebuild, which then notifies widgets watching the notifier. The UI correctly reflects active/inactive states in real-time through this dependency chain.

Applied to files:

  • lib/features/auth/screens/register_screen.dart
  • lib/shared/widgets/notification_history_bell_widget.dart
  • lib/features/notifications/screens/notifications_screen.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/auth/screens/register_screen.dart
  • lib/features/walkthrough/screens/walkthrough_screen.dart
  • lib/features/notifications/providers/backup_reminder_provider.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/l10n/**/*.arb : Add new localization keys to all three ARB files (en, es, it) - use `S.of(context)!.keyName` for all user-facing strings

Applied to files:

  • lib/l10n/intl_en.arb
  • lib/l10n/intl_es.arb
  • lib/l10n/intl_it.arb
⏰ 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 (13)
lib/l10n/intl_es.arb (1)

1172-1176: Backup reminder ES localization is consistent and well‑scoped

The new _comment_backup_reminder, backupAccountReminder, and backupAccountReminderMessage entries look correct, read naturally in Spanish, and follow the existing ARB structure (trailing comma on restoreErrorMessage, comment naming pattern). Nothing to change here.
As per coding guidelines, new user‑facing strings are properly localized.

lib/l10n/intl_it.arb (1)

1227-1231: Backup reminder IT localization aligns with EN/ES

The added backup reminder keys and comment are in idiomatic Italian, semantically aligned with EN/ES, and keep ARB structure valid. No issues.
Based on learnings, all three locales now cover these keys.

lib/features/walkthrough/screens/walkthrough_screen.dart (1)

7-7: First‑run backup reminder trigger is cleanly integrated

Showing the backup reminder right after markFirstRunComplete() and before navigating home ensures first‑time users get the prompt without affecting navigation flow. The context.mounted check around context.go('/') is also correct.

Also applies to: 168-175

lib/l10n/intl_en.arb (1)

1194-1198: English backup reminder strings are clear and consistent

The restoreErrorMessage comma fix plus the new _comment_backup_reminder, backupAccountReminder, and backupAccountReminderMessage entries are well‑worded and consistent with the rest of the file. No structural or localization issues.
As per coding guidelines, ARB additions are correctly mirrored in ES/IT and consumed via S.of(context)!.

lib/features/auth/screens/register_screen.dart (1)

8-8: Auth flow backup reminder hooks are correctly placed

Using ref.listen to call showBackupReminder() on both AuthKeyGenerated and AuthRegistrationSuccess gives good coverage for newly generated and imported keys without complicating the UI tree. The sequencing (set text → show reminder → navigate home on success) is sound.

Also applies to: 31-40

lib/features/notifications/screens/notifications_screen.dart (1)

6-6: Backup reminder integration into notifications list is robust

  • shouldShowBackupReminder is cleanly read once and reused.
  • Empty state gating on notificationList.isEmpty && !shouldShowBackupReminder ensures the reminder alone still produces meaningful content.
  • totalItems plus the index == 0 special case and notificationIndex = shouldShowBackupReminder ? index - 1 : index correctly align list indices for all cases.

This is a solid, minimal change that keeps the list logic easy to reason about.

Also applies to: 9-9, 20-21, 44-45, 76-78, 85-98

lib/features/notifications/widgets/backup_reminder_notification.dart (1)

1-92: Backup reminder notification widget is well‑structured and localized

The widget cleanly encapsulates the backup reminder UI:

  • Uses S.of(context)! for both title and message.
  • Visual design (accented icon, copy, trailing chevron) clearly signals an actionable, important item.
  • Tapping routes to /key_management, delegating actual dismissal logic to the key management screen where the seed phrase is shown.

Only minor follow‑up is to double‑check that /key_management matches your GoRouter config; otherwise, this implementation looks ready.

lib/shared/widgets/notification_history_bell_widget.dart (3)

7-14: LGTM!

The conversion from ConsumerWidget to ConsumerStatefulWidget is correctly implemented, and the backup reminder provider import is appropriate.


61-87: LGTM!

The animation implementation using AnimatedBuilder and Transform.rotate is correct. The conditional rendering logic appropriately prioritizes the notification badge over the backup reminder dot when there are unread notifications.


89-107: LGTM!

The _BackupReminderDot widget is correctly implemented as a simple red dot indicator.

lib/features/notifications/providers/backup_reminder_provider.dart (3)

13-18: LGTM!

The state loading logic correctly interprets the persisted flag: new users (no stored value) default to showing the reminder, and the state accurately reflects whether the reminder was previously dismissed.


20-30: LGTM!

Both methods correctly persist the state to SharedPreferences before updating the in-memory state, ensuring data consistency.


36-39: LGTM!

The provider definition correctly follows the naming convention and properly wires the SharedPreferencesAsync dependency.

Comment thread lib/features/notifications/providers/backup_reminder_provider.dart
Comment thread lib/shared/widgets/notification_history_bell_widget.dart Outdated

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between faa5029 and d0bfab5.

📒 Files selected for processing (1)
  • lib/shared/widgets/notification_history_bell_widget.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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/shared/widgets/notification_history_bell_widget.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/shared/widgets/notification_history_bell_widget.dart
lib/shared/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

Follow existing feature patterns when adding new shared utilities - refer to order, chat, and auth features as implementation examples

Files:

  • lib/shared/widgets/notification_history_bell_widget.dart
🧠 Learnings (9)
📚 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/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_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/**/screens/**/*.dart : Keep UI code declarative and side-effect free - use post-frame callbacks for side effects like SnackBars/dialogs

Applied to files:

  • lib/shared/widgets/notification_history_bell_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 : Always check `mounted` before using BuildContext after async operations to prevent errors on disposed widgets

Applied to files:

  • lib/shared/widgets/notification_history_bell_widget.dart
📚 Learning: 2025-08-21T14:45:43.974Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 272
File: lib/features/relays/widgets/relay_selector.dart:13-15
Timestamp: 2025-08-21T14:45:43.974Z
Learning: In the Mostro mobile app's RelaySelector widget (lib/features/relays/widgets/relay_selector.dart), watching relaysProvider.notifier correctly triggers rebuilds because the relaysProvider itself depends on settingsProvider (line 8 in relays_provider.dart). When blacklist changes via toggleMostroRelayBlacklist(), the settingsProvider updates, causing relaysProvider to rebuild, which then notifies widgets watching the notifier. The UI correctly reflects active/inactive states in real-time through this dependency chain.

Applied to files:

  • lib/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_widget.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 (3)
lib/shared/widgets/notification_history_bell_widget.dart (3)

56-63: LGTM!

The ref.listen pattern correctly handles animation state changes as a side effect, addressing the previous review feedback. Animation starts/stops reactively based on provider state.


73-93: LGTM!

The conditional rotation with AnimatedBuilder and the priority logic for displaying backup reminder dot vs notification badge is well-structured. The rotation applies only when backup reminder is active, avoiding unnecessary transforms.


99-117: LGTM!

The _BackupReminderDot widget is correctly implemented as a const StatelessWidget with appropriate positioning as a Stack child.

Comment thread lib/shared/widgets/notification_history_bell_widget.dart

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 0

🧹 Nitpick comments (1)
lib/shared/widgets/notification_history_bell_widget.dart (1)

79-87: Consider adding semantic label for accessibility.

The IconButton lacks an explicit semantic label, which could make the button less clear to screen reader users, especially when the backup reminder animation is active.

Apply this diff to improve accessibility:

 child: IconButton(
+  tooltip: 'Notifications',
   icon: const HeroIcon(
     HeroIcons.bell,
     style: HeroIconStyle.outline,
     color: AppTheme.cream1,
     size: 28,
   ),
   onPressed: () => context.push('/notifications'),
 ),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0bfab5 and a91b20e.

📒 Files selected for processing (1)
  • lib/shared/widgets/notification_history_bell_widget.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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/shared/widgets/notification_history_bell_widget.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/shared/widgets/notification_history_bell_widget.dart
lib/shared/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

Follow existing feature patterns when adding new shared utilities - refer to order, chat, and auth features as implementation examples

Files:

  • lib/shared/widgets/notification_history_bell_widget.dart
🧠 Learnings (9)
📚 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/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_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/**/screens/**/*.dart : Keep UI code declarative and side-effect free - use post-frame callbacks for side effects like SnackBars/dialogs

Applied to files:

  • lib/shared/widgets/notification_history_bell_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 : Always check `mounted` before using BuildContext after async operations to prevent errors on disposed widgets

Applied to files:

  • lib/shared/widgets/notification_history_bell_widget.dart
📚 Learning: 2025-08-21T14:45:43.974Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 272
File: lib/features/relays/widgets/relay_selector.dart:13-15
Timestamp: 2025-08-21T14:45:43.974Z
Learning: In the Mostro mobile app's RelaySelector widget (lib/features/relays/widgets/relay_selector.dart), watching relaysProvider.notifier correctly triggers rebuilds because the relaysProvider itself depends on settingsProvider (line 8 in relays_provider.dart). When blacklist changes via toggleMostroRelayBlacklist(), the settingsProvider updates, causing relaysProvider to rebuild, which then notifies widgets watching the notifier. The UI correctly reflects active/inactive states in real-time through this dependency chain.

Applied to files:

  • lib/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_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/shared/widgets/notification_history_bell_widget.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 (3)
lib/shared/widgets/notification_history_bell_widget.dart (3)

21-44: LGTM! Proper animation initialization with mounted check.

The animation controller setup is correct, and the mounted check in the post-frame callback (line 38) properly addresses the previous review concern about accessing a potentially disposed controller.


57-64: LGTM! Animation control properly moved to ref.listen.

This correctly addresses the previous review comment about moving animation control logic out of the build method body. Using ref.listen to respond to provider changes is the proper Riverpod pattern for handling side effects like animation control.


91-94: LGTM! Clear conditional rendering logic.

The logic correctly prioritizes unread notifications over the backup reminder indicator, ensuring users see actual notifications first. The mutually exclusive conditions prevent overlapping visual indicators.

@Catrya Catrya requested a review from grunch December 10, 2025 16:14
  - Implement backup reminder notification that appears first in notifications list
  - Trigger reminder on first app launch and new user creation
  - Dismiss reminder only when user views seed phrase
  - Integrate with existing notification system without breaking functionality
  - Persist reminder state across app restarts using SharedPreferences
  - Add animated notification bell with shake animation when backup needed
@Catrya Catrya force-pushed the backup-notification branch from a91b20e to 95075f6 Compare December 10, 2025 22:18

@grunch grunch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

tACK, great job! @Catrya 🥳

@grunch grunch merged commit b594627 into main Dec 18, 2025
2 checks passed
@grunch grunch deleted the backup-notification branch December 18, 2025 14:46
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.

Notify the user to back up their account

2 participants