Files
jamshalat-diary/docs/notification-audit-tasklist.md
Dwindi Ramadhana 4badfb6521 Notification system audit: fix 6 defects, close 5 gaps, add rich notifications (v1.1.0)
Defects fixed:
- D1: Fix notification ID range collision (report reminders 700k→2M+)
- D2: Streak risk now checks both dzikir pagi & petang
- D3: _cancelPrayerPending no longer kills non-prayer notifications
- D4: Push notifications carry deeplink in payload for proper routing
- D5: Add reconfigureTimeZoneIfNeeded() for TZ change detection
- D6: Defer launch notification routing until widget tree is ready

Gaps closed:
- G1: Add streak risk + weekly summary toggles to settings UI
- G2: Verified boot reschedule already in place (flutter_local_notifications v21)
- G3: Remove unused mirrorAdzanToInbox field and legacy cleanup calls
- G4: Add notif_push_opened analytics tracking
- G5: Add notif_settings_changed analytics tracking

Enhancements:
- O1: Rich notification with Sudah Sholat action button on report reminders
- O2: Permission check on app resume via WidgetsBindingObserver (30s throttle)
- O2b: Fix stretched notification icon (white crescent moon vector drawable)
- O3: Expired inbox cleanup in background sync
- O4: Haptic feedback on notification bell quick actions

Bump version 1.0.8+9 → 1.1.0+10
2026-06-06 22:38:02 +07:00

6.5 KiB
Raw Blame History

Notification Feature Audit — Tasklist

Source: Full codebase trace of notification system
Date: June 2026
Status legend: [ ] Not started · [~] In progress · [x] Done · [-] Skipped


Defects (Bugs)

D1. Notification ID Range Collision — Adhan vs Report Reminders [SEVERITY: High]

  • D1.1 Move report reminder ID range from 700000+ to 2000000+ in _reportReminderId()
  • D1.2 Update _cancelPrayerPending() range guard to exclude the new report range explicitly
  • D1.3 Verify adhan IDs (100k800k), iqamah IDs (800k1.5M), report IDs (2M+), non-prayer IDs (900k980k) are all disjoint

D2. Streak Risk Only Checks Dzikir Petang, Not Pagi [SEVERITY: Medium]

  • D2.1 Fix emitStreakRiskIfNeeded to check both !pagi and !petang in dzikir risk logic
  • D2.2 Emit separate inbox items for pagi vs petang dzikir risk with correct deeplinks

D3. _cancelPrayerPending Cancels Non-Prayer Notifications Too [SEVERITY: Medium]

  • D3.1 Narrow the ID range filter to only cancel adhan (100k799k), iqamah (800k1.5M), and report (2M+) IDs
  • D3.2 Exclude non-prayer range (900k980k) from cancellation
  • D4.1 Update routeForNotificationPayload to parse deeplink from payload for streak_risk type
  • D4.2 Include deeplink in notification payload through _pushNonPrayershowNonPrayerAlert chain

D5. Timezone Not Updated on Device TZ Change [SEVERITY: Medium]

  • D5.1 Add reconfigureTimeZoneIfNeeded() method to detect and apply timezone changes
  • D5.2 Reset _lastSyncSignature on TZ change to force prayer notification resync

D6. _handleLaunchNotification May Fire Before Router is Ready [SEVERITY: Low]

  • D6.1 Defer launch notification routing — store pending route, consume from AppState.initState with 800ms delay

Gaps (Missing or Incomplete)

G1. No Settings UI for Notification Preferences [SEVERITY: High]

  • G1.1 Settings UI already existed — added missing streakRiskEnabled toggle to notification group
  • G1.2 Added weeklySummaryEnabled toggle to notification group
  • G1.3 All other notification settings (alerts, inbox, checklist reminder, quiet hours, push cap) were already present

