Files
crowd-funder-for-time-pwa/doc/daily-notification-alignment-outline.md
Jose Olarte III 9902e5fac7 chore: align with daily-notification-plugin 2.0.0 (org.timesafari namespace)
- Update Android manifest, Java imports, and capacitor.plugins.json to use
  org.timesafari.dailynotification (receivers, intent action, plugin classpath)
- Update iOS Info.plist BGTaskSchedulerPermittedIdentifiers to org.timesafari.*
- Bump @timesafari/daily-notification-plugin 1.3.3 → 2.0.0 (package-lock, Podfile.lock)
- Update docs and test-notification-receiver.sh to reference new package/action names
- Lockfile: minor bumps for @expo/cli, @expo/fingerprint, @expo/router-server, babel-preset-expo
2026-03-12 17:20:45 +08:00

5.9 KiB
Raw Blame History

Daily Notification Plugin: Alignment Outline

Purpose: Checklist of changes/additions needed in this app to align with the test app (daily-notification-plugin/test-apps/daily-notification-test) so that:

  1. Rollover recovery (and rollover itself) works.
  2. Notifications show when the app is in the foreground (not only background/closed).
  3. Plugin loads at app launch so recovery runs after reboot without the user opening notification UI.

Reference: Test app at
/Users/aardimus/Sites/trentlarson/daily-notification-plugin_test/daily-notification-plugin/test-apps/daily-notification-test


1. iOS AppDelegate

File: ios/App/App/AppDelegate.swift

1.1 Add imports

  • import UserNotifications
  • Import the Daily Notification plugin framework (Swift module name: TimesafariDailyNotificationPlugin per this apps Podfile; test app uses DailyNotificationPlugin)

1.2 Conform to UNUserNotificationCenterDelegate

  • Add , UNUserNotificationCenterDelegate to the class declaration:
    class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate

1.3 Force-load plugin at launch

  • In application(_:didFinishLaunchingWithOptions:), before other setup, add logic to force-load the plugin class (e.g. _ = DailyNotificationPlugin.self or the class exposed by the TimesafariDailyNotificationPlugin pod) so that the plugins load() (and thus performRecovery()) runs at app launch, not only when JS first calls the plugin.

1.4 Set notification center delegate

  • In didFinishLaunchingWithOptions, set:
    UNUserNotificationCenter.current().delegate = self
  • In applicationDidBecomeActive, re-set the same delegate (in case Capacitor or another component clears it).

1.5 Implement userNotificationCenter(_:willPresent:withCompletionHandler:)

  • When a notification is delivered (including in foreground), read notification_id and scheduled_time from notification.request.content.userInfo.
  • Post rollover event:
    NotificationCenter.default.post(name: NSNotification.Name("DailyNotificationDelivered"), object: nil, userInfo: ["notification_id": id, "scheduled_time": scheduledTime])
  • Call completion handler with presentation options so the notification is shown in foreground, e.g.
    completionHandler([.banner, .sound, .badge]) (use .alert on iOS 13 if needed).

1.6 Implement userNotificationCenter(_:didReceive:withCompletionHandler:)

  • Handle notification tap/interaction; call completionHandler() when done.

2. Android Manifest

File: android/app/src/main/AndroidManifest.xml

2.1 Fix receiver placement

  • Move the two <receiver> elements (DailyNotificationReceiver and BootReceiver) inside the <application> block (e.g. after <activity>...</activity> and before <provider>...</provider>).
  • Remove the stray second </application> so there is a single <application>...</application> containing activity, receivers, and provider.

2.2 (Optional) Add NotifyReceiver

  • If the plugins Android integration expects NotifyReceiver for alarm-based delivery, add a <receiver> for org.timesafari.dailynotification.NotifyReceiver inside <application> (see test app manifest for exact declaration).

2.3 (Optional) BootReceiver options

  • Consider aligning with test app: add android:directBootAware="true", android:exported="true", and intent-filter actions LOCKED_BOOT_COMPLETED, MY_PACKAGE_REPLACED, PACKAGE_REPLACED if you need the same boot/update behavior.

File: src/main.capacitor.ts (or the main entry used for native builds)

3.1 Load plugin at startup

  • Add a top-level import or an early call that touches the Daily Notification plugin so the JS side loads it at app startup (e.g. import "@timesafari/daily-notification-plugin" or a small init that calls getRebootRecoveryStatus() or configure()).
    This ensures the plugin is loaded as soon as the app runs; together with the iOS force-load in AppDelegate, recovery runs at launch.

4. Plugin configuration (optional)

  • If you use the native fetcher or need plugin config (db path, storage, etc.), call DailyNotification.configure() and/or configureNativeFetcher() when appropriate (e.g. after login or when notification UI is first used), similar to the test apps configureNativeFetcher() in HomeView.

5. Summary table

Area Change / addition
iOS AppDelegate Conform to UNUserNotificationCenterDelegate; set delegate; force-load plugin; implement willPresent (post DailyNotificationDelivered + show in foreground) and didReceive.
Android manifest Move DailyNotificationReceiver and BootReceiver inside <application>; remove duplicate </application>; optionally add NotifyReceiver and BootReceiver options.
main.capacitor.ts Optionally import or call plugin at startup so it (and recovery) load at launch.
Plugin config Optionally call configure() / configureNativeFetcher() where appropriate.

6. Verification

After making the changes:

  • iOS: Build and run; trigger a daily notification and confirm it appears when the app is in the foreground.
  • iOS: Confirm rollover (next days schedule) still occurs after a notification fires (check logs for DNP-ROLLOVER / DailyNotificationDelivered).
  • iOS: Restart the app (or reboot) and confirm recovery runs without opening the notification settings screen (e.g. logs show plugin load and recovery).
  • Android: Build and run; confirm receivers are registered (no manifest errors) and that notifications and boot recovery behave as expected.