Skip to content

Feature/remove legacy plan metadata#498

Merged
tentamdin merged 4 commits into
developfrom
feature/remove-legacy-plan-metadata
Jul 5, 2026
Merged

Feature/remove legacy plan metadata#498
tentamdin merged 4 commits into
developfrom
feature/remove-legacy-plan-metadata

Conversation

@tentamdin

@tentamdin tentamdin commented Jul 5, 2026

Copy link
Copy Markdown
Member
  • remove old notification for plan/series
  • fix the notification toggle

tentamdin added 3 commits July 5, 2026 15:30
- Added new dependencies: jni and jni_flutter to pubspec.lock.
- Updated path_provider_android version to 2.3.1 in pubspec.lock.
- Modified Flutter SDK version constraint in pubspec.lock.
- Refactored connect screen to enhance group discovery and loading states.
- Introduced DiscoverGroupsScreen and DiscoverGroupsSection for better UI organization.
- Updated localization strings for improved user experience.
… sync process

- Deleted PlanMetadataStore and SpecialPlanStartedAtStore to streamline storage management.
- Updated notification sync process to directly hydrate server routines into local storage without relying on legacy metadata stores.
- Adjusted notification scheduling to focus on local recitation and timer reminders, with plan reminders now delivered via server push (FCM).
- Cleaned up related imports and references throughout the codebase for improved clarity and maintainability.
@greptile-apps

greptile-apps Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

Safe to merge with one issue to address: the FCM device re-registration triggered by a notification toggle reads stale SharedPreferences before the toggle write has landed, so the backend receives the wrong plan/series push gate on the first registration after each toggle.

When the user flips the master or routine toggle, Riverpod fires the notificationProvider listener synchronously before prefs.setBool is awaited in the notifier. refreshRegistration() immediately reads the old SharedPreferences value and sends it to the backend, so the backend's push gate for plan/series notifications reflects the pre-toggle state until the next login.

lib/features/push_notifications/presentation/providers/push_notification_providers.dart and lib/features/push_notifications/application/push_notification_service.dart — the interaction between the Riverpod listener firing on state change and the async SharedPreferences write in the notifier.

Reviews (2): Last reviewed commit: "Update lib/features/connect/presentation..." | Re-trigger Greptile

Comment on lines +63 to +71
ref.listen<NotificationState>(
notificationProvider,
(prev, next) {
final changed = prev == null ||
prev.appMasterEnabled != next.appMasterEnabled ||
prev.appRoutineEnabled != next.appRoutineEnabled;
if (changed) service.refreshRegistration();
},
);

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.

P2 FCM re-registration fires on first notification-state emission

When prev == null, refreshRegistration() is called unconditionally on the first state change from notificationProvider. For a StateNotifierProvider, Riverpod sets the initial state synchronously in the constructor, so the first listener call has a non-null prev in practice — but the prev == null guard still triggers on edge cases such as provider disposal/re-creation. The result is an extra PATCH /devices call on every cold start. This is idempotent on the backend, so it's never incorrect, but it causes a redundant network round-trip immediately after login when syncAuth() already triggers _registerToken().

Comment thread lib/features/connect/presentation/widgets/discover_groups_section.dart Outdated
…ion.dart

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@tentamdin tentamdin merged commit b7f69db into develop Jul 5, 2026
1 of 2 checks passed
Comment on lines +63 to +71
ref.listen<NotificationState>(
notificationProvider,
(prev, next) {
final changed = prev == null ||
prev.appMasterEnabled != next.appMasterEnabled ||
prev.appRoutineEnabled != next.appRoutineEnabled;
if (changed) service.refreshRegistration();
},
);

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.

P1 Stale SharedPreferences read when preference is re-registered

The listener fires synchronously as soon as state = state.copyWith(appMasterEnabled: enable) (or the routine equivalent) is executed inside toggleMaster/toggleRoutine. At that exact moment, prefs.setBool(...) hasn't been called yet — it's still pending in the async body. refreshRegistration() immediately calls unawaited(_registerToken()), which reads StorageKeys.notificationMasterEnabled/notificationRoutineEnabled from SharedPreferences via _readPreferences(). Because the write hasn't happened, it reads the old value and sends the stale {'routine': true} to the backend even when the user just toggled master or routine OFF. The backend therefore won't suppress plan/series push until the next token registration (login).

The simplest fix is to write the preference to SharedPreferences before updating the Riverpod state, so the listener always sees the already-persisted value. Alternatively, the listener already has the correct next.appMasterEnabled / next.appRoutineEnabled values in scope and could pass them directly into a variant of refreshRegistration instead of re-reading from storage.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant