# Daily Notification Plugin - AccountViewView Integration Strategy **Author**: Matthew Raymer **Date**: 2025-11-03 **Status**: 🎯 **PLANNING** - UI integration strategy **Feature**: Daily Notification Scheduling in Account Settings --- ## Overview This document outlines the strategy for integrating daily notification scheduling into `AccountViewView.vue`, allowing users to configure notification times directly from their account settings. --- ## Current State Analysis ### Account Settings Context **Location**: `AccountViewView.vue` - Settings view for user account configuration **Integration Approach**: Add new "Daily Notifications" section for scheduling native daily notifications using PlatformService. --- ## Integration Strategy **Approach**: 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 **Implementation**: ```vue

Daily Notifications

Daily Notification
Scheduled for: {{ nativeNotificationTime }}
``` --- ## Approach Rationale **Decision Date**: 2025-11-03 **Status**: ✅ **ACCEPTED** - Will proceed with separate native notification section 1. **Clear Platform Distinction**: Users understand this is for mobile apps 2. **No Conflicts**: Doesn't interfere with disabled web notifications 3. **Better UX**: Can use native time picker on mobile 4. **Future-Proof**: Easy to extend with additional native notification features ### Implementation Status - [x] Approach decision finalized - [ ] Implementation begins (Phase 1) --- ## 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!"; ``` ### 3. 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. ### 4. 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 return; } // 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 --- ## Plugin Integration ### PlatformService Usage ```typescript 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 } ``` ### Key Operations (via PlatformService) 1. **Check Status**: `getDailyNotificationStatus()` - Returns status or `null` if unsupported 2. **Check Permissions**: `checkNotificationPermissions()` - Returns permissions or `null` if unsupported 3. **Request Permissions**: `requestNotificationPermissions()` - Requests permissions or returns `null` if unsupported 4. **Schedule**: `scheduleDailyNotification(options)` - Schedules notification or throws error if unsupported 5. **Cancel**: `cancelDailyNotification()` - Cancels notification or throws error if unsupported --- ## 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 Phases ### Phase 1: Basic Integration - [ ] Add platform detection property - [ ] Create native notification section in template - [ ] Add component state properties - [ ] Implement toggle functionality - [ ] Basic enable/disable operations ### Phase 2: Time Management - [ ] Add time input (HTML5 time picker) - [ ] Implement time format conversion - [ ] Add edit time functionality - [ ] Save/load time from settings ### Phase 3: Plugin Integration - [ ] Integrate with DailyNotificationFactory - [ ] Schedule notification on enable - [ ] Cancel notification on disable - [ ] Update notification on time change - [ ] Sync plugin state with settings ### Phase 4: Polish & Error Handling - [ ] Permission request flow - [ ] Error handling and user feedback - [ ] Status verification - [ ] Help/info dialogs - [ ] Accessibility improvements --- ## 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 --- ## Success Criteria - [ ] Native notification section appears only on Capacitor platforms - [ ] Toggle enables/disables notifications via plugin - [ ] Time can be set and edited - [ ] Settings persist across app restarts - [ ] Plugin state syncs with settings - [ ] Error handling provides clear user feedback - [ ] UI matches existing design patterns - [ ] Accessibility requirements met --- ## Related Components - **PlatformService**: Interface for platform capabilities (notification methods) - **PlatformServiceFactory**: Factory for getting platform service instance - **ScheduleView**: Dedicated scheduling interface (for complex editing) - **AccountViewView**: Main settings view (integration target) --- ## Next Steps 1. ~~**Decide on Approach**: Separate native notification section~~ ✅ **DECIDED** 2. **Define Settings Schema**: Add native notification fields to Settings interface 3. **Create UI Components**: Build notification section in AccountViewView 4. **Integrate Plugin**: Connect UI to DailyNotificationFactory service 5. **Test Flow**: Verify enable/disable/edit workflows 6. **Add Help Content**: Create help documentation for native notifications --- **See also**: - `doc/daily-notification-plugin-integration-plan.md` - Overall integration plan - `src/views/AccountViewView.vue` - Target component for integration - `src/services/PlatformService.ts` - PlatformService interface definition - `src/services/PlatformServiceFactory.ts` - Factory for platform service instances