# Notification Integration Changes - Implementation Outline **Date**: 2026-01-23 **Purpose**: Detailed outline of changes needed to integrate DailyNotificationPlugin with UI --- ## Overview This document outlines all changes required to integrate the DailyNotificationPlugin with the existing notification UI, making it work seamlessly on both native (iOS/Android) and web platforms. **Estimated Complexity**: Medium **Estimated Files Changed**: 3-4 files **Breaking Changes**: None (backward compatible) --- ## Change Summary | File | Changes | Complexity | Risk | |------|---------|------------|------| | `PushNotificationPermission.vue` | Add platform detection, native flow | Medium | Low | | `AccountViewView.vue` | Platform detection in toggles, hide push server on native | Low | Low | | `WebPushNotificationService.ts` | Complete stub implementation (optional) | Medium | Low | --- ## Detailed Changes ### 1. PushNotificationPermission.vue **File**: `src/components/PushNotificationPermission.vue` **Current Lines**: ~656 lines **Estimated New Lines**: +50-80 lines **Complexity**: Medium #### Changes Required **A. Add Imports** (Top of script section) ```typescript import { Capacitor } from "@capacitor/core"; import { NotificationService } from "@/services/notifications"; ``` **B. Add Platform Detection Property** ```typescript // Add to class properties private get isNativePlatform(): boolean { return Capacitor.isNativePlatform(); } ``` **C. Modify `open()` Method** (Lines 170-258) - **Current**: Always initializes web push (VAPID key, service worker) - **Change**: Add platform check at start - If native: Skip VAPID/service worker, show UI immediately - If web: Keep existing logic **D. Modify `turnOnNotifications()` Method** (Lines 393-499) - **Current**: Web push subscription flow - **Change**: Split into two paths: - **Native path**: Use `NotificationService.getInstance()` → `requestPermissions()` → `scheduleDailyNotification()` - **Web path**: Keep existing logic **E. Add New Method: `turnOnNativeNotifications()`** - Request permissions via `NotificationService` - Convert time input (AM/PM) to 24-hour format (HH:mm) - Call `scheduleDailyNotification()` with proper options - Save to settings - Call callback with success/time/message **F. Update `handleTurnOnNotifications()` Method** (Line 643) - Add platform check - Route to `turnOnNativeNotifications()` or `turnOnNotifications()` based on platform **G. Update Computed Properties** - `isSystemReady`: For native, return `true` immediately (no VAPID needed) - `canShowNotificationForm`: For native, return `true` immediately **H. Update Template** (Optional - for better UX) - Add platform-specific messaging if desired - Native: "Notifications will be scheduled on your device" - Web: Keep existing messaging #### Code Structure Preview ```typescript async open(pushType: string, callback?: ...) { this.callback = callback || this.callback; this.isVisible = true; this.pushType = pushType; // Platform detection if (this.isNativePlatform) { // Native: No VAPID/service worker needed this.serviceWorkerReady = true; // Fake it for UI this.vapidKey = "native"; // Placeholder return; // Skip web push initialization } // Existing web push initialization... // (keep all existing code) } async turnOnNotifications() { if (this.isNativePlatform) { return this.turnOnNativeNotifications(); } // Existing web push logic... } private async turnOnNativeNotifications(): Promise { const service = NotificationService.getInstance(); // Request permissions const granted = await service.requestPermissions(); if (!granted) { // Handle permission denial return; } // Convert time to 24-hour format const time24h = this.convertTo24HourFormat(); // Determine title and body based on pushType const title = this.pushType === this.DAILY_CHECK_TITLE ? "Daily Check-In" : "Daily Reminder"; const body = this.pushType === this.DIRECT_PUSH_TITLE ? this.messageInput : "Time to check your TimeSafari activity"; // Schedule notification const success = await service.scheduleDailyNotification({ time: time24h, title, body, priority: 'normal' }); if (success) { // Save to settings const timeText = this.notificationTimeText; await this.$saveSettings({ [this.pushType === this.DAILY_CHECK_TITLE ? 'notifyingNewActivityTime' : 'notifyingReminderTime']: timeText, ...(this.pushType === this.DIRECT_PUSH_TITLE && { notifyingReminderMessage: this.messageInput }) }); // Call callback this.callback(true, timeText, this.messageInput); } } private convertTo24HourFormat(): string { const hour = parseInt(this.hourInput); const minute = parseInt(this.minuteInput); let hour24 = hour; if (!this.hourAm && hour !== 12) { hour24 = hour + 12; } else if (this.hourAm && hour === 12) { hour24 = 0; } return `${hour24.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`; } ``` #### Testing Considerations - Test on iOS device - Test on Android device - Test on web (should still work as before) - Test permission denial flow - Test time conversion (AM/PM → 24-hour) --- ### 2. AccountViewView.vue **File**: `src/views/AccountViewView.vue` **Current Lines**: 2124 lines **Estimated New Lines**: +20-30 lines **Complexity**: Low #### Changes Required **A. Add Import** (Top of script section, around line 739) ```typescript import { Capacitor } from "@capacitor/core"; ``` **B. Add Computed Property** (In class, around line 888) ```typescript private get isNativePlatform(): boolean { return Capacitor.isNativePlatform(); } ``` **C. Modify Notification Toggle Methods** (Lines 1134-1202) **`showNewActivityNotificationChoice()`** (Lines 1134-1158) - **Current**: Always uses `PushNotificationPermission` component - **Change**: Add platform check - If native: Use `NotificationService` directly (or still use component - it will handle platform) - If web: Keep existing logic - **Note**: Since we're updating `PushNotificationPermission` to handle both, this might not need changes, but we could add direct native path for cleaner code **`showReminderNotificationChoice()`** (Lines 1171-1202) - Same as above **D. Conditionally Hide Push Server Setting** (Lines 506-549) - Wrap the entire "Notification Push Server" section in `v-if="!isNativePlatform"` - This hides it on iOS/Android where it's not needed **E. Update Status Display** (Optional) - When showing notification status, could add platform indicator - "Native notification scheduled" vs "Web push subscription active" #### Code Structure Preview ```typescript // Add computed property private get isNativePlatform(): boolean { return Capacitor.isNativePlatform(); } // In template, wrap push server section:

