Integrate DailyNotificationPlugin with notification UI to enable native notifications on iOS/Android while maintaining web push for web/PWA. - Add platform detection to PushNotificationPermission component - Implement native notification flow via NotificationService - Hide push server setting on native platforms (not needed) - Add time conversion (AM/PM to 24-hour) for native plugin - Add comprehensive documentation Breaking Changes: None (backward compatible)
12 KiB
Notification System Overview
Date: 2026-01-23
Purpose: Understanding notification architecture and implementation guide for daily-notification-plugin
Executive Summary
Your app has two separate notification systems that coexist:
-
Web Push Notifications (Web/PWA platforms)
- Uses service workers, VAPID keys, and a push server
- Requires the "Notification Push Server" setting
- Server-based delivery
-
Native Notifications (iOS/Android via DailyNotificationPlugin)
- Uses native OS notification APIs
- On-device scheduling (no server needed)
- The "Notification Push Server" setting is NOT used for native
The system automatically selects the correct implementation based on platform using Capacitor.isNativePlatform().
Notification Push Server Setting
Location
- File:
src/views/AccountViewView.vue(lines 506-549) - UI Section: Advanced Settings → "Notification Push Server"
- Database Field:
settings.webPushServer
Purpose
The "Notification Push Server" setting ONLY applies to Web Push notifications (web/PWA platforms). It configures:
- VAPID Key Retrieval: The server URL used to fetch VAPID (Voluntary Application Server Identification) keys
- Subscription Endpoint: Where push subscriptions are sent
- Push Message Delivery: The server that sends push messages to browsers
How It Works (Web Push Flow)
User enables notification
↓
PushNotificationPermission.vue opens
↓
Fetches VAPID key from: {webPushServer}/web-push/vapid
↓
Subscribes to browser push service
↓
Sends subscription + time + message to: {webPushServer}/web-push/subscribe
↓
Server stores subscription and schedules push messages
↓
Server sends push messages at scheduled time via browser push service
Key Code Locations
AccountViewView.vue (lines 1473-1479):
async onClickSavePushServer(): Promise<void> {
await this.$saveSettings({
webPushServer: this.webPushServerInput,
});
this.webPushServer = this.webPushServerInput;
this.notify.warning(ACCOUNT_VIEW_CONSTANTS.INFO.RELOAD_VAPID);
}
PushNotificationPermission.vue (lines 177-221):
- Retrieves
webPushServerfrom settings - Fetches VAPID key from
{webPushServer}/web-push/vapid - Uses VAPID key to subscribe to push notifications
PushNotificationPermission.vue (lines 556-575):
- Sends subscription to
/web-push/subscribeendpoint (relative URL, handled by service worker)
Important Notes
- ⚠️ This setting is NOT used for native iOS/Android notifications
- The setting defaults to
DEFAULT_PUSH_SERVERif not configured - Changing the server requires reloading VAPID keys (hence the warning message)
- Local development (
http://localhost) skips VAPID key retrieval
Daily Notification Plugin Integration
Current Status
✅ Infrastructure Complete:
- Plugin registered (
src/plugins/DailyNotificationPlugin.ts) - Service abstraction layer created (
src/services/notifications/) - Platform detection working
- Native implementation ready (
NativeNotificationService.ts)
🔄 UI Integration Needed:
PushNotificationPermission.vuestill uses web push logic- AccountViewView notification toggles need platform detection
- Settings storage needs to handle both systems
Architecture
NotificationService.getInstance()
↓
Platform Detection (Capacitor.isNativePlatform())
↓
┌─────────────────────┬─────────────────────┐
│ Native Platform │ Web Platform │
│ (iOS/Android) │ (Web/PWA) │
├─────────────────────┼─────────────────────┤
│ NativeNotification │ WebPushNotification │
│ Service │ Service │
│ │ │
│ Uses: │ Uses: │
│ - DailyNotification │ - Service Workers │
│ Plugin │ - VAPID Keys │
│ - Native OS APIs │ - Push Server │
│ - On-device alarms │ - Server scheduling │
└─────────────────────┴─────────────────────┘
Key Differences
| Feature | Native (Plugin) | Web Push |
|---|---|---|
| Server Required | ❌ No | ✅ Yes (Notification Push Server) |
| Scheduling | On-device | Server-side |
| Offline Delivery | ✅ Yes | ❌ No (requires network) |
| Background Support | ✅ Full | ⚠️ Limited (browser-dependent) |
| Permission Model | OS-level | Browser-level |
| Settings Storage | Local only | Local + server subscription |
Implementation Recommendations
1. Update PushNotificationPermission Component
Current State: Only handles web push
Recommended Changes:
// In PushNotificationPermission.vue
import { NotificationService } from '@/services/notifications';
import { Capacitor } from '@capacitor/core';
async open(pushType: string, callback?: ...) {
const isNative = Capacitor.isNativePlatform();
if (isNative) {
// Use native notification service
const service = NotificationService.getInstance();
const granted = await service.requestPermissions();
if (granted) {
// Show time picker UI
// Then schedule via service.scheduleDailyNotification()
}
} else {
// Existing web push logic
// ... current implementation ...
}
}
2. Update AccountViewView Notification Toggles
Current State: Always uses PushNotificationPermission component (web push)
Recommended Changes:
// In AccountViewView.vue
import { NotificationService } from '@/services/notifications';
import { Capacitor } from '@capacitor/core';
async showNewActivityNotificationChoice(): Promise<void> {
const isNative = Capacitor.isNativePlatform();
if (isNative) {
// Use native service directly
const service = NotificationService.getInstance();
// Show time picker, then schedule
} else {
// Use existing PushNotificationPermission component
(this.$refs.pushNotificationPermission as PushNotificationPermission)
.open(DAILY_CHECK_TITLE, ...);
}
}
3. Settings Storage Strategy
Current Settings Fields (from src/db/tables/settings.ts):
notifyingNewActivityTime- Time string for daily checknotifyingReminderTime- Time string for remindernotifyingReminderMessage- Reminder message textwebPushServer- Push server URL (web only)
Recommendation: These settings work for both systems:
- ✅
notifyingNewActivityTime- Works for both (native stores locally, web sends to server) - ✅
notifyingReminderTime- Works for both - ✅
notifyingReminderMessage- Works for both - ⚠️
webPushServer- Only used for web push (hide on native platforms)
4. Platform-Aware UI
Recommendations:
-
Hide "Notification Push Server" setting on native platforms:
<h2 v-if="!isNativePlatform" class="text-slate-500 text-sm font-bold mb-2"> Notification Push Server </h2> -
Update help text to explain platform differences
-
Show different messaging based on platform:
- Native: "Notifications are scheduled on your device"
- Web: "Notifications are sent via push server"
Notification Types
Your app supports two notification types:
1. Daily Check (DAILY_CHECK_TITLE)
- Purpose: Notify user of new activity/updates
- Message: Auto-generated by server (web) or app (native)
- Settings Field:
notifyingNewActivityTime
2. Direct Push (DIRECT_PUSH_TITLE)
- Purpose: Daily reminder with custom message
- Message: User-provided (max 100 characters)
- Settings Fields:
notifyingReminderTime,notifyingReminderMessage
Both types can be enabled simultaneously.
Code Flow Examples
Native Notification Flow (Recommended Implementation)
// 1. Get service instance
const service = NotificationService.getInstance();
// 2. Request permissions
const granted = await service.requestPermissions();
if (!granted) {
// Show error, guide to settings
return;
}
// 3. Schedule notification
await service.scheduleDailyNotification({
time: '09:00', // HH:mm format (24-hour)
title: 'Daily Check-In',
body: 'Time to check your TimeSafari activity',
priority: 'normal'
});
// 4. Save to settings
await this.$saveSettings({
notifyingNewActivityTime: '09:00'
});
// 5. Check status
const status = await service.getStatus();
console.log('Enabled:', status.enabled);
console.log('Time:', status.scheduledTime);
Web Push Flow (Current Implementation)
// 1. Open PushNotificationPermission component
(this.$refs.pushNotificationPermission as PushNotificationPermission)
.open(DAILY_CHECK_TITLE, async (success, timeText) => {
if (success) {
// Component handles:
// - VAPID key retrieval from webPushServer
// - Service worker subscription
// - Sending subscription to server
// Just save the time
await this.$saveSettings({
notifyingNewActivityTime: timeText
});
}
});
Testing Checklist
Native (iOS/Android)
- Request permissions works
- Notification appears at scheduled time
- Notification survives app close
- Notification survives device reboot
- Both notification types can be enabled
- Cancellation works correctly
Web Push
- VAPID key retrieval works
- Service worker subscription works
- Subscription sent to server
- Push messages received at scheduled time
- Works with different push server URLs
Platform Detection
- Correct service selected on iOS
- Correct service selected on Android
- Correct service selected on web
- Settings UI shows/hides appropriately
Key Files Reference
Core Notification Services
src/services/notifications/NotificationService.ts- Factory/selectorsrc/services/notifications/NativeNotificationService.ts- Native implementationsrc/services/notifications/WebPushNotificationService.ts- Web implementation (stub)
UI Components
src/components/PushNotificationPermission.vue- Web push UI (needs update)src/views/AccountViewView.vue- Settings UI (lines 506-549 for push server)
Settings & Constants
src/db/tables/settings.ts- Settings schemasrc/constants/app.ts-DEFAULT_PUSH_SERVERconstantsrc/libs/util.ts-DAILY_CHECK_TITLE,DIRECT_PUSH_TITLE
Plugin
src/plugins/DailyNotificationPlugin.ts- Plugin registration
Next Steps
- Update
PushNotificationPermission.vueto detect platform and use appropriate service - Update
AccountViewView.vuenotification toggles to use platform detection - Hide "Notification Push Server" setting on native platforms
- Test on real devices (iOS and Android)
- Update documentation with platform-specific instructions
Questions & Answers
Q: Do I need to configure the Notification Push Server for native apps?
A: No. The setting is only for web push. Native notifications are scheduled on-device.
Q: Can both notification systems be active at the same time?
A: No, they're mutually exclusive per platform. The app automatically selects the correct one.
Q: How do I test native notifications?
A: Use NotificationService.getInstance() and test on a real device (simulators have limitations).
Q: What happens if I change the push server URL?
A: Only affects web push. Users need to re-subscribe to push notifications with the new server.
Q: Can I use the same settings fields for both systems?
A: Yes! The time and message fields work for both. Only webPushServer is web-specific.
Last Updated: 2026-01-23