From 9db381c72b5c18bb5974137efe202458ffd028ec Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Tue, 5 May 2026 15:08:12 +0800 Subject: [PATCH] feat(ios): add batch UN notification replace-all API Expose clearAllNotifications and scheduleNotifications on DailyNotification. clearAllNotifications clears pending and delivered center notifications. scheduleNotifications replaces pending requests from epoch-ms timestamps with deterministic predictive_* IDs and DNP-BATCH logging. --- ios/Plugin/DailyNotificationPlugin.swift | 61 ++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/ios/Plugin/DailyNotificationPlugin.swift b/ios/Plugin/DailyNotificationPlugin.swift index 8911e78..5d30ff1 100644 --- a/ios/Plugin/DailyNotificationPlugin.swift +++ b/ios/Plugin/DailyNotificationPlugin.swift @@ -1107,6 +1107,63 @@ public class DailyNotificationPlugin: CAPPlugin { return predictiveReminderRequestId(hour: hour, minute: minute) } + // MARK: - Predictive batch API (replace-all UNUserNotificationCenter) + + /// Clears all pending and delivered user notifications. Parallel to the DB/scheduler stack; does not clear stored schedules elsewhere. + @objc func clearAllNotifications(_ call: CAPPluginCall) { + NSLog("DNP-BATCH: clearAllNotifications — removing all pending and delivered notifications") + print("DNP-BATCH: clearAllNotifications — removing all pending and delivered notifications") + notificationCenter.removeAllPendingNotificationRequests() + notificationCenter.removeAllDeliveredNotifications() + call.resolve() + } + + /// Replaces all pending notifications with one-shot reminders at the given epoch millis. Clears pending first. + @objc func scheduleNotifications(_ call: CAPPluginCall) { + guard let timestamps = call.getArray("timestamps", Double.self) else { + call.reject("Missing timestamps") + return + } + + NSLog("DNP-BATCH: scheduleNotifications — removeAllPending then scheduling \(timestamps.count) request(s)") + print("DNP-BATCH: scheduleNotifications — removeAllPending then scheduling \(timestamps.count) request(s)") + notificationCenter.removeAllPendingNotificationRequests() + + for ts in timestamps { + let date = Date(timeIntervalSince1970: ts / 1000) + let interval = max(date.timeIntervalSinceNow, 1) + + let trigger = UNTimeIntervalNotificationTrigger( + timeInterval: interval, + repeats: false + ) + + let content = UNMutableNotificationContent() + content.title = "Reminder" + content.body = "You have a scheduled notification" + + let id = "predictive_\(Int(ts))" + + NSLog("DNP-BATCH: scheduling ts=\(ts) interval=\(interval)s id=\(id)") + print("DNP-BATCH: scheduling ts=\(ts) interval=\(interval)s id=\(id)") + + let request = UNNotificationRequest( + identifier: id, + content: content, + trigger: trigger + ) + + notificationCenter.add(request) { error in + if let error = error { + NSLog("DNP-BATCH: add failed id=\(id) error=\(error.localizedDescription)") + print("DNP-BATCH: add failed id=\(id) error=\(error.localizedDescription)") + } + } + } + + call.resolve() + } + // MARK: - Static Daily Reminder Methods @objc func scheduleDailyReminder(_ call: CAPPluginCall) { @@ -2546,6 +2603,10 @@ public class DailyNotificationPlugin: CAPPlugin { methods.append(CAPPluginMethod(name: "getScheduledReminders", returnType: CAPPluginReturnPromise)) methods.append(CAPPluginMethod(name: "updateDailyReminder", returnType: CAPPluginReturnPromise)) + // Predictive batch API (replace-all UNUserNotificationCenter) + methods.append(CAPPluginMethod(name: "clearAllNotifications", returnType: CAPPluginReturnPromise)) + methods.append(CAPPluginMethod(name: "scheduleNotifications", returnType: CAPPluginReturnPromise)) + // Dual scheduling methods methods.append(CAPPluginMethod(name: "scheduleContentFetch", returnType: CAPPluginReturnPromise)) methods.append(CAPPluginMethod(name: "scheduleUserNotification", returnType: CAPPluginReturnPromise))