Files
daily-notification-plugin/docs/IOS_IMPLEMENTATION_CHECKLIST.md
Matthew a90d08c425 feat(ios): add Core Data DAO layer and unit tests
Implement comprehensive data access layer for Core Data entities:

- Add NotificationContentDAO, NotificationDeliveryDAO, and NotificationConfigDAO
  with full CRUD operations and query helpers
- Add DailyNotificationDataConversions utility for type conversions
  (Date ↔ Int64, Int ↔ Int32, JSON, optional strings)
- Update PersistenceController with entity verification and migration policies
- Add comprehensive unit tests for all DAO classes and data conversions
- Update Core Data model with NotificationContent, NotificationDelivery,
  and NotificationConfig entities (relationships and indexes)
- Integrate ReactivationManager into DailyNotificationPlugin.load()

DAO Features:
- Create/Insert methods with dictionary support
- Read/Query methods with predicates (by timesafariDid, notificationType,
  scheduledTime range, deliveryStatus, etc.)
- Update methods (touch, updateDeliveryStatus, recordUserInteraction)
- Delete methods (by ID, by key, delete all)
- Relationship management (NotificationContent ↔ NotificationDelivery)
- Cascade delete support

Test Coverage:
- 328 lines: DailyNotificationDataConversionsTests (time, numeric, string, JSON)
- 490 lines: NotificationContentDAOTests (CRUD, queries, updates)
- 415 lines: NotificationDeliveryDAOTests (CRUD, relationships, cascade delete)
- 412 lines: NotificationConfigDAOTests (CRUD, queries, active filtering)

All tests use in-memory Core Data stack for isolation and speed.

Completes sections 4.4, 4.5, and 6.0 of iOS implementation checklist.
2025-12-09 02:23:05 -08:00

488 lines
17 KiB
Markdown

# 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