feat(ios): implement isAlarmScheduled, getNextAlarmTime, and testAlarm methods

Implemented alarm status and testing methods matching Android functionality:

isAlarmScheduled():
- Checks if notification is scheduled for given trigger time
- Searches pending notifications for matching trigger date
- Uses 1-minute tolerance for time comparison
- Returns scheduled status and triggerAtMillis

getNextAlarmTime():
- Gets the next scheduled notification time
- Finds earliest scheduled daily notification
- Returns scheduled status and triggerAtMillis (or just scheduled: false)

testAlarm():
- Schedules test notification for testing purposes
- Defaults to 5 seconds from now (configurable)
- Creates test notification with title and body
- Returns scheduled status, secondsFromNow, and triggerAtMillis
- Useful for verifying notification delivery works

iOS Adaptations:
- Uses UNCalendarNotificationTrigger for scheduling
- Searches pending notifications to check status
- Date component matching for precise scheduling

Progress: 30/52 methods implemented (58% complete)
This commit is contained in:
Matthew Raymer
2025-11-11 02:12:35 -08:00
parent b3817a0cb1
commit bdee842ea9

View File

@@ -1131,6 +1131,153 @@ public class DailyNotificationPlugin: CAPPlugin {
}
}
// MARK: - Alarm Status Methods
/**
* Check if alarm is scheduled
*
* Checks if a notification is scheduled for the given trigger time.
*
* Equivalent to Android's isAlarmScheduled method.
*/
@objc func isAlarmScheduled(_ call: CAPPluginCall) {
guard let options = call.options else {
call.reject("Options are required")
return
}
guard let triggerAtMillis = options["triggerAtMillis"] as? Int64 else {
call.reject("triggerAtMillis is required")
return
}
let triggerAt = Date(timeIntervalSince1970: TimeInterval(triggerAtMillis) / 1000.0)
print("DNP-PLUGIN: Checking alarm status: triggerAt=\(triggerAt)")
// Check if notification exists for this time
notificationCenter.getPendingNotificationRequests { requests in
let dailyNotifications = requests.filter { $0.identifier.hasPrefix("daily_") }
// Check if any notification matches the trigger time
var isScheduled = false
for notification in dailyNotifications {
if let trigger = notification.trigger as? UNCalendarNotificationTrigger,
let nextTriggerDate = trigger.nextTriggerDate() {
// Compare dates (within 1 minute tolerance)
if abs(nextTriggerDate.timeIntervalSince(triggerAt)) < 60 {
isScheduled = true
break
}
}
}
let result: [String: Any] = [
"scheduled": isScheduled,
"triggerAtMillis": triggerAtMillis
]
print("DNP-PLUGIN: Alarm status: scheduled=\(isScheduled), triggerAt=\(triggerAtMillis)")
DispatchQueue.main.async {
call.resolve(result)
}
}
}
/**
* Get next alarm time
*
* Returns the next scheduled notification time.
*
* Equivalent to Android's getNextAlarmTime method.
*/
@objc func getNextAlarmTime(_ call: CAPPluginCall) {
print("DNP-PLUGIN: Getting next alarm time")
notificationCenter.getPendingNotificationRequests { requests in
let dailyNotifications = requests.filter { $0.identifier.hasPrefix("daily_") }
var nextAlarmTime: TimeInterval? = nil
// Find the earliest scheduled notification
for notification in dailyNotifications {
if let trigger = notification.trigger as? UNCalendarNotificationTrigger,
let nextTriggerDate = trigger.nextTriggerDate() {
let triggerTime = nextTriggerDate.timeIntervalSince1970 * 1000
if nextAlarmTime == nil || triggerTime < nextAlarmTime! {
nextAlarmTime = triggerTime
}
}
}
let result: [String: Any]
if let nextTime = nextAlarmTime {
result = [
"scheduled": true,
"triggerAtMillis": Int64(nextTime)
]
print("DNP-PLUGIN: Next alarm time: \(nextTime)")
} else {
result = [
"scheduled": false
]
print("DNP-PLUGIN: No alarm scheduled")
}
DispatchQueue.main.async {
call.resolve(result)
}
}
}
/**
* Test alarm
*
* Schedules a test notification to fire in a few seconds.
* Useful for verifying notification delivery works correctly.
*
* Equivalent to Android's testAlarm method.
*/
@objc func testAlarm(_ call: CAPPluginCall) {
let options = call.options
let secondsFromNow = (options?["secondsFromNow"] as? Int) ?? 5
print("DNP-PLUGIN: TEST: Scheduling test alarm in \(secondsFromNow) seconds")
// Create test notification
let content = UNMutableNotificationContent()
content.title = "Test Notification"
content.body = "This is a test notification scheduled \(secondsFromNow) seconds from now"
content.sound = .default
// Schedule for secondsFromNow seconds in the future
let triggerDate = Date().addingTimeInterval(TimeInterval(secondsFromNow))
let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: triggerDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let identifier = "test_alarm_\(Date().timeIntervalSince1970)"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
notificationCenter.add(request) { error in
DispatchQueue.main.async {
if let error = error {
print("DNP-PLUGIN: Failed to schedule test alarm: \(error)")
call.reject("Failed to schedule test alarm: \(error.localizedDescription)")
} else {
let triggerAtMillis = Int64(Date().addingTimeInterval(TimeInterval(secondsFromNow)).timeIntervalSince1970 * 1000)
let result: [String: Any] = [
"scheduled": true,
"secondsFromNow": secondsFromNow,
"triggerAtMillis": triggerAtMillis
]
print("DNP-PLUGIN: Test alarm scheduled successfully")
call.resolve(result)
}
}
}
}
// MARK: - Private Implementation Methods
private func setupBackgroundTasks() {