# Daily Notification Plugin Integration Plan **Author**: Matthew Raymer **Date**: 2025-11-03 **Status**: 🎯 **PLANNING** - Feature planning phase **Feature**: Daily Notification Plugin Integration **Platform Scope**: Capacitor-only (Android/iOS) --- ## Executive Summary This plan outlines the integration of `@timesafari/daily-notification-plugin` into the TimeSafari application using the PlatformService interface pattern. The feature is implemented on all platforms via PlatformService, but only Capacitor platforms provide full functionality. Web and Electron platforms return `null` for unsupported operations. ### Key Requirements - **Platform**: All platforms (Capacitor provides full functionality, Web/Electron return null) - **Architecture**: PlatformService interface integration (all platforms implement, unsupported return null) - **Components**: Home view (diagnostics/status) + Schedule view (time setting) - **Store**: Pinia store for notification state management - **Routes**: New routes for schedule, notifications, history, settings views --- ## Complexity Assessment ### Technical Complexity: **Medium** #### Code Changes - **Medium**: New Vue components, Pinia store, router routes - **Pattern**: Following PlatformService interface pattern (like camera, filesystem methods) - all platforms implement, unsupported return null - **Integration**: Plugin API integration with error handling #### Platform Impact - **Single Platform**: Capacitor-only (Android/iOS) - **Conditional Loading**: Feature only loads on Capacitor platforms - **Graceful Degradation**: Web/Electron builds should not break when plugin unavailable #### Testing Requirements - **Comprehensive**: - Plugin availability detection - Permission request flows - Notification scheduling - Status checking - Cross-platform validation (ensure web/electron unaffected) ### Dependency Complexity #### Internal Dependencies - **Medium**: - Router configuration (new routes) - Store creation (Pinia) - Component dependencies (ActionCard, StatusCard) - Logger integration (replace console.* with project logger) #### External Dependencies - **Medium**: - `@timesafari/daily-notification-plugin` (external package) - Capacitor core APIs - Platform detection utilities #### Infrastructure Dependencies - **Low**: - Package.json update (add plugin dependency) - Vite conditional imports for Capacitor builds only - No infrastructure changes required ### Risk Factors 1. **Plugin Availability**: Plugin may not be available in package registry - **Mitigation**: Verify package availability, consider local development setup 2. **Platform Implementation**: All platforms must implement interface methods - **Mitigation**: Follow PlatformService pattern - Capacitor provides full implementation, Web/Electron return null or throw errors 3. **Web/Electron Compatibility**: Feature must not break non-Capacitor builds - **Mitigation**: Use dynamic imports with platform checks, graceful fallbacks 4. **Store State Management**: Notification state persistence - **Mitigation**: Follow existing Pinia patterns in codebase --- ## Platform Analysis ### Target Platform: Capacitor Only #### Capacitor Requirements - Android: API 21+ (already supported) - iOS: 13+ (already supported) - Native platform detection: `Capacitor.isNativePlatform()` #### Build Configuration - **Vite Config**: `vite.config.capacitor.mts` (already exists) - **Build Command**: `npm run build:capacitor` - **Conditional Import Pattern**: Dynamic import based on `process.env.VITE_PLATFORM === 'capacitor'` #### Platform Detection Strategy **Pattern**: PlatformService interface - all platforms implement methods Components check PlatformService capabilities by calling methods and checking for `null` returns: ```typescript // Components check capability via PlatformService const platformService = PlatformServiceFactory.getInstance(); const status = await platformService.getDailyNotificationStatus(); if (status === null) { // Notifications not supported on this platform - hide UI return; } // Continue with notification features ``` **Why PlatformService Pattern?** - Consistent with existing platform capabilities (camera, filesystem) - All platforms implement the interface (contract compliance) - Unsupported platforms return `null` or throw clear errors - Components handle capability detection via method results, not environment variables ### Web/Electron Implementation Strategy #### Web Platform - **Implementation**: All notification methods implemented in `WebPlatformService` - **Behavior**: Methods return `null` for status/permissions, throw errors for scheduling - **UI**: Components check for `null` responses to hide notification UI - **Plugin Import**: No plugin imports - methods return null/throw errors directly #### Electron Platform - **Implementation**: All notification methods implemented in `ElectronPlatformService` - **Behavior**: Methods return `null` for status/permissions, throw errors for scheduling - **UI**: Components check for `null` responses to hide notification UI - **Plugin Import**: No plugin imports - methods return null/throw errors directly --- ## Architecture Design ### PlatformService Integration **Key Pattern**: Add notification methods directly to `PlatformService` interface, implemented on all platforms. Unsupported platforms return `null` or empty results. This follows the same pattern as other platform capabilities (camera, filesystem) where all platforms implement the interface, but unsupported platforms return null/empty results. ```typescript // src/services/PlatformService.ts - Add to interface export interface PlatformService { // ... existing methods ... // Daily notification operations /** * Get the status of scheduled daily notifications * @returns Promise resolving to notification status, or null if not supported */ getDailyNotificationStatus(): Promise; /** * Check notification permissions * @returns Promise resolving to permission status, or null if not supported */ checkNotificationPermissions(): Promise; /** * Request notification permissions * @returns Promise resolving to permission result, or null if not supported */ requestNotificationPermissions(): Promise; /** * Schedule a daily notification * @param options - Notification scheduling options * @returns Promise that resolves when scheduled, or rejects if not supported */ scheduleDailyNotification(options: ScheduleOptions): Promise; /** * Cancel scheduled daily notification * @returns Promise that resolves when cancelled, or rejects if not supported */ cancelDailyNotification(): Promise; /** * Configure native fetcher for background operations * @param config - Native fetcher configuration * @returns Promise that resolves when configured, or null if not supported */ configureNativeFetcher(config: NativeFetcherConfig): Promise; /** * Update starred plans for background fetcher * @param plans - Starred plan IDs * @returns Promise that resolves when updated, or null if not supported */ updateStarredPlans(plans: { planIds: string[] }): Promise; } ``` **Implementation Pattern**: - **CapacitorPlatformService**: Full implementation using `@timesafari/daily-notification-plugin` - **WebPlatformService**: Returns `null` for status/permissions, throws errors for scheduling operations - **ElectronPlatformService**: Returns `null` for status/permissions, throws errors for scheduling operations ### PlatformService Interface Extensions ```typescript // Types/interfaces for notification operations export interface NotificationStatus { isScheduled: boolean; scheduledTime?: string; // "HH:mm" format lastTriggered?: string; permissions: PermissionStatus; } export interface PermissionStatus { notifications: 'granted' | 'denied' | 'prompt'; exactAlarms?: 'granted' | 'denied' | 'prompt'; // Android only } export interface PermissionResult { notifications: boolean; exactAlarms?: boolean; // Android only } export interface ScheduleOptions { time: string; // "HH:mm" format in local time title: string; body: string; sound?: boolean; priority?: 'high' | 'normal' | 'low'; } export interface NativeFetcherConfig { apiServer: string; jwt: string; starredPlanHandleIds: string[]; } ``` **Implementation Behavior**: - **Capacitor**: Full implementation, all methods functional - **Web/Electron**: Status/permission methods return `null`, scheduling methods throw errors with clear messages ### Component Architecture #### Views Structure ``` src/views/ ├── HomeView.vue (existing - modify to add notification diagnostics) ├── ScheduleView.vue (new - notification scheduling) ├── NotificationsView.vue (new - view scheduled notifications) ├── NotificationHistoryView.vue (new - notification history) └── NotificationSettingsView.vue (new - notification settings) ``` #### Supporting Components ``` src/components/cards/ ├── ActionCard.vue (new - reusable action card) └── StatusCard.vue (new - reusable status card) ``` #### Store Structure ``` src/stores/ └── app.ts (new - Pinia store for app-wide state) - notificationStatus: NotificationStatus | null - platform: 'web' | 'capacitor' | 'electron' - setNotificationStatus(status): void ``` ### Router Integration ```typescript // src/router/index.ts - Add new routes { path: "/schedule", name: "schedule", component: () => import("../views/ScheduleView.vue"), }, { path: "/notifications", name: "notifications", component: () => import("../views/NotificationsView.vue"), }, { path: "/history", name: "notification-history", component: () => import("../views/NotificationHistoryView.vue"), }, { path: "/settings", name: "settings", component: () => import("../views/NotificationSettingsView.vue"), }, ``` --- ## Phase Breakdown ### Phase 1: Foundation & Infrastructure **Complexity**: Low-Medium **Goals**: Set up factory architecture, store, and conditional loading #### Tasks 1. **Package Dependency** - Add `@timesafari/daily-notification-plugin` to `package.json` - Verify package availability/version - Document in dependencies section 2. **PlatformService Interface Extension** - Add notification methods to `PlatformService` interface - Define notification types/interfaces (NotificationStatus, ScheduleOptions, etc.) - Implement in `CapacitorPlatformService` using `@timesafari/daily-notification-plugin` - Implement in `WebPlatformService` with null returns / error throws - Implement in `ElectronPlatformService` with null returns / error throws 3. **Pinia Store Setup** - Create `src/stores/app.ts` with notification state - Define `NotificationStatus` interface - Implement `setNotificationStatus()` action - Add platform detection to store 4. **Native Fetcher Configuration Integration** - Update HomeView `configureNativeFetcher()` to use active DID management - Replace `TEST_USER_ZERO_CONFIG` references with `$getActiveIdentity()` - Replace `generateEndorserJWT` with `createEndorserJwtForDid()` from `src/libs/endorserServer.ts` - Get `apiServer` and `starredPlanHandleIds` from `$accountSettings()` 5. **Router Routes** - Add route definitions for schedule, notifications, history, settings - Test route navigation #### Acceptance Criteria - [ ] PlatformService interface extended with notification methods - [ ] CapacitorPlatformService implements notification methods using plugin - [ ] WebPlatformService and ElectronPlatformService return null/throw errors appropriately - [ ] Pinia store created and tested - [ ] HomeView `configureNativeFetcher()` updated to use active DID (no TEST_USER_ZERO_CONFIG) - [ ] Routes added and accessible - [ ] No build errors in web/electron builds --- ### Phase 2: Core Components **Complexity**: Medium **Goals**: Create reusable components and main views #### Tasks 1. **Reusable Components** - Create `ActionCard.vue` component - Create `StatusCard.vue` component - Follow project styling patterns - Add TypeScript interfaces 2. **Home View Integration** - Modify existing `HomeView.vue` OR create new notification home view - Integrate plugin diagnostics - Add system status display - Connect to Pinia store - Replace `console.*` with project logger 3. **Schedule View** - Create `ScheduleView.vue` (provided code as reference) - Integrate with PlatformService via PlatformServiceFactory - Add error handling - Replace `console.*` with project logger - Add loading states 4. **AccountViewView Integration** ✅ **ACCEPTED: Option A** - Add separate "Daily Notifications" section - Check platform capabilities before showing UI - Add toggle switch for enabling/disabling notifications - Add HTML5 time input for scheduling time - Integrate with PlatformService via PlatformServiceFactory - Save/load settings from `settings` table #### Acceptance Criteria - [ ] ActionCard and StatusCard components created - [ ] Home view shows notification diagnostics - [ ] Schedule view allows notification scheduling - [ ] AccountViewView has separate "Daily Notifications" section (Option A accepted) - [ ] Notification section checks PlatformService capabilities before showing - [ ] Toggle and time input functional in AccountViewView - [ ] All logging uses project logger - [ ] Error handling implemented - [ ] Loading states visible --- ### Phase 3: Supporting Views & Configuration **Complexity**: Medium **Goals**: Complete all views and native fetcher configuration #### Tasks 1. **Supporting Views** - Create `NotificationsView.vue` (list scheduled notifications) - Create `NotificationHistoryView.vue` (notification history) - Create `NotificationSettingsView.vue` (settings/preferences) 2. **Native Fetcher Configuration** - Integrate `configureNativeFetcher()` in HomeView - Use `$getActiveIdentity()` to get active DID (replace TEST_USER_ZERO_CONFIG) - Use `createEndorserJwtForDid()` for JWT generation - Get `apiServer` and `starredPlanHandleIds` from `$accountSettings()` - Add error handling for configuration failures 3. **Permission Management** - Implement permission request flow - Handle permission denial gracefully - Update status after permission changes #### Acceptance Criteria - [ ] All supporting views created and functional - [ ] Native fetcher configuration working - [ ] Permission requests handled properly - [ ] Status updates after permission changes - [ ] Error handling for all failure cases --- ### Phase 4: Testing & Validation **Complexity**: Medium-High **Goals**: Comprehensive testing across platforms and scenarios #### Tasks 1. **Capacitor Testing** - Test plugin availability detection - Test notification scheduling on Android - Test notification scheduling on iOS - Test permission requests - Test status updates - Test native fetcher configuration 2. **Cross-Platform Validation** - Verify web build doesn't break - Verify Electron build doesn't break - Verify feature is hidden on non-Capacitor platforms - Test graceful degradation 3. **Integration Testing** - Test full scheduling workflow - Test status checking workflow - Test navigation between views - Test store state persistence 4. **Error Scenarios** - Test plugin unavailable scenarios - Test permission denied scenarios - Test network failures (for native fetcher) - Test invalid configuration scenarios #### Acceptance Criteria - [ ] All Capacitor tests passing - [ ] Web/Electron builds unaffected - [ ] Integration tests passing - [ ] Error scenarios handled gracefully - [ ] Documentation updated --- ## Milestones ### Milestone 1: Foundation Complete **Success Criteria**: - Factory service operational - Store created and tested - Routes accessible - No build regressions ### Milestone 2: Core Features Operational **Success Criteria**: - Home view shows diagnostics - Schedule view functional - Plugin integration working - Logging standardized ### Milestone 3: Full Feature Set **Success Criteria**: - All views created and functional - Native fetcher configured - Permissions managed properly - Status updates working ### Milestone 4: Production Ready **Success Criteria**: - All tests passing - Cross-platform validation complete - Error handling robust - Documentation complete --- ## Testing Strategy ### Unit Tests - Factory service platform detection - Store actions and state management - Component rendering and interactions ### Integration Tests - Plugin API calls - Permission flows - Status updates - Navigation between views ### Platform Tests - **Capacitor Android**: Notification scheduling, permissions, status - **Capacitor iOS**: Notification scheduling, permissions, status - **Web**: Feature hidden, no errors - **Electron**: Feature hidden, no errors ### E2E Tests (Playwright) - Full notification scheduling workflow - Permission request flow - Status checking workflow - Error handling scenarios --- ## Dependencies ### External Dependencies - `@timesafari/daily-notification-plugin` (to be added) - `@capacitor/core` (already in project) - `vue` (already in project) - `vue-router` (already in project) - `pinia` (already in project) ### Internal Dependencies - Logger service (`@/utils/logger`) - Platform detection utilities - Router configuration - Existing component patterns ### Configuration Dependencies - **Active DID Management**: Use `$getActiveIdentity()` from `PlatformServiceMixin` (existing) - **JWT Generation**: Use `createEndorserJwtForDid(activeDid, payload)` from `src/libs/endorserServer.ts` (existing) - **Settings Access**: Use `$accountSettings()` for `apiServer` and `starredPlanHandleIds` (existing) - **No new config files needed**: Replace `TEST_USER_ZERO_CONFIG` references with active DID and settings --- ## Implementation Notes ### Code Quality Standards - **Logging**: Use `logger` from `@/utils/logger`, not `console.*` - **File Documentation**: Add file-level documentation headers - **Method Documentation**: Rich method-level documentation - **Type Safety**: Full TypeScript typing - **PEP8/Prettier**: Follow code style guidelines - **Line Length**: Keep methods < 80 columns when possible ### Architecture Patterns to Follow - **Factory Pattern**: Like `QRScannerFactory` for conditional loading - **Service Interface**: Abstract interface with platform implementations - **Store Pattern**: Pinia store for state management - **Composition API vs Class**: Use provided code style (Composition API for HomeView, Class for ScheduleView) ### PlatformService Integration Strategy **Pattern**: Direct integration into PlatformService interface (like camera, filesystem methods) ```typescript // In components - use PlatformServiceFactory pattern import { PlatformServiceFactory } from '@/services/PlatformServiceFactory'; const platformService = PlatformServiceFactory.getInstance(); // Check if notifications are supported const status = await platformService.getDailyNotificationStatus(); if (status === null) { // Notifications not supported on this platform - hide UI return; } // Schedule notification await platformService.scheduleDailyNotification({ time: "09:00", title: "Daily Update", body: "Your daily notification is ready!", }); ``` **Key Points**: - Methods available on all PlatformService implementations - CapacitorPlatformService provides full implementation - WebPlatformService/ElectronPlatformService return `null` or throw errors - Components check for `null` responses to hide/show UI appropriately - No separate factory needed - uses existing PlatformServiceFactory pattern --- ## Risk Mitigation ### Risk 1: Plugin Package Unavailable **Mitigation**: - Verify package exists and is accessible - Consider local development setup if needed - Document package installation requirements ### Risk 2: Platform Detection Failures **Mitigation**: - Use proven patterns from `QRScannerFactory` - Test on all platforms - Add fallback logic ### Risk 3: Web/Electron Build Breaks **Mitigation**: - Use dynamic imports exclusively - Test web/electron builds after each phase - Ensure no static plugin imports ### Risk 4: Configuration Dependencies (RESOLVED) **Mitigation**: - **Use existing active DID management**: Use `$getActiveIdentity()` from `PlatformServiceMixin` to get currently selected DID - **Use existing JWT generation**: Use `createEndorserJwtForDid(activeDid, payload)` from `src/libs/endorserServer.ts` - **Use existing settings**: Get `apiServer` and `starredPlanHandleIds` from `$accountSettings()` - **No config files needed**: The HomeView component code references `TEST_USER_ZERO_CONFIG`, but should instead use the currently active DID and settings --- ## Success Criteria Summary - [ ] Plugin integrated using factory architecture - [ ] Feature works on Capacitor (Android/iOS) - [ ] Feature hidden/graceful on Web/Electron - [ ] All components created and functional - [ ] Store manages notification state - [ ] Router routes accessible - [ ] Logging standardized (no console.*) - [ ] Error handling robust - [ ] Cross-platform testing complete - [ ] Documentation updated - [ ] No build regressions --- ## Next Steps 1. **Verify Plugin Package**: Confirm `@timesafari/daily-notification-plugin` availability 2. **Update HomeView Configuration**: Replace `TEST_USER_ZERO_CONFIG` references in HomeView with existing active DID management (`$getActiveIdentity()`, `createEndorserJwtForDid()`, `$accountSettings()`) 3. **Extend PlatformService**: Add notification methods to PlatformService interface and implement in all platform services 4. **Set Up Store**: Create Pinia store for notification state 5. **Begin Phase 1 Implementation**: Start with foundation tasks --- **See also**: - `.cursor/rules/meta_feature_planning.mdc` - Feature planning workflow - `.cursor/rules/app/architectural_patterns.mdc` - Architecture patterns - `.cursor/rules/app/timesafari_platforms.mdc` - Platform requirements - `src/services/QRScanner/QRScannerFactory.ts` - Factory pattern reference