# 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), AccountViewView integration (settings UI) - **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 - **UI Integration**: AccountViewView modification with new notification section #### 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) - AccountViewView UI integration ### Dependency Complexity #### Internal Dependencies - **Medium**: - Router configuration (new routes) - Store creation (Pinia) - Component dependencies (ActionCard, StatusCard) - Logger integration (replace console.* with project logger) - AccountViewView modifications - Settings schema updates #### External Dependencies - **Medium**: - `@timesafari/daily-notification-plugin` (external package) - `@capacitor/core` (already in project) - 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 5. **AccountViewView Integration**: UI changes must not affect existing functionality - **Mitigation**: Use platform capability detection, hide UI on unsupported platforms --- ## 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) └── AccountViewView.vue (existing - add Daily Notifications section) ``` #### 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"), }, ``` --- ## AccountViewView Integration Strategy ### Overview Integrate daily notification scheduling into `AccountViewView.vue`, allowing users to configure notification times directly from their account settings. ### Integration Approach ✅ **ACCEPTED** **Decision**: Create a separate "Daily Notifications" section This approach adds a dedicated "Daily Notifications" section that checks PlatformService capabilities. On Capacitor platforms, it provides full functionality. On other platforms, the UI is hidden when PlatformService returns `null` for notification methods. **Key Benefits**: - Uses PlatformService interface pattern (consistent with camera, filesystem) - Platform-specific features properly isolated - Can use native time picker (better UX on mobile) - Future-proof: Easy to extend with additional notification features - Graceful degradation on unsupported platforms ### UI Component Design #### 1. Platform Capability Detection ```typescript // In AccountViewView component async checkNotificationSupport(): Promise { const platformService = PlatformServiceFactory.getInstance(); const status = await platformService.getDailyNotificationStatus(); return status !== null; // null means not supported } ``` #### 2. State Management ```typescript // Component properties nativeNotificationEnabled: boolean = false; nativeNotificationTime: string = ""; // Display format: "9:00 AM" nativeNotificationTimeStorage: string = ""; // Plugin format: "09:00" nativeNotificationTitle: string = "Daily Update"; nativeNotificationMessage: string = "Your daily notification is ready!"; notificationsSupported: boolean = false; // Computed from PlatformService ``` #### 3. Template Section ```vue

Daily Notifications

