forked from trent_larson/crowd-funder-for-time-pwa
docs: add plugin state sync, time update logic, and component extraction
- Update initialization to sync with plugin state on mount (checks for pre-existing schedules) - Add updateNotificationTime() method to update schedule when time changes (cancel old, schedule new) - Extract DailyNotificationSection into dedicated component using vue-facing-decorator - Update component architecture to show DailyNotificationSection.vue structure - Update Phase 2 tasks to reflect component creation and AccountViewView integration - Add acceptance criteria for plugin state sync and time update functionality - Update verification checklist with new requirements
This commit is contained in:
@@ -255,18 +255,58 @@ export interface NativeFetcherConfig {
|
||||
#### Views Structure
|
||||
```
|
||||
src/views/
|
||||
└── AccountViewView.vue (existing - add Daily Notifications section)
|
||||
└── AccountViewView.vue (existing - add DailyNotificationSection component)
|
||||
```
|
||||
|
||||
#### Supporting Components (Optional - Only if AccountViewView needs extraction)
|
||||
#### Supporting Components
|
||||
```
|
||||
src/components/notifications/ (optional)
|
||||
├── NotificationToggle.vue (optional - extract toggle if AccountViewView too long)
|
||||
├── NotificationTimePicker.vue (optional - extract time picker if needed)
|
||||
└── NotificationStatusDisplay.vue (optional - extract status display if needed)
|
||||
src/components/notifications/
|
||||
└── DailyNotificationSection.vue (required - extracted section component)
|
||||
```
|
||||
|
||||
**Note**: Supporting components should only be created if AccountViewView exceeds reasonable length limits (>200 lines). Keep everything in AccountViewView if possible.
|
||||
**Component Structure**: `DailyNotificationSection.vue` will use vue-facing-decorator with ES6 classes
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<section
|
||||
v-if="notificationsSupported"
|
||||
id="sectionDailyNotifications"
|
||||
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
||||
aria-labelledby="dailyNotificationsHeading"
|
||||
>
|
||||
<!-- Daily Notifications UI -->
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||
import { logger } from "@/utils/logger";
|
||||
|
||||
/**
|
||||
* DailyNotificationSection Component
|
||||
*
|
||||
* A self-contained component for managing daily notification scheduling
|
||||
* in AccountViewView. This component handles platform detection, permission
|
||||
* requests, scheduling, and state management for daily notifications.
|
||||
*
|
||||
* Features:
|
||||
* - Platform capability detection (hides on unsupported platforms)
|
||||
* - Permission request flow
|
||||
* - Schedule/cancel notifications
|
||||
* - Time editing with HTML5 time input
|
||||
* - Settings persistence
|
||||
* - Plugin state synchronization
|
||||
*/
|
||||
@Component({
|
||||
name: "DailyNotificationSection",
|
||||
mixins: [PlatformServiceMixin],
|
||||
})
|
||||
export default class DailyNotificationSection extends Vue {
|
||||
// Component implementation here
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -422,7 +462,7 @@ function getTimeFromInput(timeInput: string): string {
|
||||
|
||||
### Data Flow
|
||||
|
||||
#### 1. Initialization
|
||||
#### 1. Initialization (Sync with Plugin State)
|
||||
|
||||
```typescript
|
||||
async initializeState() {
|
||||
@@ -440,13 +480,33 @@ async initializeState() {
|
||||
|
||||
this.notificationsSupported = true;
|
||||
|
||||
// Load from settings
|
||||
const nativeNotificationTime = settings.nativeNotificationTime || "";
|
||||
this.nativeNotificationEnabled = !!nativeNotificationTime;
|
||||
this.nativeNotificationTimeStorage = nativeNotificationTime;
|
||||
// CRITICAL: Sync with plugin state first (source of truth)
|
||||
// Plugin may have an existing schedule even if settings don't
|
||||
if (status.isScheduled && status.scheduledTime) {
|
||||
// Plugin has a scheduled notification - sync UI to match
|
||||
this.nativeNotificationEnabled = true;
|
||||
this.nativeNotificationTimeStorage = status.scheduledTime;
|
||||
this.nativeNotificationTime = formatTimeForDisplay(status.scheduledTime);
|
||||
|
||||
if (nativeNotificationTime) {
|
||||
this.nativeNotificationTime = formatTimeForDisplay(nativeNotificationTime);
|
||||
// Also sync settings to match plugin state
|
||||
const settings = await this.$accountSettings();
|
||||
if (settings.nativeNotificationTime !== status.scheduledTime) {
|
||||
await this.$saveSettings({
|
||||
nativeNotificationTime: status.scheduledTime,
|
||||
nativeNotificationTitle: settings.nativeNotificationTitle || this.nativeNotificationTitle,
|
||||
nativeNotificationMessage: settings.nativeNotificationMessage || this.nativeNotificationMessage,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// No plugin schedule - check settings for user preference
|
||||
const settings = await this.$accountSettings();
|
||||
const nativeNotificationTime = settings.nativeNotificationTime || "";
|
||||
this.nativeNotificationEnabled = !!nativeNotificationTime;
|
||||
this.nativeNotificationTimeStorage = nativeNotificationTime;
|
||||
|
||||
if (nativeNotificationTime) {
|
||||
this.nativeNotificationTime = formatTimeForDisplay(nativeNotificationTime);
|
||||
}
|
||||
}
|
||||
|
||||
// Update UI with current status
|
||||
@@ -454,6 +514,12 @@ async initializeState() {
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- `getDailyNotificationStatus()` is called on mount to check for pre-existing schedules
|
||||
- Plugin state is the source of truth - if plugin has a schedule, UI syncs to match
|
||||
- Settings are synced with plugin state if they differ
|
||||
- If no plugin schedule exists, fall back to settings
|
||||
|
||||
#### 2. Enable Notification
|
||||
|
||||
```typescript
|
||||
@@ -529,18 +595,63 @@ async disableNativeNotification() {
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Edit Time
|
||||
#### 4. Edit Time (Update Schedule)
|
||||
|
||||
**Approach**: Use inline HTML5 time input for quick edits
|
||||
**Approach**: When time changes, immediately update the scheduled notification
|
||||
|
||||
```typescript
|
||||
async editNativeNotificationTime() {
|
||||
// Show inline HTML5 time input for quick changes
|
||||
this.showTimeEdit = true;
|
||||
}
|
||||
|
||||
async updateNotificationTime(newTime: string) {
|
||||
// newTime is in "HH:mm" format from HTML5 time input
|
||||
if (!this.nativeNotificationEnabled) {
|
||||
// If notification is disabled, just save the time preference
|
||||
this.nativeNotificationTimeStorage = newTime;
|
||||
this.nativeNotificationTime = formatTimeForDisplay(newTime);
|
||||
await this.$saveSettings({
|
||||
nativeNotificationTime: newTime,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Notification is enabled - update the schedule
|
||||
try {
|
||||
const platformService = PlatformServiceFactory.getInstance();
|
||||
|
||||
// 1. Cancel existing notification
|
||||
await platformService.cancelDailyNotification();
|
||||
|
||||
// 2. Schedule with new time
|
||||
await platformService.scheduleDailyNotification({
|
||||
time: newTime, // "09:00" in local time
|
||||
title: this.nativeNotificationTitle,
|
||||
body: this.nativeNotificationMessage,
|
||||
sound: true,
|
||||
priority: 'high'
|
||||
});
|
||||
|
||||
// 3. Update local state
|
||||
this.nativeNotificationTimeStorage = newTime;
|
||||
this.nativeNotificationTime = formatTimeForDisplay(newTime);
|
||||
|
||||
// 4. Save to settings
|
||||
await this.$saveSettings({
|
||||
nativeNotificationTime: newTime,
|
||||
});
|
||||
|
||||
this.notify.success("Notification time updated successfully", TIMEOUTS.SHORT);
|
||||
this.showTimeEdit = false;
|
||||
} catch (error) {
|
||||
logger.error("Failed to update notification time:", error);
|
||||
this.notify.error("Failed to update notification time. Please try again.", TIMEOUTS.LONG);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation Note**: HTML5 time input provides native mobile picker experience when shown inline, making it ideal for quick time adjustments in AccountViewView.
|
||||
**Implementation Note**: HTML5 time input provides native mobile picker experience when shown inline, making it ideal for quick time adjustments. When the time changes, the notification schedule is immediately updated via PlatformService.
|
||||
|
||||
### Settings Schema
|
||||
|
||||
@@ -643,39 +754,46 @@ interface Settings {
|
||||
**Goals**: Integrate notification scheduling into AccountViewView with optional supporting components
|
||||
|
||||
#### Tasks
|
||||
1. **Supporting Components (Optional)**
|
||||
- [ ] Create supporting components only if AccountViewView exceeds length limits
|
||||
- [ ] Consider: `NotificationToggle.vue`, `NotificationTimePicker.vue`, `NotificationStatusDisplay.vue`
|
||||
- [ ] Follow project styling patterns
|
||||
- [ ] Add TypeScript interfaces
|
||||
- [ ] Keep components focused and reusable within AccountViewView context
|
||||
|
||||
2. **AccountViewView Integration** ✅ **ACCEPTED**
|
||||
- [ ] Add separate "Daily Notifications" section
|
||||
- [ ] Check platform capabilities before showing UI (`v-if="notificationsSupported"`)
|
||||
- [ ] Add computed property for platform capability detection
|
||||
1. **DailyNotificationSection Component**
|
||||
- [ ] Create `src/components/notifications/DailyNotificationSection.vue`
|
||||
- [ ] Use vue-facing-decorator with ES6 class extending Vue
|
||||
- [ ] Add PlatformServiceMixin to component
|
||||
- [ ] Implement platform capability detection on mount
|
||||
- [ ] Implement initialization that syncs with plugin state (checks for pre-existing schedules)
|
||||
- [ ] 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 edit time functionality with schedule update (cancel old, schedule new)
|
||||
- [ ] Add permission request flow
|
||||
- [ ] Add error handling and user feedback
|
||||
- [ ] Save/load settings from `settings` table
|
||||
- [ ] Follow project styling patterns
|
||||
- [ ] Add TypeScript interfaces
|
||||
- [ ] Add file-level documentation
|
||||
|
||||
2. **AccountViewView Integration**
|
||||
- [ ] Import DailyNotificationSection component
|
||||
- [ ] Add component to template (minimal integration)
|
||||
- [ ] Verify component renders correctly
|
||||
- [ ] Test component hiding on unsupported platforms
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] Supporting components created only if AccountViewView exceeds length limits
|
||||
- [ ] AccountViewView has separate "Daily Notifications" section
|
||||
- [ ] **AccountViewView notification section hidden on unsupported platforms** (`v-if="notificationsSupported"`)
|
||||
- [ ] Notification section checks PlatformService capabilities before showing
|
||||
- [ ] Toggle and time input functional in AccountViewView
|
||||
- [ ] DailyNotificationSection component created using vue-facing-decorator
|
||||
- [ ] Component extends Vue class with PlatformServiceMixin
|
||||
- [ ] Component checks platform support on mount via `getDailyNotificationStatus()`
|
||||
- [ ] Component syncs with plugin state on initialization (checks for pre-existing schedules)
|
||||
- [ ] Component hidden on unsupported platforms (`v-if="notificationsSupported"`)
|
||||
- [ ] Toggle and time input functional
|
||||
- [ ] Time changes update notification schedule immediately (cancel old, schedule new)
|
||||
- [ ] Settings persist across app restarts
|
||||
- [ ] Plugin state syncs with settings
|
||||
- [ ] Plugin state syncs with settings on mount
|
||||
- [ ] All logging uses project logger
|
||||
- [ ] Error handling implemented
|
||||
- [ ] Loading states visible
|
||||
- [ ] UI matches existing design patterns
|
||||
- [ ] AccountViewView integration is minimal (just imports and uses component)
|
||||
|
||||
---
|
||||
|
||||
@@ -837,16 +955,16 @@ async mounted() {
|
||||
|
||||
#### Components That Must Implement This Pattern
|
||||
|
||||
1. **AccountViewView.vue**: Daily Notifications section uses `v-if="notificationsSupported"`
|
||||
2. **Supporting components** (if created): Must check support before rendering any scheduling UI
|
||||
3. **Any component providing scheduling UI**: Must verify `getDailyNotificationStatus() !== null` before showing scheduling controls
|
||||
1. **DailyNotificationSection.vue**: Daily Notifications section uses `v-if="notificationsSupported"` and checks `getDailyNotificationStatus()` on mount
|
||||
2. **Any component providing scheduling UI**: Must verify `getDailyNotificationStatus() !== null` before showing scheduling controls
|
||||
|
||||
#### Verification Checklist
|
||||
|
||||
- [ ] AccountViewView notification section hidden via `v-if` on unsupported platforms
|
||||
- [ ] Supporting components (if created) check and hide on unsupported platforms
|
||||
- [ ] All components tested on Web/Electron to verify hiding works
|
||||
- [ ] DailyNotificationSection checks platform support on mount and hides on unsupported platforms
|
||||
- [ ] DailyNotificationSection syncs with plugin state on initialization (checks for pre-existing schedules)
|
||||
- [ ] Component tested on Web/Electron to verify hiding works
|
||||
- [ ] No console errors when components are hidden
|
||||
- [ ] Time changes properly update notification schedule
|
||||
|
||||
### Code Quality Standards
|
||||
- **Logging**: Use `logger` from `@/utils/logger`, not `console.*`
|
||||
@@ -938,8 +1056,11 @@ await platformService.scheduleDailyNotification({
|
||||
- [ ] Plugin integrated using PlatformService architecture
|
||||
- [ ] Feature works on Capacitor (Android/iOS)
|
||||
- [ ] Feature hidden/graceful on Web/Electron
|
||||
- [ ] AccountViewView integration complete and functional
|
||||
- [ ] **AccountViewView notification section hides itself on unsupported platforms**
|
||||
- [ ] DailyNotificationSection component created and functional
|
||||
- [ ] **DailyNotificationSection hides itself on unsupported platforms**
|
||||
- [ ] Component syncs with plugin state on mount (checks for pre-existing schedules)
|
||||
- [ ] Time changes update notification schedule immediately
|
||||
- [ ] AccountViewView integration minimal (just imports component)
|
||||
- [ ] Settings persist across app restarts
|
||||
- [ ] Logging standardized (no console.*)
|
||||
- [ ] Error handling robust
|
||||
|
||||
Reference in New Issue
Block a user