Add TimeSafariNativeFetcher (plansLastUpdatedBetween parity with Android) and call DailyNotificationPlugin.registerNativeFetcher from AppDelegate before JS configureNativeFetcher; broaden DailyNotificationDelivered scheduled_time types in willPresent. Wire the new file into the App target; normalize PBX object IDs to 24-char hex. Document plugin ≥3 handoff (consuming-app-handoff-ios-native-fetcher-chained-dual), refresh iOS/Android parity and notification-from-api-call file tables.
4.5 KiB
Consuming app handoff: iOS native fetcher + chained dual (mirror)
Canonical source: daily-notification-plugin repo, doc/CONSUMING_APP_HANDOFF_IOS_NATIVE_FETCHER_AND_CHAINED_DUAL.md (same content as below for offline use).
Implemented in this app
ios/App/App/TimeSafariNativeFetcher.swift— SwiftNativeNotificationContentFetchermirroringTimeSafariNativeFetcher.java(POST …/plansLastUpdatedBetween, starred IDs fromdaily_notification_timesafari.starredPlanIds, JWT pool selection, pagination keydaily_notification_timesafari.last_acked_jwt_id, aggregated copy).AppDelegate.swift—DailyNotificationPlugin.registerNativeFetcher(TimeSafariNativeFetcher.shared)at launch before any JSconfigureNativeFetcher; foreground handler readsscheduled_timeasInt64,NSNumber, orIntforDailyNotificationDelivered.
Dependency
@timesafari/daily-notification-pluginmust be ≥ 3.0.0 (register native fetcher, chained dual, iOSupdateStarredPlans). Declare it inpackage.jsonfrom the official remote (git+https://gitea.anomalistdesign.com/trent_larson/daily-notification-plugin.git, branch or tag as needed), thennpm installsopackage-lock.jsonresolves the published tree.
Bump / sync (after plugin version is resolved)
npm installnpx cap sync ios && npx cap sync androidcd ios/App && pod install- Clean build in Xcode / Android Studio
QA focus
- iOS: Fetcher registered before
configureNativeFetcher;updateStarredPlansnotUNIMPLEMENTED. - Both: New Activity fires after prefetch for that cycle where the plugin implements chaining.
- Android: Existing
MainActivity.setNativeFetcherunchanged; regression-testcancelDualSchedulevs Daily Reminder.
Original handoff text (from plugin)
This document is for the host app repository (e.g. crowd-funder-for-time-pwa) after bumping @timesafari/daily-notification-plugin to a version that includes:
- iOS
NativeNotificationContentFetcher–style registration (DailyNotificationPlugin.registerNativeFetcher) - iOS
updateStarredPlans/getStarredPlans(parity with Androiddaily_notification_timesafari/starredPlanIdssemantics) - iOS chained dual flow: user notification is armed only after prefetch completes (delay if fetch is late; max slip 15 minutes before fallback copy)
- Android chained dual flow: exact notify alarm is scheduled after dual prefetch completes (no longer scheduled at initial
scheduleDualNotificationbefore fetch)
Material from doc/new-activity-notifications-ios-android-parity.md still applies; the plugin doc adds app-side steps not spelled out there.
1. iOS — register native fetcher before configureNativeFetcher
The plugin rejects configureNativeFetcher if no fetcher is registered (aligned with Android).
In AppDelegate (or earliest app startup before Capacitor calls into the plugin):
import TimesafariDailyNotificationPlugin
DailyNotificationPlugin.registerNativeFetcher(TimeSafariNativeFetcher.shared)
Implement TimeSafariNativeFetcher as a Swift type that:
- Conforms to
NativeNotificationContentFetcher - Implements
fetchContent(context: FetchContext) async throws -> [NotificationContent]with the same Endorser behavior asTimeSafariNativeFetcher.java - Implements
configure(apiBaseUrl:activeDid:jwtToken:jwtTokenPool:)if the fetcher needs credentials pushed from TypeScript
Starred plan IDs for the fetcher: Read JSON array string from UserDefaults key daily_notification_timesafari.starredPlanIds (written by updateStarredPlans from JS).
2. iOS — UNUserNotificationCenterDelegate / rollover
Chained dual notifications set:
notification_id=org.timesafari.dailynotification.dualscheduled_time=NSNumber(fire time in ms)
Ensure DailyNotificationDelivered forwards notification_id and scheduled_time from notification content userInfo.
3. Android — no API change for setNativeFetcher
Host apps that already call DailyNotificationPlugin.setNativeFetcher(TimeSafariNativeFetcher(...)) keep that flow.
Behavior change: the dual notify alarm is scheduled when dual prefetch work finishes, not at the initial scheduleDualNotification only.
4. Assumptions
- Swift host implements
TimeSafariNativeFetcher; the plugin does not embedplansLastUpdatedBetweenon iOS when a host fetcher is registered (mirrors Android). - Module import:
TimesafariDailyNotificationPlugin(PodTimesafariDailyNotificationPlugin).