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,
|
body: String,
|
||||||
nextRunTime: TimeInterval
|
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] = [
|
let schedule: [String: Any] = [
|
||||||
"id": id,
|
"id": id,
|
||||||
"kind": "notify",
|
"kind": "notify",
|
||||||
@@ -324,13 +329,123 @@ public class DailyNotificationPlugin: CAPPlugin {
|
|||||||
"createdAt": Date().timeIntervalSince1970 * 1000
|
"createdAt": Date().timeIntervalSince1970 * 1000
|
||||||
]
|
]
|
||||||
|
|
||||||
var schedules = UserDefaults.standard.array(forKey: "DailyNotificationSchedules") as? [[String: Any]] ?? []
|
|
||||||
schedules.append(schedule)
|
schedules.append(schedule)
|
||||||
UserDefaults.standard.set(schedules, forKey: "DailyNotificationSchedules")
|
UserDefaults.standard.set(schedules, forKey: "DailyNotificationSchedules")
|
||||||
|
|
||||||
print("DNP-PLUGIN: Schedule stored: \(id)")
|
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
|
// MARK: - Private Implementation Methods
|
||||||
|
|
||||||
private func setupBackgroundTasks() {
|
private func setupBackgroundTasks() {
|
||||||
|
|||||||
Reference in New Issue
Block a user