docs: add comprehensive notification system documentation
- Add GLOSSARY.md with core terminology and cross-references - Add implementation-roadmap.md with 3-phase development plan - Add notification-system.md with Native-First architecture spec - Update ios/Plugin/README.md to reflect actual vs planned implementation status This establishes the foundation for implementing shared SQLite storage, TTL-at-fire enforcement, rolling window safety, and platform completion as outlined in the phased roadmap. Files: 4 changed, 807 insertions(+), 13 deletions(-)
This commit is contained in:
96
.cursor/rules/docs/documentation_references_model_agents.mdc
Normal file
96
.cursor/rules/docs/documentation_references_model_agents.mdc
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
title: Documentation, References, and Model Agent Use
|
||||
version: 1.1
|
||||
alwaysApply: true
|
||||
scope: code, project-plans
|
||||
---
|
||||
|
||||
# Directive on Documentation, References, and Model Agent Use in Code and Project Plans
|
||||
|
||||
To ensure clarity, efficiency, and high-value documentation within code and project plans—and to leverage **model agents** (AI- or automation-based assistants) effectively—contributors must follow these rules:
|
||||
|
||||
---
|
||||
|
||||
## 1. Documentation and References Must Add Clear Value
|
||||
|
||||
- Only include documentation, comments, or reference links when they provide _new, meaningful information_ that assists understanding or decision-making.
|
||||
- Avoid duplicating content already obvious in the codebase, version history, or linked project documents.
|
||||
|
||||
---
|
||||
|
||||
## 2. Eliminate Redundant or Noisy References
|
||||
|
||||
- Remove references that serve no purpose beyond filling space.
|
||||
- Model agents may automatically flag and suggest removal of trivial references (e.g., links to unchanged boilerplate or self-evident context).
|
||||
|
||||
---
|
||||
|
||||
## 3. Explicit Role of Model Agents
|
||||
|
||||
Model agents are **active participants** in documentation quality control. Their tasks include:
|
||||
|
||||
- **Relevance Evaluation**: Automatically analyze references for their substantive contribution before inclusion.
|
||||
- **Redundancy Detection**: Flag duplicate or trivial references across commits, files, or tasks.
|
||||
- **Context Linking**: Suggest appropriate higher-level docs (designs, ADRs, meeting notes) when a code change touches multi-stage or cross-team items.
|
||||
- **Placement Optimization**: Recommend centralization of references (e.g., in plan overviews, ADRs, or merge commit messages) rather than scattered low-value inline references.
|
||||
- **Consistency Monitoring**: Ensure references align with team standards (e.g., ADR template, architecture repo, or external policy documents).
|
||||
|
||||
Contributors must treat agent recommendations as **first-pass reviews** but remain accountable for final human judgment.
|
||||
|
||||
---
|
||||
|
||||
## 4. Contextual References for Complex Items
|
||||
|
||||
- Use **centralized references** for multi-stage features (e.g., architectural docs, research threads).
|
||||
- Keep inline code comments light; push broader context into centralized documents.
|
||||
- Model agents may auto-summarize complex chains of discussion and attach them as a single reference point.
|
||||
|
||||
---
|
||||
|
||||
## 5. Centralization of Broader Context
|
||||
|
||||
- Store overarching context (design docs, proposals, workflows) in accessible, well-indexed places.
|
||||
- Model agents should assist by **generating reference maps** that track where docs are cited across the codebase.
|
||||
|
||||
---
|
||||
|
||||
## 6. Focused Documentation
|
||||
|
||||
- Documentation should explain **why** and **how** decisions are made, not just what was changed.
|
||||
- Model agents can auto-generate first-pass explanations from commit metadata, diffs, and linked issues—but humans must refine them for accuracy and intent.
|
||||
|
||||
---
|
||||
|
||||
## 7. Review and Accountability
|
||||
|
||||
- Reviewers and team leads must reject submissions containing unnecessary or low-quality documentation.
|
||||
- Model agent outputs are aids, not replacements—contributors remain responsible for **final clarity and relevance**.
|
||||
|
||||
---
|
||||
|
||||
## 8. Continuous Improvement and Agent Feedback Loops
|
||||
|
||||
- Encourage iterative development of model agents so their evaluations become more precise over time.
|
||||
- Contributions should include **feedback on agent suggestions** (e.g., accepted, rejected, or corrected) to train better future outputs.
|
||||
- Agents should log patterns of “rejected” suggestions for refinement.
|
||||
|
||||
---
|
||||
|
||||
## 9. Workflow Overview (Mermaid Diagram)
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Contributor] -->|Writes Code & Draft Docs| B[Model Agent]
|
||||
B -->|Evaluates References| C{Relevant?}
|
||||
C -->|Yes| D[Suggest Placement & Context Links]
|
||||
C -->|No| E[Flag Redundancy / Noise]
|
||||
D --> F[Contributor Refines Docs]
|
||||
E --> F
|
||||
F --> G[Reviewer]
|
||||
G -->|Approves / Requests Revisions| H[Final Documentation]
|
||||
G -->|Feedback on Agent Suggestions| B
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
✅ **Outcome:** By integrating disciplined contributor standards with **model agent augmentation**, the team achieves documentation that is consistently _relevant, concise, centralized, and decision-focused_. AI ensures coverage and noise reduction, while humans ensure precision and judgment.
|
||||
31
doc/GLOSSARY.md
Normal file
31
doc/GLOSSARY.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Glossary
|
||||
|
||||
**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to accurately reflect current implementation status vs. planned features.
|
||||
|
||||
**T (slot time)** — The local wall-clock time a notification should fire (e.g., 08:00). *See Notification System → Scheduling & T–lead.*
|
||||
|
||||
**T–lead** — The moment **`prefetchLeadMinutes`** before **T** when the system *attempts* a **single** background prefetch. T–lead **controls prefetch attempts, not arming**; locals are pre-armed earlier to guarantee closed-app delivery. *See Notification System → Scheduling & T–lead and Roadmap Phase 2.1.*
|
||||
|
||||
**Lead window** — The interval from **T–lead** up to **T** during which we **try once** to refresh content. It does **not** control arming; we pre-arm earlier. *See Notification System → Scheduling & T–lead.*
|
||||
|
||||
**Rolling window** — Always keep **today's remaining** (and tomorrow if iOS pending caps allow) locals **armed** so the OS can deliver while the app is closed. *See Notification System → Scheduling & T–lead and Roadmap Phase 1.3.*
|
||||
|
||||
**TTL (time-to-live)** — Maximum allowed payload age **at fire time**. If `T − fetchedAt > ttlSeconds`, we **skip** arming for that T. *See Notification System → Policies and Roadmap Phase 1.2.*
|
||||
|
||||
**Shared DB (planned)** — The app and plugin will open the **same SQLite file**; the app owns schema/migrations, the plugin performs short writes with WAL. *Currently using SharedPreferences/UserDefaults.* *See Notification System → Storage and Roadmap Phase 1.1.*
|
||||
|
||||
**WAL (Write-Ahead Logging)** — SQLite journaling mode that permits concurrent reads during writes; recommended for foreground-read + background-write. *See Notification System → Storage and Roadmap Phase 1.1.*
|
||||
|
||||
**`PRAGMA user_version`** — An integer the app increments on each migration; the plugin **checks** (does not migrate) to ensure compatibility. *See Notification System → Storage and Roadmap Phase 1.1.*
|
||||
|
||||
**Exact alarm (Android)** — Minute-precise alarm via `AlarmManager.setExactAndAllowWhileIdle`, subject to policy and permission. *See Notification System → Policies and Roadmap Phase 2.2.*
|
||||
|
||||
**Windowed alarm (Android)** — Batched/inexact alarm via `setWindow(start,len)`; we target **±10 minutes** when exact alarms are unavailable. *See Notification System → Policies and Roadmap Phase 2.2.*
|
||||
|
||||
**Delivery-time mutation (iOS)** — Not available for **local** notifications. Notification Service Extensions mutate **remote** pushes only; locals must be rendered before scheduling. *See Notification System → Policies.*
|
||||
|
||||
**Start-on-Login** — Electron feature that automatically launches the application when the user logs into their system, enabling background notification scheduling and delivery after system reboot. *See Roadmap Phase 2.3.*
|
||||
|
||||
**Tiered Storage (current)** — Current implementation uses SharedPreferences (Android) / UserDefaults (iOS) for quick access, in-memory cache for structured data, and file system for large assets. *See Notification System → Storage and Roadmap Phase 1.1.*
|
||||
|
||||
**No delivery-time network:** Local notifications display **pre-rendered content only**; never fetch at delivery. *See Notification System → Policies.*
|
||||
486
doc/implementation-roadmap.md
Normal file
486
doc/implementation-roadmap.md
Normal file
@@ -0,0 +1,486 @@
|
||||
# Daily Notification Plugin - Implementation Roadmap
|
||||
|
||||
**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to clarify current implementation status and distinguish between existing infrastructure and planned T–lead logic.
|
||||
|
||||
**Status:** Ready for implementation
|
||||
**Date:** 2025-01-27
|
||||
**Author:** Matthew Raymer
|
||||
**Assessment Date:** 2025-01-27
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This document outlines the implementation roadmap to bring the current Daily Notification Plugin (65% complete) to full compliance with the Native-First Notification System specification. The implementation is organized into three phases, with Phase 1 containing critical infrastructure components required for core functionality.
|
||||
|
||||
### Current State Assessment
|
||||
- **Overall Completion:** 65% of specification requirements
|
||||
- **Critical Gaps:** SQLite database sharing, TTL-at-fire enforcement, rolling window safety
|
||||
- **Current Storage:** SharedPreferences (Android) / UserDefaults (iOS) + in-memory cache
|
||||
- **Background Infrastructure:** Basic WorkManager (Android) exists, but lacks T–lead logic
|
||||
- **Critical Path:** Data persistence → Freshness enforcement → Platform completion
|
||||
|
||||
---
|
||||
|
||||
## Current Implementation Status Clarification
|
||||
|
||||
### Background Fetch Infrastructure
|
||||
**Current State:** Basic infrastructure exists but lacks T–lead logic
|
||||
- **Android:** `DailyNotificationFetchWorker.java` (WorkManager) exists
|
||||
- **Android:** `DailyNotificationFetcher.java` with scheduling logic exists
|
||||
- **Missing:** T–lead calculation, TTL enforcement, ETag support
|
||||
- **Status:** Infrastructure ready, T–lead logic needs implementation
|
||||
|
||||
### iOS Implementation Status
|
||||
**Current State:** Basic plugin structure with power management
|
||||
- **Implemented:** Plugin skeleton, power management, UserDefaults storage
|
||||
- **Missing:** BGTaskScheduler, background tasks, T–lead prefetch
|
||||
- **Status:** Foundation exists, background execution needs implementation
|
||||
|
||||
---
|
||||
|
||||
**Gate:** No further freshness or scheduling work merges to main until **shared SQLite** (see Glossary → Shared DB) is in place and reading/writing under **WAL** (see Glossary → WAL), with UI hot-read verified.
|
||||
|
||||
**Dependencies:** None
|
||||
|
||||
### 1.1 SQLite Database Sharing Implementation
|
||||
|
||||
**Priority:** CRITICAL
|
||||
|
||||
#### Requirements
|
||||
- Migrate from SharedPreferences/UserDefaults to shared SQLite database (see Glossary → Shared DB)
|
||||
- WAL mode configuration for concurrent access (see Glossary → WAL)
|
||||
- Schema version checking and compatibility validation (see Glossary → PRAGMA user_version)
|
||||
- Required tables: `notif_contents`, `notif_deliveries`, `notif_config`
|
||||
- **Migration Strategy:** Gradual migration from current tiered storage (see Glossary → Tiered Storage)
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **Migration from Current Storage**
|
||||
- Create migration utilities from SharedPreferences to SQLite
|
||||
- Implement data migration from UserDefaults to SQLite (iOS)
|
||||
- Add backward compatibility during transition
|
||||
- Preserve existing notification data during migration
|
||||
|
||||
- [ ] **SQLite Setup (Android)**
|
||||
- Create `DailyNotificationDatabase.java` with WAL mode (see Glossary → WAL)
|
||||
- Implement schema version checking (`PRAGMA user_version`) (see Glossary → PRAGMA user_version)
|
||||
- Add database connection management with proper error handling
|
||||
|
||||
- [ ] **Database Configuration**
|
||||
- Add `dbPath: string` to `ConfigureOptions` interface
|
||||
- Implement database path resolution (absolute vs platform alias)
|
||||
- Add `storage: 'shared'` configuration option
|
||||
- Extend existing `NotificationOptions` with database settings
|
||||
|
||||
- [ ] **Database Schema**
|
||||
```sql
|
||||
-- notif_contents: keep history, newest-first reads
|
||||
CREATE TABLE IF NOT EXISTS notif_contents(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
slot_id TEXT NOT NULL,
|
||||
payload_json TEXT NOT NULL,
|
||||
fetched_at INTEGER NOT NULL, -- epoch ms
|
||||
etag TEXT,
|
||||
UNIQUE(slot_id, fetched_at)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS notif_idx_contents_slot_time
|
||||
ON notif_contents(slot_id, fetched_at DESC);
|
||||
|
||||
-- notif_deliveries: track many deliveries per slot/time
|
||||
CREATE TABLE IF NOT EXISTS notif_deliveries(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
slot_id TEXT NOT NULL,
|
||||
fire_at INTEGER NOT NULL, -- intended fire time (epoch ms)
|
||||
delivered_at INTEGER, -- when actually shown (epoch ms)
|
||||
status TEXT NOT NULL DEFAULT 'scheduled', -- scheduled|shown|error|canceled
|
||||
error_code TEXT, error_message TEXT
|
||||
);
|
||||
|
||||
-- notif_config: generic configuration KV
|
||||
CREATE TABLE IF NOT EXISTS notif_config(
|
||||
k TEXT PRIMARY KEY,
|
||||
v TEXT NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] App and plugin can open the same SQLite file
|
||||
- [ ] WAL mode enables concurrent reads during writes
|
||||
- [ ] Schema version checking prevents compatibility issues
|
||||
- [ ] All required tables exist and are accessible
|
||||
- [ ] Shared DB visibility: UI reads updated rows immediately
|
||||
- [ ] WAL overlap shows no UI blocking during background writes
|
||||
- [ ] UI can read a row written by a background job **within the same second** (WAL hot-read)
|
||||
- [ ] Plugin refuses to write if `PRAGMA user_version` < expected
|
||||
|
||||
### 1.2 TTL-at-Fire Enforcement
|
||||
|
||||
**Priority:** CRITICAL
|
||||
|
||||
#### Requirements
|
||||
- Skip arming notifications if `(T - fetchedAt) > ttlSeconds` (see Glossary → TTL)
|
||||
- Validate freshness before scheduling
|
||||
- Log TTL violations for debugging
|
||||
- **Current State:** Not implemented - needs to be added to existing scheduling logic
|
||||
- **Shared DB (single file):** App owns migrations (`PRAGMA user_version`) (see Glossary → PRAGMA user_version); plugin opens the **same path**; enable `journal_mode=WAL` (see Glossary → WAL), `synchronous=NORMAL`, `busy_timeout=5000`, `foreign_keys=ON`; background writes are **short & serialized**.
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **TTL Validation Logic**
|
||||
- Insert TTL check into the scheduler path **before** any arm/re-arm
|
||||
- Add log code `TTL_VIOLATION`
|
||||
- Implement freshness validation before arming
|
||||
- Before arming, if `(T − fetchedAt) > ttlSeconds`, **skip arming** and log `TTL_VIOLATION`
|
||||
- Add TTL configuration to `NotificationOptions`
|
||||
|
||||
- [ ] **Freshness Checking**
|
||||
- Create `isContentFresh()` method
|
||||
- Implement TTL calculation logic
|
||||
- Add logging for TTL violations
|
||||
|
||||
- [ ] **Configuration Integration**
|
||||
- Add `ttlSeconds` to `NotificationOptions` interface
|
||||
- Implement default TTL values (3600 seconds = 1 hour)
|
||||
- Add TTL validation in option validation
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] Notifications are skipped if content is stale
|
||||
- [ ] TTL violations are logged with timestamps
|
||||
- [ ] Default TTL values are applied when not specified
|
||||
- [ ] Freshness checking works across all platforms
|
||||
- [ ] No armed notification violates **TTL-at-fire**
|
||||
- [ ] No armed row violates TTL at T across platforms
|
||||
|
||||
### 1.3 Rolling Window Safety
|
||||
|
||||
**Priority:** CRITICAL
|
||||
|
||||
#### Requirements
|
||||
- Keep today's remaining notifications armed
|
||||
- Keep tomorrow's notifications armed (within iOS caps) (see Glossary → Rolling window)
|
||||
- Ensure closed-app delivery reliability
|
||||
- **Current State:** Basic scheduling exists, but no rolling window logic
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **Rolling Window Logic** (see Glossary → Rolling window)
|
||||
- Implement `armRollingWindow()` method
|
||||
- Calculate today's remaining slots
|
||||
- Calculate tomorrow's slots within iOS limits
|
||||
- Account for iOS pending-notification limits; arm tomorrow only if within cap
|
||||
|
||||
- [ ] **iOS Capacity Management**
|
||||
- Implement iOS pending notification limit checking
|
||||
- Add capacity-aware scheduling logic
|
||||
- Handle capacity overflow gracefully
|
||||
|
||||
- [ ] **Window Maintenance**
|
||||
- Create `maintainRollingWindow()` method
|
||||
- Implement automatic re-arming logic
|
||||
- Add window state persistence
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] Today's remaining notifications stay armed
|
||||
- [ ] Tomorrow's notifications are armed within iOS caps
|
||||
- [ ] Closed-app delivery works reliably
|
||||
- [ ] Window maintenance runs automatically
|
||||
- [ ] Today always armed; tomorrow armed when within iOS cap
|
||||
|
||||
### 1.4 Configuration API Enhancement
|
||||
|
||||
**Priority:** HIGH
|
||||
|
||||
#### Requirements
|
||||
- Add `dbPath` configuration option
|
||||
- Implement database path resolution
|
||||
- Add storage mode configuration
|
||||
- **Current State:** No database path configuration exists
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **Interface Updates**
|
||||
- Extend `ConfigureOptions` with `dbPath: string`
|
||||
- Add `storage: 'shared'` option
|
||||
- Update validation logic
|
||||
|
||||
- [ ] **Path Resolution**
|
||||
- Implement absolute path handling
|
||||
- Add platform-specific path resolution
|
||||
- Create path validation logic
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] `dbPath` can be configured via API
|
||||
- [ ] Path resolution works on all platforms
|
||||
- [ ] Configuration validation prevents invalid paths
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Platform Completion (High Priority)
|
||||
|
||||
**Dependencies:** Phase 1 completion - **CRITICAL:** Phase 2 cannot start until SQLite sharing + TTL enforcement are finished
|
||||
|
||||
### 2.1 iOS Background Tasks Implementation
|
||||
|
||||
**Priority:** HIGH
|
||||
|
||||
#### Requirements
|
||||
- `BGTaskScheduler` for T-lead prefetch (see Glossary → T–lead)
|
||||
- Silent push nudge support
|
||||
- Background execution budget management
|
||||
- Schedule prefetch at **T–lead = T − prefetchLeadMinutes** (see Glossary → T–lead)
|
||||
- On wake, perform **one** ETag-aware fetch with **12s** timeout; **never** fetch at delivery
|
||||
- Optionally (re)arm if still within **TTL-at-fire** (see Glossary → TTL)
|
||||
- Single attempt at **T–lead**; **12s** timeout; no delivery-time fetch; (re)arm only if within **TTL-at-fire**. **(Planned)**
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **BGTaskScheduler Integration**
|
||||
- Create `DailyNotificationBackgroundTask.swift`
|
||||
- Implement background task registration
|
||||
- Add task expiration handling
|
||||
|
||||
- [ ] **Silent Push Support**
|
||||
- Add silent push notification handling
|
||||
- Implement push-to-background task bridge
|
||||
- Add push token management
|
||||
|
||||
- [ ] **Budget Management**
|
||||
- Implement execution budget tracking
|
||||
- Add budget-aware scheduling
|
||||
- Handle budget exhaustion gracefully
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] Background tasks run at T-lead (see Glossary → T–lead)
|
||||
- [ ] Silent push can trigger background execution
|
||||
- [ ] Budget management prevents system penalties
|
||||
- [ ] Background execution works when app is closed
|
||||
- [ ] iOS BGTask best-effort at T–lead; closed-app still delivers via rolling window (see Glossary → Rolling window)
|
||||
|
||||
### 2.2 Android Fallback Completion
|
||||
|
||||
**Priority:** HIGH
|
||||
|
||||
#### Requirements
|
||||
- Complete ±10 minute windowed alarm implementation (see Glossary → Windowed alarm)
|
||||
- Finish reboot/time change recovery
|
||||
- Improve exact alarm fallback handling (see Glossary → Exact alarm)
|
||||
- Finalize ±10m windowed alarm; reboot/time-change recovery; deep-link to Exact Alarm permission. **(Planned)**
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **Windowed Alarm Implementation**
|
||||
- Complete `scheduleInexactAlarm()` method
|
||||
- Implement ±10 minute window targeting
|
||||
- Add window size configuration
|
||||
|
||||
- [ ] **Recovery Mechanisms**
|
||||
- Complete `BOOT_COMPLETED` receiver
|
||||
- Implement `TIMEZONE_CHANGED` handling
|
||||
- Add `TIME_SET` recovery logic
|
||||
|
||||
- [ ] **Fallback Logic**
|
||||
- Improve exact alarm permission checking
|
||||
- Add graceful degradation to windowed alarms
|
||||
- Implement fallback logging
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] Windowed alarms target ±10 minute windows
|
||||
- [ ] Reboot recovery re-arms next 24h
|
||||
- [ ] Time change recovery recomputes schedules
|
||||
- [ ] Fallback works seamlessly
|
||||
- [ ] Android exact permission path verified with fallback ±10m
|
||||
|
||||
### 2.3 Electron Platform Support
|
||||
|
||||
**Priority:** MEDIUM
|
||||
|
||||
#### Requirements
|
||||
- Notifications while app is running
|
||||
- Start-on-Login support
|
||||
- Best-effort background scheduling
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **Electron Integration**
|
||||
- Create `DailyNotificationElectron.ts`
|
||||
- Implement notification API
|
||||
- Add Start-on-Login support
|
||||
|
||||
- [ ] **Background Limitations**
|
||||
- Document Electron limitations
|
||||
- Implement best-effort scheduling
|
||||
- Add fallback mechanisms
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] Notifications work while app is running
|
||||
- [ ] Start-on-Login enables post-reboot delivery
|
||||
- [ ] Limitations are clearly documented
|
||||
- [ ] Best-effort scheduling is implemented
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Network Optimization (Medium Priority)
|
||||
|
||||
**Dependencies:** Phase 1 completion - **CRITICAL:** Phase 3 cannot start until SQLite sharing + TTL enforcement are finished
|
||||
|
||||
### 3.1 ETag Support Implementation
|
||||
|
||||
**Priority:** MEDIUM
|
||||
|
||||
#### Requirements
|
||||
- ETag headers in fetch requests
|
||||
- 304 response handling
|
||||
- Network efficiency optimization
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **ETag Headers**
|
||||
- Add ETag to fetch requests
|
||||
- Implement ETag storage in database
|
||||
- Add ETag validation logic
|
||||
|
||||
- [ ] **304 Response Handling**
|
||||
- Implement 304 response processing
|
||||
- Add conditional request logic
|
||||
- Handle ETag mismatches
|
||||
|
||||
- [ ] **Network Optimization**
|
||||
- Add request caching
|
||||
- Implement conditional fetching
|
||||
- Add network efficiency metrics
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] ETag headers are sent with requests
|
||||
- [ ] 304 responses are handled correctly
|
||||
- [ ] Network efficiency is improved
|
||||
- [ ] Conditional requests work reliably
|
||||
|
||||
### 3.2 Advanced Error Handling
|
||||
|
||||
**Priority:** MEDIUM
|
||||
|
||||
#### Requirements
|
||||
- Comprehensive error categorization
|
||||
- Retry logic with exponential backoff
|
||||
- Error reporting and telemetry
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **Error Categories**
|
||||
- Define error types and codes
|
||||
- Implement error classification
|
||||
- Add error severity levels
|
||||
|
||||
- [ ] **Retry Logic**
|
||||
- Implement exponential backoff
|
||||
- Add retry limit configuration
|
||||
- Create retry state management
|
||||
|
||||
- [ ] **Telemetry**
|
||||
- Add error reporting
|
||||
- Implement success/failure metrics
|
||||
- Create debugging information
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] Errors are properly categorized
|
||||
- [ ] Retry logic works with backoff
|
||||
- [ ] Telemetry provides useful insights
|
||||
- [ ] Debugging information is comprehensive
|
||||
|
||||
### 3.3 Performance Optimization
|
||||
|
||||
**Priority:** LOW
|
||||
|
||||
#### Requirements
|
||||
- Database query optimization
|
||||
- Memory usage optimization
|
||||
- Battery usage optimization
|
||||
|
||||
#### Implementation Tasks
|
||||
- [ ] **Database Optimization**
|
||||
- Add database indexes
|
||||
- Optimize query performance
|
||||
- Implement connection pooling
|
||||
|
||||
- [ ] **Memory Optimization**
|
||||
- Reduce memory footprint
|
||||
- Implement object pooling
|
||||
- Add memory usage monitoring
|
||||
|
||||
- [ ] **Battery Optimization**
|
||||
- Minimize background CPU usage
|
||||
- Optimize network requests
|
||||
- Add battery usage tracking
|
||||
|
||||
#### Acceptance Criteria
|
||||
- [ ] Database queries are optimized
|
||||
- [ ] Memory usage is minimized
|
||||
- [ ] Battery usage is optimized
|
||||
- [ ] Performance metrics are tracked
|
||||
|
||||
---
|
||||
|
||||
## Implementation Guidelines
|
||||
|
||||
### Development Standards
|
||||
- **Code Quality:** Follow existing code style and documentation standards
|
||||
- **Testing:** Write unit tests for all new functionality
|
||||
- **Documentation:** Update documentation for all API changes
|
||||
- **Logging:** Add comprehensive logging with proper tagging
|
||||
- **Security:** Follow security best practices for database access
|
||||
|
||||
### Testing Requirements
|
||||
- **Unit Tests:** All new methods must have unit tests
|
||||
- **Integration Tests:** Test database sharing functionality
|
||||
- **Platform Tests:** Test on Android, iOS, and Electron
|
||||
- **Edge Cases:** Test TTL violations, network failures, and recovery scenarios
|
||||
|
||||
### Documentation Updates
|
||||
- **API Documentation:** Update TypeScript definitions
|
||||
- **Implementation Guide:** Update implementation documentation
|
||||
- **Troubleshooting:** Add troubleshooting guides for common issues
|
||||
- **Examples:** Create usage examples for new features
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### Phase 1 Success Criteria
|
||||
- [ ] SQLite database sharing works reliably
|
||||
- [ ] TTL-at-fire enforcement prevents stale notifications
|
||||
- [ ] Rolling window ensures closed-app delivery
|
||||
- [ ] Configuration API supports all required options
|
||||
|
||||
### Phase 2 Success Criteria
|
||||
- [ ] iOS background tasks run at T-lead
|
||||
- [ ] Android fallback works seamlessly
|
||||
- [ ] Electron notifications work while running
|
||||
- [ ] All platforms support the unified API
|
||||
|
||||
### Phase 3 Success Criteria
|
||||
- [ ] ETag support improves network efficiency
|
||||
- [ ] Error handling is comprehensive and robust
|
||||
- [ ] Performance is optimized across all platforms
|
||||
- [ ] System meets all specification requirements
|
||||
|
||||
---
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
### Technical Risks
|
||||
- **Database Compatibility:** Test schema version checking thoroughly
|
||||
- **Platform Differences:** Implement platform-specific fallbacks
|
||||
- **Background Execution:** Handle iOS background execution limitations
|
||||
- **Permission Changes:** Monitor Android permission policy changes
|
||||
|
||||
### Implementation Risks
|
||||
- **Scope Creep:** Stick to specification requirements
|
||||
- **Testing Coverage:** Ensure comprehensive testing
|
||||
- **Documentation:** Keep documentation up-to-date
|
||||
- **Performance:** Monitor performance impact
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
This roadmap provides a structured approach to completing the Daily Notification Plugin implementation. Phase 1 addresses the critical infrastructure gaps, Phase 2 completes platform-specific functionality, and Phase 3 optimizes the system for production use.
|
||||
|
||||
The implementation should follow the existing code patterns and maintain the high quality standards established in the current codebase. Regular testing and documentation updates are essential for success.
|
||||
|
||||
**Next Steps:**
|
||||
1. Review and approve this roadmap
|
||||
2. Begin Phase 1 implementation
|
||||
3. Set up testing infrastructure
|
||||
4. Create implementation tracking system
|
||||
247
doc/notification-system.md
Normal file
247
doc/notification-system.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# TimeSafari — Native-First Notification System
|
||||
|
||||
**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to clarify current background fetch infrastructure status and iOS implementation completeness.
|
||||
|
||||
**Status:** Ready for implementation
|
||||
**Date:** 2025-09-07
|
||||
**Author:** Matthew Raymer
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Ship a **single, Native-First** notification system: OS-scheduled **background prefetch at T–lead** + **pre-armed** local notifications. Web-push is retired.
|
||||
|
||||
### What we deliver
|
||||
|
||||
- **Closed-app delivery:** Pre-armed locals fire even if the app is closed.
|
||||
- **Freshness:** One prefetch attempt per slot at **T–lead**; ETag/TTL controls; skip when stale.
|
||||
- **Android precision:** Exact alarms with permission; windowed fallback (±10m) otherwise.
|
||||
- **Resilience:** Re-arm after reboot/time-change (Android receivers; iOS on next wake/silent push).
|
||||
- **Cross-platform:** Same TS API (iOS/Android/Electron). Electron is best-effort while running.
|
||||
|
||||
### Success signals
|
||||
|
||||
- High delivery reliability, minute-precision on Android with permission.
|
||||
- Prefetch budget hit rate at **T–lead**; zero stale deliveries beyond TTL.
|
||||
|
||||
---
|
||||
|
||||
## Strategic Plan
|
||||
|
||||
### Goal
|
||||
|
||||
Deliver 1..M daily notifications with **OS background prefetch at T–lead** *(see Glossary)* and **rolling-window safety** *(see Glossary)* so messages display with fresh content even when the app is closed.
|
||||
|
||||
### Tenets
|
||||
|
||||
- **Reliability first:** OS delivers once scheduled; no JS at delivery time.
|
||||
- **Freshness with guardrails:** Prefetch at **T–lead** *(see Glossary)*; enforce **TTL-at-fire** *(see Glossary)*; ETag-aware.
|
||||
- **Single system:** One TS API; native adapters swap under the hood.
|
||||
- **Platform honesty:** Android exactness via permission; iOS best-effort budget.
|
||||
- **No delivery-time network:** Local notifications display **pre-rendered content only**; never fetch at delivery.
|
||||
|
||||
### Architecture (high level)
|
||||
|
||||
App (Vue/TS) → Orchestrator (policy) → Native Adapters:
|
||||
|
||||
- **SchedulerNative** — AlarmManager (Android) / UNUserNotificationCenter (iOS)
|
||||
- **BackgroundPrefetchNative** — WorkManager (Android) / BGTaskScheduler (+ silent push) (iOS)
|
||||
- **DataStore** — SQLite
|
||||
|
||||
**Storage:** **Current:** SharedPreferences (Android) / UserDefaults (iOS) + in-memory cache (see Glossary → Tiered Storage). **Planned:** one **shared SQLite** file (see Glossary → Shared DB); the app owns schema/migrations; the plugin opens the same path with **WAL** (see Glossary → WAL); background writes are **short & serialized**. *(Keep the "(Planned)" label until Phase 1 ships.)*
|
||||
|
||||
### SQLite Ownership & Concurrency *(Planned)*
|
||||
|
||||
* **One DB file:** The plugin will open the **same path** the app uses (no second DB).
|
||||
* **Migrations owned by app:** The app executes schema migrations and bumps `PRAGMA user_version` (see Glossary → PRAGMA user_version). The plugin **never** migrates; it **asserts** the expected version.
|
||||
* **WAL mode:** Open DB with `journal_mode=WAL`, `synchronous=NORMAL`, `busy_timeout=5000`, `foreign_keys=ON`. WAL (see Glossary → WAL) allows foreground reads while a background job commits quickly.
|
||||
* **Single-writer discipline:** Background jobs write in **short transactions** (UPSERT per slot), then return.
|
||||
* **Encryption (optional):** If using SQLCipher, the **same key** is used by both app and plugin. Do not mix encrypted and unencrypted openings.
|
||||
|
||||
*Note: Currently using SharedPreferences (Android) / UserDefaults (iOS) with in-memory cache. See Implementation Roadmap → Phase 1.1 for migration steps.*
|
||||
|
||||
### Scheduling & T–lead *(Planned)*
|
||||
|
||||
- Arm **rolling window** (see Glossary → Rolling window). **(Planned)**
|
||||
- Exactly **one** online-first fetch at **T–lead** (see Glossary → T–lead) with **12s** timeout; **ETag/304** respected. **(Planned)**
|
||||
- If fresh **and** within **TTL-at-fire** (see Glossary → TTL), (re)arm; otherwise keep prior content. **(Planned)**
|
||||
- If the OS skips the wake, the pre-armed local still fires from cache. **(Planned)**
|
||||
|
||||
*Note: Current implementation has basic scheduling and WorkManager infrastructure (Android) but lacks T–lead prefetch logic, rolling window logic, and iOS background tasks. See Implementation Roadmap → Phase 1-2.*
|
||||
|
||||
### Policies *(Mixed Implementation)*
|
||||
|
||||
- **TTL-at-fire** (see Glossary → TTL): Before arming for T, if `(T − fetchedAt) > ttlSeconds` → **skip**. **(Planned)**
|
||||
- **Android exactness** (see Glossary → Exact alarm): **(Partial)** — permission flow exists; finalize ±10m window & deep-link to settings.
|
||||
- **Reboot/time change:** **(Partial)** — Android receivers partially present; iOS via next wake/silent push.
|
||||
- **No delivery-time network** (see Glossary → No delivery-time network): Local notifications display **pre-rendered content only**; never fetch at delivery. **(Implemented)**
|
||||
|
||||
---
|
||||
|
||||
## Implementation Guide
|
||||
|
||||
### 1) Interfaces (TS stable)
|
||||
|
||||
- **SchedulerNative**: `scheduleExact({slotId, whenMs, title, body, extra})`, `scheduleWindow(..., windowLenMs)`, `cancelBySlot`, `rescheduleAll`, `capabilities()`
|
||||
- **BackgroundPrefetchNative**: `schedulePrefetch(slotId, atMs)`, `cancelPrefetch(slotId)`
|
||||
- **DataStore**: SQLite adapters (notif_contents, notif_deliveries, notif_config)
|
||||
- **Public API**: `configure`, `requestPermissions`, `runFullPipelineNow`, `reschedule`, `getState`
|
||||
|
||||
### DB Path & Adapter Configuration *(Planned)*
|
||||
|
||||
* **Configure option:** `dbPath: string` (absolute path or platform alias) will be passed from JS to the plugin during `configure()`.
|
||||
* **Shared tables:**
|
||||
|
||||
* `notif_contents(slot_id, payload_json, fetched_at, etag, …)`
|
||||
* `notif_deliveries(slot_id, fire_at, delivered_at, status, error_code, …)`
|
||||
* `notif_config(k, v)`
|
||||
* **Open settings:**
|
||||
|
||||
* `journal_mode=WAL`
|
||||
* `synchronous=NORMAL`
|
||||
* `busy_timeout=5000`
|
||||
* `foreign_keys=ON`
|
||||
|
||||
*Note: Currently using SharedPreferences/UserDefaults (see Glossary → Tiered Storage). Database configuration is planned for Phase 1.*
|
||||
|
||||
See **Implementation Roadmap → Phase 1.1** for migration steps and schema.
|
||||
|
||||
**Type (TS) extension** *(Planned)*
|
||||
|
||||
```ts
|
||||
export type ConfigureOptions = {
|
||||
// …existing fields…
|
||||
dbPath: string; // shared DB file the plugin will open
|
||||
storage: 'shared'; // canonical value; plugin-owned DB is not used
|
||||
};
|
||||
```
|
||||
|
||||
*Note: Current `NotificationOptions` interface exists but lacks `dbPath` configuration. This will be added in Phase 1.*
|
||||
|
||||
**Plugin side (pseudo)**
|
||||
|
||||
```kotlin
|
||||
// Android open
|
||||
val db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READWRITE)
|
||||
db.execSQL("PRAGMA journal_mode=WAL")
|
||||
db.execSQL("PRAGMA synchronous=NORMAL")
|
||||
db.execSQL("PRAGMA foreign_keys=ON")
|
||||
db.execSQL("PRAGMA busy_timeout=5000")
|
||||
// Verify schema version
|
||||
val uv = rawQuery("PRAGMA user_version").use { it.moveToFirst(); it.getInt(0) }
|
||||
require(uv >= MIN_EXPECTED_VERSION) { "Schema version too old" }
|
||||
```
|
||||
|
||||
```swift
|
||||
// iOS open (FMDB / SQLite3)
|
||||
// Set WAL via PRAGMA after open; check user_version the same way.
|
||||
```
|
||||
|
||||
### 2) Templating & Arming
|
||||
|
||||
- Render `title/body` **before** scheduling; pass via **SchedulerNative**.
|
||||
- Route all arming through **SchedulerNative** to centralize Android exact/window semantics.
|
||||
|
||||
### 3) T–lead (single attempt)
|
||||
|
||||
**T–lead governs prefetch, not arming.** We **arm** one-shot locals as part of the rolling window so closed-app delivery is guaranteed. At **T–lead = T − prefetchLeadMinutes**, the **native background job** attempts **one** 12s ETag-aware fetch. If fresh content arrives and will not violate **TTL-at-fire**, we (re)arm the upcoming slot; if the OS skips the wake, the pre-armed local still fires with cached content.
|
||||
|
||||
- Compute T–lead = `whenMs - prefetchLeadMinutes*60_000`.
|
||||
- `BackgroundPrefetchNative.schedulePrefetch(slotId, atMs=T–lead)`.
|
||||
- On wake: **ETag** fetch (timeout **12s**), persist, optionally cancel & re-arm if within TTL.
|
||||
- Never fetch at delivery time.
|
||||
|
||||
### 4) TTL-at-fire
|
||||
|
||||
**TTL-at-fire:** Before arming for time **T**, compute `T − fetchedAt`. If that exceeds `ttlSeconds`, **do not arm** (skip). This prevents posting stale notifications when the app has been closed for a long time.
|
||||
|
||||
`if (whenMs - fetchedAt) > ttlSeconds*1000 → skip`
|
||||
|
||||
### 5) Android specifics
|
||||
|
||||
- Request `SCHEDULE_EXACT_ALARM`; deep-link if denied; fallback to `setWindow(start,len)` (±10m).
|
||||
- Receivers: `BOOT_COMPLETED`, `TIMEZONE_CHANGED`, `TIME_SET` → recompute & re-arm for next 24h and schedule T–lead prefetch.
|
||||
|
||||
### 6) iOS specifics
|
||||
|
||||
- `BGTaskScheduler` for T–lead prefetch (best-effort). Optional silent push nudge.
|
||||
- Locals: `UNCalendarNotificationTrigger` (one-shots); no NSE mutation for locals.
|
||||
|
||||
### 7) Network & Timeouts
|
||||
|
||||
- Content fetch: **12s** timeout; single attempt at T–lead; ETag/304 respected.
|
||||
- ACK/Error: **8s** timeout, fire-and-forget.
|
||||
|
||||
### 8) Electron
|
||||
|
||||
- Notifications while app is running; recommend **Start-on-Login**. No true background scheduling when fully closed.
|
||||
|
||||
### 9) Telemetry
|
||||
|
||||
- Record `scheduled|shown|error`; ACK deliveries (8s timeout); include slot/times/TZ/app version.
|
||||
|
||||
---
|
||||
|
||||
## Capability Matrix
|
||||
|
||||
| Capability | Android (Native) | iOS (Native) | Electron | Web |
|
||||
|---|---|---|---|---|
|
||||
| Multi-daily locals (closed app) | ✅ | ✅ | ✅ (app running) | — |
|
||||
| Prefetch at T–lead (app closed) | ✅ WorkManager | ⚠️ BGTask (best-effort) | ✅ (app running) | — |
|
||||
| Re-arm after reboot/time-change | ✅ Receivers | ⚠️ On next wake/silent push | ✅ Start-on-Login | — |
|
||||
| Minute-precision alarms | ✅ with exact permission | ❌ not guaranteed | ✅ timer best-effort | — |
|
||||
| Delivery-time mutation for locals | ❌ | ❌ | — | — |
|
||||
| ETag/TTL enforcement | ✅ | ✅ | ✅ | — |
|
||||
| Rolling-window safety | ✅ | ✅ | ✅ | — |
|
||||
|
||||
---
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Core
|
||||
|
||||
- **Closed-app delivery:** Armed locals fire at T with last rendered content. No delivery-time network.
|
||||
- **T–lead prefetch:** Single background attempt at **T–lead**; if skipped, delivery still occurs from cache.
|
||||
- **TTL-at-fire:** No armed local violates TTL at T.
|
||||
|
||||
### Android
|
||||
|
||||
- **Exact permission path:** With `SCHEDULE_EXACT_ALARM` → within ±1m; else **±10m** window.
|
||||
- **Reboot recovery:** After reboot, receivers re-arm next 24h and schedule T–lead prefetch.
|
||||
- **TZ/DST change:** Recompute & re-arm; future slots align to new wall-clock.
|
||||
|
||||
### iOS
|
||||
|
||||
- **BGTask budget respected:** Prefetch often runs but may be skipped; delivery still occurs via rolling window.
|
||||
- **Force-quit caveat:** No background execution after user terminate; delivery still occurs if pre-armed.
|
||||
|
||||
### Electron
|
||||
|
||||
- **Running-app rule:** Delivery only while app runs; with Start-on-Login, after reboot the orchestrator re-arms and subsequent slots deliver.
|
||||
|
||||
### Network
|
||||
|
||||
- Content fetch timeout **12s**; ACK/Error **8s**; no retries inside lead; ETag honored.
|
||||
|
||||
### Observability
|
||||
|
||||
- Log/telemetry for `scheduled|shown|error`; ACK payload includes slot, times, device TZ, app version.
|
||||
|
||||
### DB Sharing *(Planned)*
|
||||
|
||||
* **Shared DB visibility:** A background prefetch writes `notif_contents`; the foreground UI **immediately** reads the same row.
|
||||
* **WAL overlap:** With the app reading while the plugin commits, no user-visible blocking occurs.
|
||||
* **Version safety:** If `user_version` is behind, the plugin emits an error and does not write (protects against partial installs).
|
||||
|
||||
*Note: Currently using SharedPreferences/UserDefaults with in-memory cache. SQLite sharing is planned for Phase 1.*
|
||||
|
||||
---
|
||||
|
||||
## Web-Push Cleanup
|
||||
|
||||
Web-push functionality has been retired due to unreliability. All web-push related code paths and documentation sections should be removed or marked as deprecated. See `web-push-cleanup-guide.md` for detailed cleanup steps.
|
||||
|
||||
---
|
||||
|
||||
_This document consolidates the Native-First notification system strategy, implementation details, capabilities, and acceptance criteria into a single comprehensive reference._
|
||||
@@ -2,14 +2,34 @@
|
||||
|
||||
This directory contains the iOS-specific implementation of the DailyNotification plugin.
|
||||
|
||||
## Current Implementation Status
|
||||
|
||||
**✅ IMPLEMENTED:**
|
||||
- Basic plugin structure (`DailyNotificationPlugin.swift`)
|
||||
- UserDefaults for local data storage
|
||||
- Power management (`DailyNotificationPowerManager.swift`)
|
||||
- Battery optimization handling
|
||||
- iOS notification categories and actions
|
||||
|
||||
**❌ NOT IMPLEMENTED (Planned):**
|
||||
- `BGTaskScheduler` for background data fetching
|
||||
- Background task management
|
||||
- Silent push nudge support
|
||||
- T–lead prefetch logic
|
||||
|
||||
## Implementation Details
|
||||
|
||||
The iOS implementation uses:
|
||||
The iOS implementation currently uses:
|
||||
|
||||
- `UNUserNotificationCenter` for notification management ✅
|
||||
- `UserDefaults` for local data storage ✅
|
||||
- iOS notification categories and actions ✅
|
||||
- Power management and battery optimization ✅
|
||||
|
||||
**Planned additions:**
|
||||
- `BGTaskScheduler` for background data fetching
|
||||
- `UNUserNotificationCenter` for notification management
|
||||
- `UserDefaults` for local data storage
|
||||
- iOS notification categories and actions
|
||||
- Background task management
|
||||
- Silent push support
|
||||
|
||||
## Native Code Location
|
||||
|
||||
@@ -17,18 +37,28 @@ The native iOS implementation is located in the `ios/` directory at the project
|
||||
|
||||
## Key Components
|
||||
|
||||
1. `DailyNotificationIOS.swift`: Main plugin class
|
||||
2. `BackgroundTaskManager.swift`: Handles background fetch scheduling
|
||||
3. `NotificationManager.swift`: Manages notification creation and display
|
||||
4. `DataStore.swift`: Handles local data persistence
|
||||
1. `DailyNotificationPlugin.swift`: Main plugin class ✅
|
||||
2. `DailyNotificationPowerManager.swift`: Power state management ✅
|
||||
3. `DailyNotificationConfig.swift`: Configuration options ✅
|
||||
4. `DailyNotificationMaintenanceWorker.swift`: Maintenance tasks ✅
|
||||
5. `DailyNotificationLogger.swift`: Logging system ✅
|
||||
|
||||
**Missing Components (Planned):**
|
||||
- `BackgroundTaskManager.swift`: Handles background fetch scheduling
|
||||
- `NotificationManager.swift`: Manages notification creation and display
|
||||
- `DataStore.swift`: Handles local data persistence
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Uses BGTaskScheduler for reliable background execution
|
||||
- Implements proper battery optimization handling
|
||||
- Supports iOS notification categories and actions
|
||||
- Handles background refresh limitations
|
||||
- Uses UserDefaults for lightweight data storage
|
||||
- Uses UserDefaults for lightweight data storage ✅
|
||||
- Implements proper battery optimization handling ✅
|
||||
- Supports iOS notification categories and actions ✅
|
||||
- Handles background refresh limitations ✅
|
||||
|
||||
**Planned Features:**
|
||||
- BGTaskScheduler for reliable background execution
|
||||
- Silent push notification support
|
||||
- Background task budget management
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user