feat(ios): implement getNotificationStatus and cancelAllNotifications methods
Implemented status and cancellation methods matching Android functionality: getNotificationStatus(): - Gets pending notifications from UNUserNotificationCenter - Retrieves schedules from UserDefaults - Calculates next notification time from schedules - Returns status matching Android API structure - Includes isEnabled, isScheduled, lastNotificationTime, nextNotificationTime, pending count cancelAllNotifications(): - Removes all pending daily notifications from UNUserNotificationCenter - Cancels background fetch tasks by identifier - Clears notification schedules from UserDefaults - Idempotent (safe to call multiple times) - Matches Android behavior (cancels alarms, WorkManager jobs, database) Helper Methods: - getSchedulesFromUserDefaults() - Retrieves stored schedules - Improved storeScheduleInUserDefaults() - Prevents duplicates Progress: 12/52 methods implemented (23% complete)
This commit is contained in:
@@ -313,6 +313,11 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
body: String,
|
||||
nextRunTime: TimeInterval
|
||||
) {
|
||||
var schedules = UserDefaults.standard.array(forKey: "DailyNotificationSchedules") as? [[String: Any]] ?? []
|
||||
|
||||
// Remove existing schedule with same ID if present
|
||||
schedules.removeAll { ($0["id"] as? String) == id }
|
||||
|
||||
let schedule: [String: Any] = [
|
||||
"id": id,
|
||||
"kind": "notify",
|
||||
@@ -324,13 +329,123 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
"createdAt": Date().timeIntervalSince1970 * 1000
|
||||
]
|
||||
|
||||
var schedules = UserDefaults.standard.array(forKey: "DailyNotificationSchedules") as? [[String: Any]] ?? []
|
||||
schedules.append(schedule)
|
||||
UserDefaults.standard.set(schedules, forKey: "DailyNotificationSchedules")
|
||||
|
||||
print("DNP-PLUGIN: Schedule stored: \(id)")
|
||||
}
|
||||
|
||||
// MARK: - Status & Cancellation Methods
|
||||
|
||||
/**
|
||||
* Get notification status
|
||||
*
|
||||
* Returns the current status of scheduled notifications, including:
|
||||
* - Whether notifications are enabled/scheduled
|
||||
* - Last notification time
|
||||
* - Next notification time
|
||||
* - Pending notification count
|
||||
*
|
||||
* Equivalent to Android's getNotificationStatus method.
|
||||
*/
|
||||
@objc func getNotificationStatus(_ call: CAPPluginCall) {
|
||||
// Get pending notifications from UNUserNotificationCenter
|
||||
notificationCenter.getPendingNotificationRequests { requests in
|
||||
// Filter for daily notifications (those starting with "daily_")
|
||||
let dailyNotifications = requests.filter { $0.identifier.hasPrefix("daily_") }
|
||||
|
||||
// Get schedules from UserDefaults
|
||||
let schedules = self.getSchedulesFromUserDefaults()
|
||||
let notifySchedules = schedules.filter {
|
||||
($0["kind"] as? String) == "notify" &&
|
||||
($0["enabled"] as? Bool) == true
|
||||
}
|
||||
|
||||
// Calculate next notification time
|
||||
var nextNotificationTime: TimeInterval = 0
|
||||
if let nextRunTimes = notifySchedules.compactMap({ $0["nextRunTime"] as? TimeInterval }) as? [TimeInterval],
|
||||
!nextRunTimes.isEmpty {
|
||||
nextNotificationTime = nextRunTimes.min() ?? 0
|
||||
}
|
||||
|
||||
// Get last notification time from UserDefaults (stored when notification is delivered)
|
||||
// For now, we'll use 0 if not available (history tracking can be added later)
|
||||
let lastNotificationTime = UserDefaults.standard.double(forKey: "DailyNotificationLastDeliveryTime")
|
||||
|
||||
// Build result matching Android API
|
||||
let result: [String: Any] = [
|
||||
"isEnabled": !notifySchedules.isEmpty,
|
||||
"isScheduled": !notifySchedules.isEmpty,
|
||||
"lastNotificationTime": lastNotificationTime > 0 ? lastNotificationTime : 0,
|
||||
"nextNotificationTime": nextNotificationTime,
|
||||
"scheduledCount": notifySchedules.count,
|
||||
"pending": dailyNotifications.count,
|
||||
"settings": [
|
||||
"enabled": !notifySchedules.isEmpty,
|
||||
"count": notifySchedules.count
|
||||
] as [String: Any]
|
||||
]
|
||||
|
||||
DispatchQueue.main.async {
|
||||
call.resolve(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel all notifications
|
||||
*
|
||||
* Cancels all scheduled daily notifications:
|
||||
* 1. Removes all pending notifications from UNUserNotificationCenter
|
||||
* 2. Cancels all background fetch tasks
|
||||
* 3. Clears schedules from UserDefaults
|
||||
*
|
||||
* Equivalent to Android's cancelAllNotifications method.
|
||||
* The method is idempotent - safe to call multiple times.
|
||||
*/
|
||||
@objc func cancelAllNotifications(_ call: CAPPluginCall) {
|
||||
print("DNP-PLUGIN: Cancelling all notifications")
|
||||
|
||||
// 1. Get all pending notifications
|
||||
notificationCenter.getPendingNotificationRequests { requests in
|
||||
let dailyNotificationIds = requests
|
||||
.filter { $0.identifier.hasPrefix("daily_") }
|
||||
.map { $0.identifier }
|
||||
|
||||
// 2. Remove all daily notifications
|
||||
if !dailyNotificationIds.isEmpty {
|
||||
self.notificationCenter.removePendingNotificationRequests(withIdentifiers: dailyNotificationIds)
|
||||
print("DNP-PLUGIN: Removed \(dailyNotificationIds.count) pending notification(s)")
|
||||
}
|
||||
|
||||
// 3. Cancel all background tasks
|
||||
// Cancel by identifier (BGTaskScheduler requires identifier to cancel)
|
||||
// Note: cancel() doesn't throw, it's safe to call even if task doesn't exist
|
||||
self.backgroundTaskScheduler.cancel(taskRequestWithIdentifier: self.fetchTaskIdentifier)
|
||||
self.backgroundTaskScheduler.cancel(taskRequestWithIdentifier: self.notifyTaskIdentifier)
|
||||
print("DNP-PLUGIN: Cancelled background tasks")
|
||||
|
||||
// 4. Clear schedules from UserDefaults
|
||||
var schedules = UserDefaults.standard.array(forKey: "DailyNotificationSchedules") as? [[String: Any]] ?? []
|
||||
let notifySchedules = schedules.filter { ($0["kind"] as? String) == "notify" }
|
||||
schedules.removeAll { ($0["kind"] as? String) == "notify" }
|
||||
UserDefaults.standard.set(schedules, forKey: "DailyNotificationSchedules")
|
||||
print("DNP-PLUGIN: Removed \(notifySchedules.count) schedule(s) from storage")
|
||||
|
||||
DispatchQueue.main.async {
|
||||
print("DNP-PLUGIN: All notifications cancelled successfully")
|
||||
call.resolve()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get schedules from UserDefaults
|
||||
*/
|
||||
private func getSchedulesFromUserDefaults() -> [[String: Any]] {
|
||||
return UserDefaults.standard.array(forKey: "DailyNotificationSchedules") as? [[String: Any]] ?? []
|
||||
}
|
||||
|
||||
// MARK: - Private Implementation Methods
|
||||
|
||||
private func setupBackgroundTasks() {
|
||||
|
||||
Reference in New Issue
Block a user