Daily Notification
Scheduled for: {{ nativeNotificationTime }}
``` #### 4. Time Input ✅ **SELECTED: HTML5 Time Input** **Decision**: Use HTML5 `` for native mobile experience ```vue ``` **Benefits**: - Native mobile time picker UI on Capacitor platforms - Simpler implementation (no custom time parsing needed) - Automatic 24-hour format output (compatible with plugin) - System handles locale-specific time formatting - Better UX on mobile devices **Note**: HTML5 time input provides time in "HH:mm" format (24-hour) which matches the plugin's expected format perfectly. #### 5. Time Format Conversion (Using System Time) **Key Principle**: Use device's local system time - no timezone conversions needed. The plugin handles system time natively. ```typescript // Convert "09:00" (plugin storage format) to "9:00 AM" (display) function formatTimeForDisplay(time24: string): string { const [hours, minutes] = time24.split(':'); const hourNum = parseInt(hours); const isPM = hourNum >= 12; const displayHour = hourNum === 0 ? 12 : hourNum > 12 ? hourNum - 12 : hourNum; return `${displayHour}:${minutes} ${isPM ? 'PM' : 'AM'}`; } // HTML5 time input provides "HH:mm" in local time - use directly // No UTC conversion needed - plugin handles local timezone function getTimeFromInput(timeInput: string): string { // timeInput is already in "HH:mm" format from // This is in the user's local timezone - pass directly to plugin return timeInput; // e.g., "09:00" in user's local time } ``` **Time Handling**: - **PlatformService Integration**: Uses device's local system time directly - NO UTC conversion needed. The plugin schedules notifications on the device itself, using the device's timezone. **Implementation Principles**: - HTML5 `` provides time in device's local timezone - Plugin receives time in "HH:mm" format and schedules relative to device's local time - No manual timezone conversion or UTC calculations needed - System automatically handles: - Timezone changes - Daylight saving time transitions - Device timezone updates - User sets "9:00 AM" in their local time → plugin schedules for 9:00 AM local time every day ### Data Flow #### 1. Initialization ```typescript async initializeState() { // ... existing initialization ... const platformService = PlatformServiceFactory.getInstance(); // Check if notifications are supported on this platform const status = await platformService.getDailyNotificationStatus(); if (status === null) { // Notifications not supported - don't initialize this.notificationsSupported = false; return; } this.notificationsSupported = true; // Load from settings const nativeNotificationTime = settings.nativeNotificationTime || ""; this.nativeNotificationEnabled = !!nativeNotificationTime; this.nativeNotificationTimeStorage = nativeNotificationTime; if (nativeNotificationTime) { this.nativeNotificationTime = formatTimeForDisplay(nativeNotificationTime); } // Update UI with current status this.notificationStatus = status; } ``` #### 2. Enable Notification ```typescript async enableNativeNotification() { try { const platformService = PlatformServiceFactory.getInstance(); // 1. Request permissions if needed const permissions = await platformService.checkNotificationPermissions(); if (permissions === null || permissions.notifications !== 'granted') { const result = await platformService.requestNotificationPermissions(); if (result === null || !result.notifications) { throw new Error("Notification permissions denied"); } } // 2. Schedule notification via PlatformService // Time is in device's local system time (from HTML5 time input) // PlatformService handles timezone and scheduling internally await platformService.scheduleDailyNotification({ time: this.nativeNotificationTimeStorage, // "09:00" in local time title: this.nativeNotificationTitle, body: this.nativeNotificationMessage, sound: true, priority: 'high' }); // 3. Save to settings await this.$saveSettings({ nativeNotificationTime: this.nativeNotificationTimeStorage, nativeNotificationTitle: this.nativeNotificationTitle, nativeNotificationMessage: this.nativeNotificationMessage, }); // 4. Update UI state this.nativeNotificationEnabled = true; this.notify.success("Daily notification scheduled successfully", TIMEOUTS.SHORT); } catch (error) { logger.error("Failed to enable notification:", error); this.notify.error("Failed to schedule notification. Please try again.", TIMEOUTS.LONG); } } ``` #### 3. Disable Notification ```typescript async disableNativeNotification() { try { const platformService = PlatformServiceFactory.getInstance(); // 1. Cancel notification via PlatformService await platformService.cancelDailyNotification(); // 2. Clear settings await this.$saveSettings({ nativeNotificationTime: "", nativeNotificationTitle: "", nativeNotificationMessage: "", }); // 3. Update UI state this.nativeNotificationEnabled = false; this.nativeNotificationTime = ""; this.nativeNotificationTimeStorage = ""; this.notify.success("Daily notification disabled", TIMEOUTS.SHORT); } catch (error) { logger.error("Failed to disable native notification:", error); this.notify.error("Failed to disable notification. Please try again.", TIMEOUTS.LONG); } } ``` #### 4. Edit Time **Approach**: Use inline HTML5 time input for quick edits ```typescript async editNativeNotificationTime() { // Show inline HTML5 time input for quick changes // For complex editing (title, message), navigate to ScheduleView this.showTimeEdit = true; } ``` **Implementation Note**: HTML5 time input provides native mobile picker experience when shown inline, making it ideal for quick time adjustments in AccountViewView. ### Settings Schema #### New Settings Fields ```typescript // Add to Settings interface in src/db/tables/settings.ts interface Settings { // ... existing fields ... // Native notification settings (Capacitor only) nativeNotificationTime?: string; // "09:00" format (24-hour) nativeNotificationTitle?: string; // Default: "Daily Update" nativeNotificationMessage?: string; // Default message } ``` #### Settings Persistence - Store in `settings` table via `$saveSettings()` - Use same pattern as `notifyingNewActivityTime` - Persist across app restarts - Sync with plugin state on component mount ### UI/UX Considerations #### Visual Design - **Section Style**: Match existing notification section (`bg-slate-100 rounded-md`) - **Toggle Switch**: Reuse existing custom toggle pattern - **Time Display**: Show in user-friendly format ("9:00 AM") - **Edit Button**: Small, subtle link/button to edit time #### User Feedback - **Success**: Toast notification when scheduled successfully - **Error**: Clear error message with troubleshooting guidance - **Loading**: Show loading state during plugin operations - **Permission Request**: Handle gracefully if denied #### Accessibility - **ARIA Labels**: Proper labels for all interactive elements - **Keyboard Navigation**: Full keyboard support - **Screen Reader**: Clear announcements for state changes ### Implementation Decisions ✅ #### Time Input Format ✅ - **Selected**: HTML5 `` for Capacitor platforms - **Rationale**: Native mobile experience, simpler code, automatic 24-hour format #### Edit Approach ✅ - **Selected**: Inline HTML5 time input for quick edits in AccountViewView - **Note**: For complex editing (title, message changes), users can navigate to dedicated ScheduleView #### Settings Field Names ✅ - **Selected**: `nativeNotificationTime`, `nativeNotificationTitle`, `nativeNotificationMessage` - **Rationale**: Clear distinction from web push notification fields #### Notification Title/Message ✅ - **Selected**: Allow customization, default to "Daily Update" / "Your daily notification is ready!" - **Rationale**: Flexibility for users, sensible defaults --- ## 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 & AccountViewView Integration **Complexity**: Medium **Goals**: Create reusable components, main views, and AccountViewView integration #### 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** - Add separate "Daily Notifications" section - Check platform capabilities before showing UI (`v-if="notificationsSupported"`) - Add computed property for platform capability detection - 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 - Implement time format conversion (display vs storage) - Add enable/disable notification methods - Add edit time functionality - Add permission request flow - Add error handling and user feedback #### Acceptance Criteria - [ ] ActionCard and StatusCard components created - [ ] Home view shows notification diagnostics - [ ] Schedule view allows notification scheduling - [ ] AccountViewView has separate "Daily Notifications" section - [ ] Notification section checks PlatformService capabilities before showing - [ ] Toggle and time input functional in AccountViewView - [ ] Settings persist across app restarts - [ ] Plugin state syncs with settings - [ ] All logging uses project logger - [ ] Error handling implemented - [ ] Loading states visible - [ ] UI matches existing design patterns --- ### 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 - Test AccountViewView integration on Capacitor 2. **Cross-Platform Validation** - Verify web build doesn't break - Verify Electron build doesn't break - Verify feature is hidden on non-Capacitor platforms - Verify AccountViewView section hidden on web/electron - Test graceful degradation 3. **Integration Testing** - Test full scheduling workflow - Test status checking workflow - Test navigation between views - Test store state persistence - Test AccountViewView enable/disable/edit workflows 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 - [ ] AccountViewView integration verified on all platforms - [ ] Integration tests passing - [ ] Error scenarios handled gracefully - [ ] Documentation updated --- ## Milestones ### Milestone 1: Foundation Complete **Success Criteria**: - PlatformService interface extended - Store created and tested - Routes accessible - No build regressions ### Milestone 2: Core Features Operational **Success Criteria**: - Home view shows diagnostics - Schedule view functional - AccountViewView integration complete - 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 - AccountViewView notification section rendering ### Integration Tests - Plugin API calls - Permission flows - Status updates - Navigation between views - AccountViewView enable/disable/edit workflows ### Platform Tests - **Capacitor Android**: Notification scheduling, permissions, status, AccountViewView UI - **Capacitor iOS**: Notification scheduling, permissions, status, AccountViewView UI - **Web**: Feature hidden, no errors, AccountViewView section hidden - **Electron**: Feature hidden, no errors, AccountViewView section hidden ### E2E Tests (Playwright) - Full notification scheduling workflow - Permission request flow - Status checking workflow - Error handling scenarios - AccountViewView notification configuration workflow --- ## 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 - AccountViewView component - Settings schema and persistence ### 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 Pattern**: Check capabilities via method results, not environment variables ### 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 - Verify AccountViewView section properly hidden ### 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 ### Risk 5: AccountViewView Integration Issues **Mitigation**: - Use platform capability detection before showing UI - Test on all platforms to ensure proper hiding - Follow existing UI patterns for consistency - Add comprehensive error handling --- ## Success Criteria Summary - [ ] Plugin integrated using PlatformService architecture - [ ] Feature works on Capacitor (Android/iOS) - [ ] Feature hidden/graceful on Web/Electron - [ ] All components created and functional - [ ] AccountViewView integration complete 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 6. **AccountViewView Integration**: Implement Daily Notifications section in Phase 2 --- **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 - `src/views/AccountViewView.vue` - Target component for integration