Implement enhanced app launch recovery to detect and schedule missed rollover
notifications that occurred while the app was terminated, backgrounded, or
inactive.
Key improvements:
- Detect missed rollovers on app launch by checking for past notifications
without next scheduled notification
- Add active rollover check when app becomes active (handles inactive app
scenario where notifications fire silently)
- Calculate forward to future time when next scheduled time is in the past
(handles delays > rollover interval)
- Enhance duplicate detection to exclude original notification from checks
- Retry rollover if previous attempt failed (rollover time set but no next
notification exists)
Changes:
- DailyNotificationReactivationManager: Add detectAndProcessMissedRollovers()
method and performActiveRolloverCheck() for app becoming active
- DailyNotificationReactivationManager: Enhance warm start scenario to check
for missed rollovers
- DailyNotificationScheduler: Add forward calculation loop when next scheduled
time is in the past
- DailyNotificationPlugin: Register observer for UIApplication.didBecomeActiveNotification
to trigger rollover check when app becomes active
Fixes rollover scheduling for:
- App terminated: Rollover now detected and scheduled on next launch
- App inactive/backgrounded: Rollover detected when app becomes active
- Delayed recovery: Handles cases where app reopened after rollover interval
has passed by calculating forward to next future time
All scenarios now properly schedule rollover notifications regardless of app
state when notification fires.
Add inline comments and documentation explaining how to temporarily
change rollover notification intervals from 24 hours to 2 minutes
for testing purposes. Comments specify exact line numbers and values
to change, making it easy to switch between production and testing
modes without losing context.
Changes:
- Add TESTING section to calculateNextScheduledTime() documentation
- Add inline TESTING comments at three change points:
* Calendar date addition (24 hours → 2 minutes)
* Fallback time calculation (24 hours → 2 minutes)
* Duplicate prevention threshold (1 hour → 1 minute)
All code remains at production settings (24-hour intervals).
Save notification content to storage immediately after scheduling
rollover notification so it can be retrieved when the notification
fires. Without this, processRollover fails to find the content
and cannot schedule the next notification.
The rollover flow creates a new notification with a new ID
(daily_rollover_*) but was only scheduling it with the system,
not saving it to storage. When the notification fired, the
lookup by ID failed because the content wasn't stored.
This matches the pattern used in DailyNotificationScheduleHelper
which saves content before scheduling.
- iOS: Implement rolling window counting using UNUserNotificationCenter
- iOS: Enable TTL validation in scheduler before arming notifications
- iOS: Implement SQLite persistence for save/delete/clear operations
- Android: Implement rolling window counting using storage as source of truth
- Android: Add dateBoundsMillis helper for date range calculations
Removes all TODO stubs affecting capacity/rate-limiting correctness.
Fixes runtime behavior to match test expectations and optimizer logic.
Refs: Deep fixes directive for bottom-of-tree gaps
- Fix getNextNotificationTime() to find earliest scheduled notification
instead of using first request (pendingNotificationRequests doesn't
guarantee order)
- Add comprehensive logging for rollover tracking with DNP-ROLLOVER
prefix for Xcode console filtering
- Reset all notifications and rollover state when scheduling new
notification via scheduleDailyNotification() to ensure clean test
state
- Fix userInfo scope error in handleNotificationDelivery error handler
- Update test app UI to refresh status every 5-10 seconds and
immediately after notification delivery to reflect rollover changes
- Add console logging in UI to debug getNotificationStatus() results
This ensures the UI correctly displays the next notification time after
rollover completes, and test notifications start with a clean slate.
Fixed multiple issues in iOS test script and added logging for test compatibility:
Test Script Fixes:
- Fixed get_simulator_id() to correctly extract UUID from booted devices
- Fixed get_app_logs() to use log show (historical) instead of log stream (live) to avoid hanging
- Improved check_plugin_configured() with multiple detection methods (app container, app listing, data directory)
- Added ensure_plugin_configured() function matching Android pattern for consistent user interaction flow
- Fixed integer comparison error in booted device check (removed newlines from count)
- Removed 'local' keyword from variables in main script body (local can only be used in functions)
- Fixed APP_BUNDLE_ID to match actual bundle identifier
Pending Notification Detection:
- Improved get_pending_notifications() to parse pendingCount from plugin logs
- Added direct log query without restrictive predicate to catch plugin logs
- Added multiple fallback methods for detecting pending count
Plugin Logging Enhancement:
- Added explicit pendingCount logging in DailyNotificationScheduler after scheduling
- Uses both NSLog() and print() to ensure logs appear in system logs and Xcode console
- Matches Android's alarm count logging pattern for test script compatibility
This resolves script crashes and enables reliable detection of pending notifications
for automated testing.