feat(ios): Enhance battery optimization and notification management

Description:
- Add battery status and power state monitoring
- Implement adaptive scheduling based on battery levels
- Add maintenance worker for background tasks
- Enhance logging with structured DailyNotificationLogger
- Add configuration management with DailyNotificationConfig
- Define constants in DailyNotificationConstants
- Improve error handling and recovery mechanisms

Testing:
- Add comprehensive test coverage for battery optimization
- Add test coverage for power state management
- Add test coverage for maintenance tasks
- Add test coverage for configuration management
- Add test coverage for constants validation

Documentation:
- Add comprehensive file-level documentation
- Add method-level documentation
- Add test documentation
- Add configuration documentation

This commit improves the iOS implementation's reliability and battery
efficiency by adding robust error handling, logging, and configuration
management to make the plugin more maintainable and debuggable.
This commit is contained in:
Matthew Raymer
2025-03-28 03:50:54 -07:00
parent 450352718f
commit a54ba34cb9
9 changed files with 511 additions and 24 deletions

View File

@@ -0,0 +1,122 @@
/**
* DailyNotificationMaintenanceWorker.swift
* Daily Notification Plugin for Capacitor
*
* Handles background maintenance tasks for notifications
*/
import Foundation
import UserNotifications
/// Handles background maintenance tasks for the notification plugin
public class DailyNotificationMaintenanceWorker {
/// Shared instance for singleton access
public static let shared = DailyNotificationMaintenanceWorker()
private let notificationCenter = UNUserNotificationCenter.current()
private let powerManager = DailyNotificationPowerManager.shared
private init() {}
/// Performs maintenance tasks
public func performMaintenance() {
DailyNotificationLogger.shared.log(.info, "Starting maintenance tasks")
// Update battery status
_ = powerManager.getBatteryStatus()
// Clean up old notifications
cleanupOldNotifications()
// Reschedule missed notifications
rescheduleMissedNotifications()
DailyNotificationLogger.shared.log(.info, "Maintenance tasks completed")
}
private func cleanupOldNotifications() {
let cutoffDate = Date().addingTimeInterval(-Double(DailyNotificationConfig.shared.retentionDays * 24 * 60 * 60))
notificationCenter.getDeliveredNotifications { notifications in
let oldNotifications = notifications.filter { $0.date < cutoffDate }
if !oldNotifications.isEmpty {
let identifiers = oldNotifications.map { $0.request.identifier }
self.notificationCenter.removeDeliveredNotifications(withIdentifiers: identifiers)
DailyNotificationLogger.shared.log(
.info,
"Cleaned up \(identifiers.count) old notifications"
)
}
}
}
private func rescheduleMissedNotifications() {
notificationCenter.getPendingNotificationRequests { requests in
let now = Date()
for request in requests {
guard let trigger = request.trigger as? UNCalendarNotificationTrigger,
let nextTriggerDate = trigger.nextTriggerDate() else {
continue
}
// If the next trigger date is more than 24 hours in the past
if nextTriggerDate.timeIntervalSince(now) < -24 * 60 * 60 {
// Reschedule the notification
let content = request.content.mutableCopy() as! UNMutableNotificationContent
let newRequest = UNNotificationRequest(
identifier: request.identifier,
content: content,
trigger: trigger
)
self.notificationCenter.add(newRequest) { error in
if let error = error {
DailyNotificationLogger.shared.log(
.error,
"Failed to reschedule notification: \(error.localizedDescription)"
)
} else {
DailyNotificationLogger.shared.log(
.info,
"Successfully rescheduled notification: \(request.identifier)"
)
}
}
}
}
}
}
/// Schedules the next maintenance window
public func scheduleNextMaintenance() {
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: DailyNotificationConfig.SchedulingIntervals.normal,
repeats: true
)
let content = UNMutableNotificationContent()
content.title = "Maintenance"
content.body = "Performing notification maintenance"
content.sound = nil
let request = UNNotificationRequest(
identifier: "maintenance-window",
content: content,
trigger: trigger
)
notificationCenter.add(request) { error in
if let error = error {
DailyNotificationLogger.shared.log(
.error,
"Failed to schedule maintenance window: \(error.localizedDescription)"
)
} else {
DailyNotificationLogger.shared.log(.info, "Maintenance window scheduled")
}
}
}
}