Daily Reminders now use daily_<reminderId> for UNNotificationCenter
requests instead of sharing api_<epochMillis> with batch API notifications.
clearApiNotifications no longer removes new daily reminders.
Add legacy api_* cleanup on schedule/cancel/update and transitional
getScheduledReminders matching via stored predictiveEpochMillis.
Update TypeScript JSDoc for iOS identifier families.
Expose bridge-safe pending, delivered, and settings snapshots from
UNUserNotificationCenter so apps can inspect local notification state
without native date objects or large payloads.
- Add getDeliveredNotifications and getNotificationSettings on iOS
- Harden getPendingNotifications with triggerTimestamp/triggerDateIso
- Always resolve with serializable values; omit userInfo from delivered
- Register new Capacitor methods and TypeScript definitions/web stubs
Use predictive_<epochMillis> for reminders (next-occurrence ms), testAlarm
fire time, and scheduleNotifications; persist predictiveEpochMillis in
UserDefaults for cancel/update alignment.
clearAllNotifications removes only predictive_* pending and delivered
entries. scheduleNotifications is additive (no global clear) and skips
past timestamps.
Expose clearAllNotifications and scheduleNotifications on DailyNotification.
clearAllNotifications clears pending and delivered center notifications.
scheduleNotifications replaces pending requests from epoch-ms timestamps
with deterministic predictive_* IDs and DNP-BATCH logging.
Replace reminder_* and random test alarm IDs with predictive_<Int>
so UNUserNotificationCenter replaces pending requests instead of
stacking. Daily reminders key off local HH:mm; testAlarm uses the
scheduled fire second. Dual notification id unchanged.
Add jwtTokens / jwtTokenPoolJson to the TypeScript API, parse and validate
(max 128) on Android and iOS, persist jwtTokenPool with native_fetcher_config
when persistToken is true (Android), and extend NativeNotificationContentFetcher
with a four-argument configure overload delegating to the existing three-arg
default. iOS stores the pool in UserDefaults JSON and uses primary jwt or first
pool entry in the plugin background fetch path. Bump version to 2.2.0. Update
TestNativeFetcher to exercise the new configure overload.
NotificationContent.title and .body are String?; assigning them to
non-optional String caused Swift build errors. Use ?? with the same
defaults as the config fallback so both branches yield non-optional
title/body.
- Android: move plugin source to org/timesafari/dailynotification, update
namespace, manifest package, and all package/imports; change intent actions
to org.timesafari.daily.NOTIFICATION and DISMISS
- iOS: update bundle IDs, BGTask identifiers, subsystem labels, and queue
names in Plugin and Xcode projects
- Capacitor: update plugin class registration and appIds in configs
- Test apps (android-test-app, daily-notification-test, ios-test-app):
applicationId/bundleId, manifests, ProGuard, scripts, and docs
- Docs: bulk update references; add CONSUMING_APP_MIGRATION_COM_TO_ORG.md
for consuming app migration
BREAKING CHANGE: Consuming apps must update plugin class to
org.timesafari.dailynotification.DailyNotificationPlugin, manifest
receivers/actions, and iOS BGTask identifiers per migration doc.
Add optional rolloverIntervalMinutes to scheduleDailyNotification so the
next occurrence can be scheduled N minutes after the current trigger
(e.g. 10 minutes) instead of 24 hours. Value is persisted and used on
rollover and after reboot.
- TypeScript: NotificationOptions.rolloverIntervalMinutes?: number
- Android: Schedule.rolloverIntervalMinutes in Room (migration 2→3);
Plugin and ScheduleHelper persist it; Worker uses it in rollover and
updates nextRunAt; ReactivationManager uses it in boot recovery
- iOS: NotificationContent.rolloverIntervalMinutes (Codable); Plugin
passes it into content; Scheduler uses it in calculateNextScheduledTime
and copies to nextContent on rollover
When absent or ≤0, behavior unchanged (24h). App can clear by calling
scheduleDailyNotification without the parameter.
Update package.json, iOS podspec, and Android plugin-version references
after fix for duplicate fallback notifications (cancel fetch-related
WorkManager jobs when scheduling daily notification).
Version bump reflects new features merged from ios-2 branch:
- iOS rollover recovery for background/inactive app scenarios
- Build script improvements and iOS support
- Test app enhancements and UI improvements
This is a MINOR version bump per semantic versioning due to
backward-compatible feature additions.
Fixes iOS build failures caused by linker picking up macOS SQLite
libraries from pkgx instead of iOS system SQLite, resulting in
undefined symbol errors for all sqlite3 functions.
Changes:
- Explicitly link system SQLite library (-lsqlite3) in podspec
- Detect and unset pkgx environment variables during iOS builds
- Add warnings to guide users if manual intervention needed
The issue occurs when pkgx (or similar package managers) set
DYLD_LIBRARY_PATH or PKGX_DIR, causing the linker to find macOS
SQLite dylibs at /Users/*/.pkgx/sqlite.org/*/lib/libsqlite3.0.dylib
instead of the iOS system SQLite library.
This fix ensures the iOS build always uses the correct system SQLite
library regardless of environment variable interference.
Adds a comprehensive clean script that removes all build artifacts,
caches, and dependencies to help reproduce build issues across
different development environments.
The script cleans:
- TypeScript build output (dist/)
- iOS plugin artifacts (Pods, Podfile.lock, build dirs)
- Android plugin artifacts (build dirs, optional .gradle cache)
- Test app artifacts (node_modules, dist/, iOS/Android builds)
- Optional: Xcode DerivedData, Gradle cache, node_modules reinstall
Usage:
./scripts/clean-build.sh # Basic clean
./scripts/clean-build.sh --all # Full clean with reinstall
This is particularly useful when troubleshooting build failures
that may be environment-specific (different Xcode, CocoaPods,
macOS, or Node versions).
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.
Fixed compilation error where userInfo was referenced outside its scope
in handleNotificationDelivery error logging. Changed to use
notification.userInfo directly.
Add comprehensive logging to trace rollover notification handling
from AppDelegate delivery through to next notification scheduling.
This enables diagnosis of why rollover notifications fail to
schedule the next 24-hour notification.
Changes:
- Log observer registration on plugin load
- Log handler entry and data extraction in handleNotificationDelivery
- Log processing steps in processRollover including:
* Missing scheduler/storage detection
* Content lookup failures with available IDs
* ScheduleNextNotification success/failure
These logs will help identify whether the issue is:
- Observer not receiving notifications
- Content missing from storage
- Scheduling logic failing silently
Add testAlarm() method to iOS plugin for quick notification testing.
Fix plugin method discovery by registering testAlarm in CAPBridgedPlugin
pluginMethods array. Add force-load code in AppDelegate to ensure plugin
is discovered by Capacitor's objc_getClassList scan.
Changes:
- Add testAlarm() implementation in DailyNotificationPlugin.swift
- Register testAlarm in pluginMethods array (required for Capacitor discovery)
- Add force-load code in test app AppDelegate (matches working ios-test-app)
- Add UNUserNotificationCenterDelegate to show notifications in foreground
- Add test notification button to ScheduleView with immediate feedback
- Add debug logging for method discovery and plugin loading
Fixes issue where testAlarm was implemented but returned "UNIMPLEMENTED"
because it wasn't registered in the pluginMethods array. Also ensures
plugin class is loaded before Capacitor's discovery phase.
- Fix async/await usage in background fetch handler
- Fix Core Data metadata access errors
- Replace SQLITE_TRANSIENT with nil for Swift compatibility
- Fix PermissionStatus interface and type casts in test app
- Add iOS setup documentation to BUILDING.md
- Update iOS sync workflow to handle Podfile regeneration
Resolves all iOS compilation errors and improves test app setup process.
Improve documentation for remaining low-priority TODOs and address script false positives.
Changes:
- Scripts: Add exclusion note for intentional TODOs/FIXMEs in script
- Added note that script may contain intentional markers
- Clarifies that these should be excluded from scan results
- Android TimeSafariIntegrationManager: Convert TODOs to implementation notes
- Lines 320-321: Converted TODOs to implementation notes
- Documents planned refactoring work without TODO markers
- Maintains same information in clearer format
- iOS Phase 3 items: Improve placeholder comments
- activeDidIntegration: Added Phase 3 implementation note
- JWT-signed fetcher: Added Phase 3 implementation note
- Clarifies these are planned Phase 3 features
- TODO Report: Update checkboxes
- Marked Android integration items as complete/documentation
- Marked scripts items as complete/documentation
Progress:
- Low priority items: 8 of 15 complete (53%)
- Remaining: 7 items (Phase 3 features - explicitly deferred)
Verification:
- TypeScript typecheck: PASS
- All documentation improvements applied
- 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