Notification Push Server

// Optional: Update notification choice methods async showNewActivityNotificationChoice(): Promise { if (!this.notifyingNewActivity) { // Component now handles platform detection, so this can stay the same // OR we could add direct native path here for cleaner separation (this.$refs.pushNotificationPermission as PushNotificationPermission) .open(DAILY_CHECK_TITLE, async (success: boolean, timeText: string) => { // ... existing callback ... }); } else { // ... existing turn-off logic ... } } ``` #### Testing Considerations - Verify push server section hidden on iOS - Verify push server section hidden on Android - Verify push server section visible on web - Test notification toggles work on all platforms --- ### 3. WebPushNotificationService.ts (Optional Enhancement) **File**: `src/services/notifications/WebPushNotificationService.ts` **Current Lines**: 213 lines **Estimated New Lines**: +100-150 lines **Complexity**: Medium **Priority**: Low (can be done later) #### Changes Required **A. Complete `scheduleDailyNotification()` Implementation** - Extract logic from `PushNotificationPermission.vue` - Subscribe to push service - Send subscription to server - Return success status **B. Complete `cancelDailyNotification()` Implementation** - Get current subscription - Unsubscribe from push service - Notify server to stop sending **C. Complete `getStatus()` Implementation** - Check settings for `notifyingNewActivityTime` / `notifyingReminderTime` - Check service worker subscription status - Return combined status **Note**: This is optional because `PushNotificationPermission.vue` already handles web push. Completing this would allow using `NotificationService` directly for web too, but it's not required for the integration to work. --- ## Implementation Order ### Phase 1: Core Integration (Required) 1. ✅ Update `PushNotificationPermission.vue` with platform detection 2. ✅ Update `AccountViewView.vue` to hide push server on native 3. ✅ Test on native platforms ### Phase 2: Polish (Optional) 4. Complete `WebPushNotificationService.ts` implementation 5. Add platform-specific UI messaging 6. Add status indicators --- ## Risk Assessment ### Low Risk Changes - ✅ Adding platform detection (read-only check) - ✅ Conditionally hiding UI elements - ✅ Adding new code paths (not modifying existing) ### Medium Risk Changes - ⚠️ Modifying `turnOnNotifications()` flow (but we're adding, not replacing) - ⚠️ Time format conversion (need to test edge cases) ### Mitigation Strategies 1. **Backward Compatibility**: All changes are additive - existing web push flow remains unchanged 2. **Feature Flags**: Could add feature flag to enable/disable native notifications 3. **Gradual Rollout**: Test on one platform first (e.g., Android), then iOS 4. **Fallback**: If native service fails, could fall back to showing error message --- ## Testing Checklist ### Functional Testing - [ ] Native iOS: Request permissions → Schedule notification → Verify scheduled - [ ] Native Android: Request permissions → Schedule notification → Verify scheduled - [ ] Web: Existing flow still works (no regression) - [ ] Permission denial: Shows appropriate error message - [ ] Time conversion: AM/PM correctly converts to 24-hour format - [ ] Both notification types: Daily Check and Direct Push work on native - [ ] Settings persistence: Times saved correctly to database ### UI Testing - [ ] Push server setting hidden on iOS - [ ] Push server setting hidden on Android - [ ] Push server setting visible on web - [ ] Notification toggles work on all platforms - [ ] Time picker UI works on native (same as web) ### Edge Cases - [ ] 12:00 AM conversion (should be 00:00) - [ ] 12:00 PM conversion (should be 12:00) - [ ] Invalid time input handling - [ ] App restart: Notifications still scheduled - [ ] Device reboot: Notifications still scheduled (Android) --- ## Dependencies ### Required - ✅ `@capacitor/core` - Already in project - ✅ `@timesafari/daily-notification-plugin` - Already installed - ✅ `NotificationService` - Already created ### No New Dependencies Needed --- ## Estimated Effort | Task | Time Estimate | |------|---------------| | Update PushNotificationPermission.vue | 2-3 hours | | Update AccountViewView.vue | 30 minutes - 1 hour | | Testing on iOS | 1-2 hours | | Testing on Android | 1-2 hours | | Bug fixes & polish | 1-2 hours | | **Total** | **5-10 hours** | --- ## Rollback Plan If issues arise: 1. **Quick Rollback**: Revert changes to `PushNotificationPermission.vue` and `AccountViewView.vue` 2. **Partial Rollback**: Keep platform detection but disable native path (feature flag) 3. **No Data Migration Needed**: Settings structure unchanged --- ## Questions to Consider 1. **Should we keep using `PushNotificationPermission` component for native, or create separate native flow?** - **Recommendation**: Keep using component (simpler, less code duplication) 2. **Should we show different UI messaging for native vs web?** - **Recommendation**: Optional enhancement, not required for MVP 3. **Should we complete `WebPushNotificationService` now or later?** - **Recommendation**: Later (not blocking, existing component works) 4. **How to handle notification cancellation on native?** - **Recommendation**: Use `NotificationService.cancelDailyNotification()` in existing turn-off logic --- ## Next Steps After Implementation 1. Update documentation with platform-specific instructions 2. Add error handling for edge cases 3. Consider adding notification status display in UI 4. Test on real devices (critical for native notifications) 5. Monitor for any platform-specific issues --- **Last Updated**: 2026-01-23