docs: add daily notification plugin integration planning documents

- Add comprehensive integration plan following meta_feature_planning workflow
- Add AccountViewView integration strategy with PlatformService approach
- Document architecture decisions: PlatformService interface integration
- Remove web/push notification references
- Document implementation phases and acceptance criteria
This commit is contained in:
Matthew Raymer
2025-11-03 10:03:08 +00:00
parent 1bb3f52a30
commit d576920810
2 changed files with 1130 additions and 0 deletions

View File

@@ -0,0 +1,658 @@
# 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<NotificationStatus | null>;
/**
* Check notification permissions
* @returns Promise resolving to permission status, or null if not supported
*/
checkNotificationPermissions(): Promise<PermissionStatus | null>;
/**
* Request notification permissions
* @returns Promise resolving to permission result, or null if not supported
*/
requestNotificationPermissions(): Promise<PermissionResult | null>;
/**
* Schedule a daily notification
* @param options - Notification scheduling options
* @returns Promise that resolves when scheduled, or rejects if not supported
*/
scheduleDailyNotification(options: ScheduleOptions): Promise<void>;
/**
* Cancel scheduled daily notification
* @returns Promise that resolves when cancelled, or rejects if not supported
*/
cancelDailyNotification(): Promise<void>;
/**
* 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<void | null>;
/**
* 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<void | null>;
}
```
**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