Wire preferences screen to notification-preference-service
epic-scenario-push-engagement-ui-task-003 — Connect the toggle controls in notification-preferences-screen to notification-preference-service (577) using Riverpod. On toggle change, call the service to persist the preference immediately so the next evaluation cycle respects it. Load initial toggle state from the service on screen mount.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Use AsyncNotifierProvider
Do not call the service multiple times if the user toggles rapidly — debounce writes by 300ms or cancel the previous pending write.
Testing Requirements
Write unit tests for the Riverpod notifier: verify initial state is loaded from the service mock, verify toggle mutations call the correct service method with correct arguments, verify revert-on-failure logic. Write widget tests for the preferences screen: mount with a mocked service returning known preferences, assert toggles render in correct on/off state, simulate a toggle tap and assert the service mock was called, simulate a service write failure and assert the toggle reverts and error UI appears. No e2e test required for this task — covered by integration test at the epic level. Target 90%+ branch coverage on the notifier class.
The in-app notification banner depends on a Supabase Realtime subscription to detect new notification records. If the subscription reconnects slowly after an app resume from background, or if Realtime delivery is delayed under high load, the banner may not appear within the 2-second acceptance criterion.
Mitigation & Contingency
Mitigation: Implement an explicit subscription reconnect handler on app foreground events using Flutter's AppLifecycleState.resumed hook, and add a polling fallback that queries for unread notifications once per app foreground event as a safety net against missed Realtime events.
Contingency: If Realtime proves unreliable in production, promote the polling fallback to the primary mechanism with a 30-second interval, accepting slight latency in exchange for reliability.
Cold-start deep linking (app not running when push notification is tapped) requires deferred navigation after the Flutter engine and Supabase session are fully initialised. If the deep link is consumed before authentication completes, the router may navigate to a protected route without a valid session, causing an error or redirect loop.
Mitigation & Contingency
Mitigation: Implement a deferred navigation queue in scenario-deep-link-router that holds the parsed deep-link target until the auth session restoration lifecycle event fires, following the existing deep-link-handler pattern used in the BankID and Vipps authentication flows.
Contingency: If deferred navigation is not achievable within the epic's scope, fall back to navigating the user to the notification centre (which is always accessible post-login) where the relevant notification record is visible and tappable.