G2. No Device Reboot Reschedule [SEVERITY: High]

  • G2.1 Verified RECEIVE_BOOT_COMPLETED permission in AndroidManifest.xml — already present
  • G2.2 Verified ScheduledNotificationReceiver and ScheduledNotificationBootReceiver — already declared
  • G2.3 flutter_local_notifications v21 handles reboot natively; workmanager periodic task resumes via ExistingPeriodicWorkPolicy.update

G3. mirrorAdzanToInbox Setting Exists But Never Used [SEVERITY: Medium]

  • G3.1 Removed unused mirrorAdzanToInbox field from AppSettings and generated adapter
  • G3.2 Removed legacy removeByType('prayer') calls from main.dart and notification_center_screen.dart

G4. No Analytics for notif_push_opened [SEVERITY: Low]

  • G4.1 Added notif_push_opened tracking in _handleNotificationResponse (foreground) and consumePendingLaunchRoute (launch)

G5. No Analytics for notif_settings_changed [SEVERITY: Low]

  • G5.1 Added notif_settings_changed tracking in notification bell quick actions toggle

Opportunities (Enhancements)

O1. Rich Notification Actions — "Sudah Sholat" Button on Report Reminders

  • O1.1 Added AndroidNotificationAction with action_prayed / "Sudah Sholat" button to _scheduleShalatReportReminder
  • O1.2 Background handler (notificationTapBackgroundHandler) opens Hive and logs ShalatLog(completed: true) via _markPrayedFromBackground
  • O1.3 Foreground handler (_handleNotificationResponse) logs prayer via _markPrayedFromForeground
  • O1.4 Added _resolvePrayerKeyFromName to map display names back to canonical keys in background isolate

O2. Notification Permission Check on App Resume via WidgetsBindingObserver

  • O2.1 Added _checkNotificationPermissionOnResume() with 30-second throttle to _AppState.didChangeAppLifecycleState
  • O2.2 Re-checks notification permissions and emits warnings via emitPermissionWarningsIfNeeded on resume

O2b. Fix Stretched Notification Icon

  • O2b.1 Created @drawable/ic_notification — white crescent moon vector drawable (Android notification-safe)
  • O2b.2 Changed AndroidInitializationSettings from @mipmap/ic_launcher to @drawable/ic_notification
  • O2b.3 Added icon: '@drawable/ic_notification' to all 4 notification channels

O3. Add Expired Item Cleanup to Background Sync

  • O3.1 Added removeExpired() call in BackgroundSyncService.runSyncPass()

O4. Haptic Feedback on Quick Actions

  • O4.1 Added HapticFeedback.selectionClick() to all three notification bell quick action taps

Progress Tracker

Category Total Done Skipped Remaining
Defects (D1D6) 11 11 0 0
Gaps (G1G5) 10 10 0 0
Opportunities (O1O4) 9 9 0 0
TOTAL 30 30 0 0

Files Changed

File Changes
lib/data/services/notification_service.dart D1: ID range fix, D3: cancel range fix, D4: payload routing with deeplink, D5: TZ reconfig, D6: deferred launch routing, O1: rich notification action + background handler, O2b: icon fix
lib/data/services/notification_event_producer_service.dart D2: pagi+petang dzikir streak risk, D4: deeplink threading
lib/core/widgets/notification_bell_button.dart G5: analytics tracking, O4: haptic feedback
lib/data/services/background_sync_service.dart O3: expired inbox cleanup
lib/features/settings/presentation/settings_screen.dart G1: streak risk + weekly summary toggles
lib/data/local/models/app_settings.dart G3: removed mirrorAdzanToInbox field
lib/data/local/models/app_settings.g.dart G3: removed field 32 from adapter
lib/main.dart G3: removed legacy removeByType('prayer')
lib/features/notifications/presentation/notification_center_screen.dart G3: removed legacy cleanup
lib/app/app.dart D6: consume pending launch route on init, O2: permission check on resume
android/app/src/main/res/drawable/ic_notification.xml O2b: white crescent moon vector drawable for notification icon