# Daily Notification Plugin - Architecture Overview ## System Architecture ``` ┌─────────────────────────────────────────────────────────────────┐ │ Vue Components │ │ (PushNotificationPermission.vue, AccountViewView.vue, etc.) │ └───────────────────────────┬─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ NotificationService (Factory) │ │ - Platform detection via Capacitor API │ │ - Singleton pattern │ │ - Returns appropriate implementation │ └───────────────────────────┬─────────────────────────────────────┘ │ ┌───────────┴────────────┐ ▼ ▼ ┌───────────────────────────┐ ┌────────────────────────────┐ │ NativeNotificationService │ │ WebPushNotificationService │ │ │ │ │ │ iOS/Android │ │ Web/PWA │ │ - UNUserNotificationCenter│ │ - Web Push API │ │ - NotificationManager │ │ - Service Workers │ │ - AlarmManager │ │ - VAPID keys │ │ - Background tasks │ │ - Push server │ └─────────────┬─────────────┘ └────────────┬───────────────┘ │ │ ▼ ▼ ┌─────────────────────────┐ ┌──────────────────────────────┐ │ DailyNotificationPlugin│ │ Existing Web Push Logic │ │ (Capacitor Plugin) │ │ (PushNotificationPermission)│ │ │ │ │ │ - Native iOS code │ │ - Service worker │ │ - Native Android code │ │ - VAPID subscription │ │ - SQLite storage │ │ - Push server integration │ └─────────────────────────┘ └──────────────────────────────┘ ``` ## Platform Decision Flow ``` User Action: Schedule Notification │ ▼ NotificationService.getInstance() │ ├──> Check: Capacitor.isNativePlatform() │ ┌────┴─────┐ │ │ YES NO │ │ ▼ ▼ Native Web/PWA Service Service │ │ ▼ ▼ Plugin Web Push ``` ## Data Flow Example: Scheduling a Notification ### Native Platform (iOS/Android) ``` 1. User clicks "Enable Notifications" │ 2. PushNotificationPermission.vue │ └─> NotificationService.getInstance() │ └─> Returns NativeNotificationService (detected iOS/Android) │ └─> nativeService.requestPermissions() │ └─> DailyNotification.requestPermissions() [Capacitor Plugin] │ └─> Native code requests OS permissions │ └─> Returns: { granted: true/false } 3. User sets time & message │ 4. nativeService.scheduleDailyNotification({ time: '09:00', ... }) │ └─> DailyNotification.scheduleDailyReminder({ ... }) │ └─> Native code: - Stores in SQLite - Schedules AlarmManager (Android) or UNNotificationRequest (iOS) - Returns: success/failure 5. At 9:00 AM: - Android: AlarmManager triggers → DailyNotificationReceiver - iOS: UNUserNotificationCenter triggers notification - Notification appears even if app is closed ``` ### Web Platform ``` 1. User clicks "Enable Notifications" │ 2. PushNotificationPermission.vue │ └─> NotificationService.getInstance() │ └─> Returns WebPushNotificationService (detected web) │ └─> webService.requestPermissions() │ └─> Notification.requestPermission() [Browser API] │ └─> Returns: 'granted'/'denied'/'default' 3. User sets time & message │ 4. webService.scheduleDailyNotification({ ... }) │ └─> [TODO] Subscribe to push service with VAPID │ └─> Send subscription to server with schedule time │ └─> Server sends push at scheduled time │ └─> Service worker receives → shows notification ``` ## File Organization ``` src/ ├── plugins/ │ └── DailyNotificationPlugin.ts [Plugin registration] │ ├── services/ │ └── notifications/ │ ├── index.ts [Barrel export] │ ├── NotificationService.ts [Factory + Interface] │ ├── NativeNotificationService.ts [iOS/Android impl] │ └── WebPushNotificationService.ts [Web impl stub] │ ├── components/ │ └── PushNotificationPermission.vue [UI - to be updated] │ └── views/ └── AccountViewView.vue [Settings UI] ``` ## Key Design Decisions ### 1. **Unified Interface** - Single `NotificationServiceInterface` for all platforms - Consistent API regardless of underlying implementation - Type-safe across TypeScript codebase ### 2. **Runtime Platform Detection** - No build-time configuration needed - Same code bundle for all platforms - Factory pattern selects implementation automatically ### 3. **Coexistence Strategy** - Web Push and Native run on different platforms - No conflicts - mutually exclusive at runtime - Allows gradual migration and testing ### 4. **Singleton Pattern** - One service instance per app lifecycle - Efficient resource usage - Consistent state management ## Permission Flow ### Android ``` App Launch ↓ Check if POST_NOTIFICATIONS granted (API 33+) │ ├─> YES: Ready to schedule │ └─> NO: Request runtime permission ↓ Show system dialog ↓ User grants/denies ↓ Schedule notifications (if granted) ``` ### iOS ``` App Launch ↓ Check notification authorization status │ ├─> authorized: Ready to schedule │ ├─> notDetermined: Request permission │ ↓ │ Show system dialog │ ↓ │ User grants/denies │ └─> denied: Guide user to Settings ``` ### Web ``` App Load ↓ Check Notification.permission │ ├─> "granted": Ready to subscribe │ ├─> "default": Request permission │ ↓ │ Show browser prompt │ ↓ │ User grants/denies │ └─> "denied": Cannot show notifications ``` ## Error Handling Strategy ```typescript // All methods return promises with success/failure try { const granted = await service.requestPermissions(); if (granted) { const success = await service.scheduleDailyNotification({...}); if (success) { // Show success message } else { // Show scheduling error } } else { // Show permission denied message } } catch (error) { // Log error and show generic error message logger.error('Notification error:', error); } ``` ## Background Execution ### Native (iOS/Android) - ✅ Full background support - ✅ Survives app termination - ✅ Survives device reboot (with BootReceiver) - ✅ Exact alarm scheduling - ✅ Works offline ### Web/PWA - ⚠️ Limited background support - ⚠️ Requires active service worker - ⚠️ Browser/OS dependent - ❌ Needs network for delivery - ⚠️ iOS: Only on Home Screen PWAs (16.4+) ## Storage ### Native ``` DailyNotificationPlugin ↓ SQLite Database (Room/Core Data) ↓ Stores: - Schedule configurations - Content cache - Delivery history - Callback registrations ``` ### Web ``` Web Push ↓ IndexedDB (via Dexie) ↓ Stores: - Settings (notifyingNewActivityTime, etc.) - Push subscription info - VAPID keys ``` ## Testing Strategy ### Unit Testing - Mock `Capacitor.isNativePlatform()` to test both paths - Test factory returns correct implementation - Test each service implementation independently ### Integration Testing - Test on actual devices (iOS/Android) - Test in browsers (Chrome, Safari, Firefox) - Verify notification delivery - Test permission flows ### E2E Testing - Schedule notification → Wait → Verify delivery - Test app restart scenarios - Test device reboot scenarios - Test permission denial recovery --- **Key Takeaway**: The architecture provides a clean separation between platforms while maintaining a unified API for Vue components. Platform detection happens automatically at runtime, and the appropriate notification system is used transparently.