# iOS Implementation Checklist **Author**: Matthew Raymer **Date**: 2025-12-08 **Status**: 🎯 **ACTIVE** - Implementation Tracking **Version**: 1.0.0 ## Purpose Complete checklist of iOS code that needs to be implemented for feature parity with Android. This checklist tracks all implementation tasks with checkboxes. **Reference**: - [iOS Implementation Directive](./ios-implementation-directive.md) - Implementation guide - [iOS Recovery Scenario Mapping](./ios-recovery-scenario-mapping.md) - Scenario details - [iOS Core Data Migration Guide](./ios-core-data-migration.md) - Database entities --- ## Phase 1: Cold Start Recovery (High Priority) ### 1.1 Create ReactivationManager - [x] Create new file: `ios/Plugin/DailyNotificationReactivationManager.swift` - [x] Implement class structure with properties: - [x] `notificationCenter: UNUserNotificationCenter` - [x] `database: DailyNotificationDatabase` - [x] `storage: DailyNotificationStorage` - [x] `scheduler: DailyNotificationScheduler` - [x] `TAG: String = "DNP-REACTIVATION"` - [x] Implement `init(database:storage:scheduler:)` initializer - [x] Implement `performRecovery()` async method - [x] Add timeout protection (2 seconds max) - [x] Add error handling (non-fatal, log only) ### 1.2 Scenario Detection - [x] Create `RecoveryScenario` enum: - [x] `.none` - No recovery needed - [x] `.coldStart` - App launched after termination - [x] `.termination` - App terminated, notifications missing - [x] `.warmStart` - App resumed (optimization) - [x] Implement `detectScenario() async throws -> RecoveryScenario`: - [x] Check if database has notifications (empty → `.none`) - [x] Get pending notifications from `UNUserNotificationCenter` - [x] Compare DB state with notification center state - [x] Return appropriate scenario ### 1.3 Cold Start Recovery Logic - [x] Implement `performColdStartRecovery() async throws -> RecoveryResult`: - [x] Detect missed notifications (scheduled_time < now, not delivered) - [x] Mark missed notifications in database (Phase 1: basic marking, Phase 2: add delivery_status) - [x] Update `last_delivery_attempt` timestamp (Phase 2: add property) - [x] Record in history table (Phase 1: logging only, Phase 2: database recording) - [x] Verify future notifications are scheduled - [x] Reschedule missing future notifications - [x] Return `RecoveryResult` with counts ### 1.4 Missed Notification Detection - [x] Implement `detectMissedNotifications() async throws -> [NotificationContent]`: - [x] Query storage for notifications with `scheduled_time < currentTime` - [x] Filter for missed notifications (Phase 1: time-based only, Phase 2: add delivery_status check) - [x] Return list of missed notifications - [x] Implement `markMissedNotification(_:) async throws`: - [x] Mark notification as missed (Phase 1: basic, Phase 2: add delivery_status property) - [x] Update notification in storage - [x] Record status change (Phase 1: logging, Phase 2: history table) ### 1.5 Future Notification Verification - [x] Implement `verifyFutureNotifications() async throws -> VerificationResult`: - [x] Get all future notifications from storage - [x] Get pending notifications from `UNUserNotificationCenter` - [x] Compare notification IDs - [x] Identify missing notifications - [x] Return verification result - [x] Implement `rescheduleMissingNotification(id:) async throws`: - [x] For each missing notification, reschedule using `DailyNotificationScheduler` - [x] Verify no duplicates created (scheduler handles this) - [x] Log rescheduling activity ### 1.6 Recovery Result Types - [x] Create `RecoveryResult` struct: - [x] `missedCount: Int` - [x] `rescheduledCount: Int` - [x] `verifiedCount: Int` - [x] `errors: Int` - [x] Create `VerificationResult` struct: - [x] `totalSchedules: Int` - [x] `notificationsFound: Int` - [x] `notificationsMissing: Int` - [x] `missingIds: [String]` ### 1.7 Integration with Plugin - [x] Add `reactivationManager` property to `DailyNotificationPlugin` - [x] Initialize `ReactivationManager` in `load()` method - [x] Call `performRecovery()` in `load()` method (async, non-blocking) - [x] Add logging with `DNP-REACTIVATION` tag - [x] Ensure recovery doesn't block app startup (Task-based async execution) ### 1.8 History Recording - [x] Implement `recordRecoveryHistory(_:scenario:)` method: - [x] Record recovery execution (Phase 1: logging with JSON, Phase 2: database table) - [x] Include scenario, counts, outcome - [x] Add diagnostic JSON with details - [x] Implement `recordRecoveryFailure(_:)` method: - [x] Record recovery errors (Phase 1: logging, Phase 2: database table) - [x] Include error message and error type ### 1.9 Testing - [x] Unit tests for scenario detection - [x] Unit tests for missed notification detection - [x] Unit tests for future notification verification - [x] Unit tests for boot detection - [x] Unit tests for recovery result types - [ ] Integration test for full recovery flow - [ ] Manual test with test scripts (`test-phase1.sh`) --- ## Phase 2: App Termination Detection (High Priority) ### 2.1 Termination Detection Logic - [x] Enhance `detectScenario()` to detect termination: - [x] Check if DB has notifications but no pending notifications - [x] Return `.termination` scenario - [x] Implement `handleTerminationRecovery() async throws`: - [x] Detect all missed notifications - [x] Mark all as missed - [x] Reschedule all future notifications - [x] Reschedule all fetch schedules (if applicable) ### 2.2 Comprehensive Recovery - [x] Implement `performFullRecovery() async throws -> RecoveryResult`: - [x] Handle all notifications (missed and future) - [x] Reschedule all missing notifications - [x] Batch operations for efficiency - [x] Return comprehensive result ### 2.3 Multiple Schedules Recovery - [x] Implement recovery for multiple schedules: - [x] Handle multiple notifications (batch processing) - [x] Batch operations for efficiency (single pending request query) - [x] Handle partial failures gracefully (continue on error) - [x] Separate missed vs future notifications for batch processing ### 2.4 Testing - [ ] Test termination detection accuracy - [ ] Test full recovery with multiple schedules - [ ] Test partial failure scenarios - [ ] Manual test with test scripts (`test-phase2.sh`) --- ## Phase 3: Background Task Registration & Boot Recovery (Medium Priority) ### 3.1 BGTaskScheduler Registration - [x] Verify `BGTaskScheduler` registration in `DailyNotificationPlugin.setupBackgroundTasks()`: - [x] Check `fetchTaskIdentifier` registration (already implemented) - [x] Check `notifyTaskIdentifier` registration (already implemented) - [x] Add verification method `verifyBGTaskRegistration()` in ReactivationManager - [x] Implement boot detection: - [x] Check system uptime on app launch - [x] Compare with last launch time (stored in UserDefaults) - [x] Detect if boot occurred recently (< 60 seconds threshold) ### 3.2 Boot Recovery Logic - [x] Implement `performBootRecovery() async throws`: - [x] Detect all missed notifications (past scheduled times) - [x] Mark all as missed - [x] Reschedule all future notifications - [x] Record boot recovery in history ### 3.3 Background Task Handlers - [ ] Enhance `handleBackgroundFetch` in `DailyNotificationBackgroundTasks.swift`: - [ ] Add recovery logic if needed - [ ] Schedule next background task - [ ] Handle expiration gracefully - [ ] Enhance `handleBackgroundNotify`: - [ ] Add recovery logic if needed - [ ] Schedule next background task ### 3.4 Testing - [ ] Test BGTaskScheduler registration - [ ] Test boot detection (simulate or manual) - [ ] Test boot recovery logic - [ ] Manual test with test scripts (`test-phase3.sh`) --- ## Core Data Entities (High Priority) ### 4.1 NotificationContent Entity - [x] Update `DailyNotificationModel.xcdatamodeld`: - [x] Add `NotificationContent` entity - [x] Add all 23 attributes (id, pluginVersion, timesafariDid, etc.) - [x] Set correct attribute types (String, Date, Int32, Int64, Bool) - [x] Add default values where specified - [x] Mark required vs optional attributes - [x] Add indexes: - [x] `timesafariDid` index - [x] `notificationType` index - [x] `scheduledTime` index - [x] Note: Core Data auto-generates class files with `codeGenerationType="class"` - [ ] Implement data conversion helpers (if needed): - [ ] `Date` ↔ `Long` (epoch milliseconds) conversion helpers - [ ] `Int64` ↔ `Long` conversion helpers ### 4.2 NotificationDelivery Entity - [x] Update `DailyNotificationModel.xcdatamodeld`: - [x] Add `NotificationDelivery` entity - [x] Add all 20 attributes - [x] Set correct attribute types - [x] Add default values - [x] Configure relationship: - [x] Add `notificationContent` relationship (to-one) - [x] Set deletion rule to `Nullify` (Core Data handles cascade via inverse) - [x] Add inverse relationship `deliveries` (to-many) on `NotificationContent` - [x] Add indexes: - [x] `notificationId` index - [x] `deliveryTimestamp` index - [x] Note: Core Data auto-generates class files ### 4.3 NotificationConfig Entity - [x] Update `DailyNotificationModel.xcdatamodeld`: - [x] Add `NotificationConfig` entity - [x] Add all 13 attributes - [x] Set correct attribute types - [x] Add default values - [x] Add indexes: - [x] `configKey` index - [x] `configType` index - [x] `timesafariDid` index - [x] Note: Core Data auto-generates class files ### 4.4 Data Access Layer - [x] Create DAO classes or extensions: - [x] `NotificationContentDAO` or extension methods - [x] `NotificationDeliveryDAO` or extension methods - [x] `NotificationConfigDAO` or extension methods - [x] Implement CRUD operations: - [x] Create/Insert methods - [x] Read/Query methods with predicates - [x] Update methods - [x] Delete methods - [x] Implement query helpers: - [x] Query by timesafariDid - [x] Query by notificationType - [x] Query by scheduledTime range - [x] Query by deliveryStatus ### 4.5 Persistence Controller Updates - [x] Update `PersistenceController` (if exists) or create: - [x] Handle new entities in initialization - [x] Add migration policies if needed - [x] Test database initialization (unit tests verify Core Data stack) - [x] Test Core Data stack: - [x] Entity creation (tested in DAO unit tests) - [x] Relationships (tested in NotificationDeliveryDAOTests) - [x] Cascade delete (tested in NotificationDeliveryDAOTests) - [x] Data conversion (tested in DailyNotificationDataConversionsTests) --- ## API Methods (Medium Priority) ### 5.1 Notification Permission Methods - [x] Implement `getNotificationPermissionStatus()`: - [x] Query `UNUserNotificationCenter.current().getNotificationSettings()` - [x] Map to `NotificationPermissionStatus` type - [x] Return authorization status - [x] Implement `requestNotificationPermission()`: - [x] Request authorization via `UNUserNotificationCenter` - [x] Handle user response - [x] Return `{ granted: boolean }` - [x] Implement `openNotificationSettings()`: - [x] Open iOS Settings app to notification settings - [x] Use `UIApplication.shared.open()` with settings URL ### 5.2 Background Task Methods - [x] Implement `getBackgroundTaskStatus()`: - [x] Check BGTaskScheduler registration - [x] Check Background App Refresh status (cannot check programmatically, return null) - [x] Return `BackgroundTaskStatus` object - [x] Implement `openBackgroundAppRefreshSettings()`: - [x] Open iOS Settings app to Background App Refresh - [x] Use `UIApplication.shared.open()` with settings URL ### 5.3 Pending Notifications Method - [x] Implement `getPendingNotifications()`: - [x] Query `UNUserNotificationCenter.current().getPendingNotificationRequests()` - [x] Map to `PendingNotification[]` array - [x] Return count and notification details - [x] Add to `pluginMethods` array in `DailyNotificationPlugin` ### 5.4 Register Methods in Plugin - [x] Add methods to `pluginMethods` array: - [x] `getNotificationPermissionStatus` - [x] `requestNotificationPermission` - [x] `getPendingNotifications` - [x] `getBackgroundTaskStatus` - [x] `openNotificationSettings` - [x] `openBackgroundAppRefreshSettings` --- ## Data Type Conversions (High Priority) ### 6.1 Time Conversions - [x] Create helper functions: - [x] `dateFromEpochMillis(_: Int64) -> Date` - [x] `epochMillisFromDate(_: Date) -> Int64` - [x] Use in all Core Data operations: - [x] When reading from database (Long → Date) - [x] When writing to database (Date → Long) ### 6.2 Numeric Conversions - [x] Ensure correct type mappings: - [x] `Int` → `Int32` for small integers - [x] `Long` → `Int64` for large integers - [x] `Boolean` → `Bool` (direct) ### 6.3 String Conversions - [x] Handle optional strings correctly: - [x] `String?` in Swift maps to optional in Core Data - [x] JSON fields stored as `String?` --- ## Logging & Observability (Medium Priority) ### 7.1 Recovery Logging - [ ] Add comprehensive logging: - [ ] `DNP-REACTIVATION: Starting app launch recovery` - [ ] `DNP-REACTIVATION: Detected scenario: [scenario]` - [ ] `DNP-REACTIVATION: Missed notifications detected: [count]` - [ ] `DNP-REACTIVATION: Future notifications verified: [count]` - [ ] `DNP-REACTIVATION: Recovery completed: [result]` - [ ] Add error logging: - [ ] `DNP-REACTIVATION: Recovery failed (non-fatal): [error]` - [ ] Include error details and stack trace ### 7.2 Metrics Recording - [ ] Record recovery metrics in history table: - [ ] Recovery execution time - [ ] Missed notification count - [ ] Rescheduled notification count - [ ] Error count - [ ] Add diagnostic JSON to history entries --- ## Error Handling (High Priority) ### 8.1 Recovery Error Handling - [ ] Ensure all recovery methods catch errors: - [ ] Database errors (non-fatal) - [ ] Notification center errors (non-fatal) - [ ] Scheduling errors (non-fatal) - [ ] Log errors but don't crash app - [ ] Return partial results if some operations fail ### 8.2 Error Types - [ ] Define iOS-specific error codes: - [ ] `NOTIFICATION_PERMISSION_DENIED` - [ ] `BACKGROUND_REFRESH_DISABLED` - [ ] `PENDING_NOTIFICATION_LIMIT_EXCEEDED` - [ ] `BG_TASK_NOT_REGISTERED` - [ ] `BG_TASK_EXECUTION_FAILED` - [ ] Map to error responses in plugin methods --- ## Testing (High Priority) ### 9.1 Unit Tests - [x] Test `ReactivationManager` initialization (DailyNotificationReactivationManagerTests) - [x] Test scenario detection logic: - [x] Test `.none` scenario (empty database) - [x] Test `.coldStart` scenario - [x] Test `.termination` scenario - [x] Test `.warmStart` scenario - [x] Test missed notification detection - [x] Test future notification verification - [x] Test recovery result creation - [x] Test data conversions (DailyNotificationDataConversionsTests) - [x] Test NotificationContentDAO (NotificationContentDAOTests) - [x] Test NotificationDeliveryDAO (NotificationDeliveryDAOTests) - [x] Test NotificationConfigDAO (NotificationConfigDAOTests) ### 9.2 Integration Tests - [ ] Test full recovery flow: - [ ] Schedule notification - [ ] Terminate app - [ ] Launch app - [ ] Verify recovery executed - [ ] Verify notifications rescheduled - [ ] Test error handling: - [ ] Test database errors - [ ] Test notification center errors - [ ] Verify app doesn't crash ### 9.3 Manual Testing - [ ] Run `test-phase1.sh` script - [ ] Run `test-phase2.sh` script - [ ] Run `test-phase3.sh` script - [ ] Test on physical device (not just simulator) - [ ] Test with Background App Refresh enabled/disabled - [ ] Test with notification permission granted/denied --- ## Documentation Updates (Low Priority) ### 10.1 Code Documentation - [ ] Add file-level documentation to `DailyNotificationReactivationManager.swift` - [ ] Add method-level documentation to all public methods - [ ] Add parameter documentation - [ ] Add return value documentation - [ ] Add error documentation ### 10.2 Implementation Status - [ ] Update `ios/Plugin/README.md` with implementation status - [ ] Mark completed features as ✅ - [ ] Update version numbers - [ ] Update "Last Updated" dates --- ## Summary **Total Tasks**: ~150+ implementation tasks **Priority Breakdown**: - **High Priority**: ~80 tasks (Phase 1, Core Data, API methods, Error handling) - **Medium Priority**: ~50 tasks (Phase 2, Phase 3, Logging) - **Low Priority**: ~20 tasks (Documentation) **Estimated Implementation Time**: - Phase 1: 2-3 days - Phase 2: 1-2 days - Phase 3: 1 day - Core Data: 2-3 days - API Methods: 1 day - Testing: 2-3 days - **Total**: ~10-15 days --- **Document Version**: 1.0.0 **Last Updated**: 2025-12-08 **Next Review**: After Phase 1 implementation