You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LeCountdown/LeCountdown/CountdownScheduler.swift

99 lines
4.1 KiB

//
// CountdownScheduler.swift
// Countdown
//
// Created by Laurent Morvillier on 15/01/2023.
//
import Foundation
import UserNotifications
class CountdownScheduler {
static let master = CountdownScheduler()
static let notificationIdSeparator: String = "||"
func scheduleIfPossible(countdown: Countdown, handler: @escaping (Result<Date?, Error>) -> Void) {
self.cancelCurrentNotifications(countdownId: countdown.stringId)
Conductor.maestro.prepareAlarm(countdown: countdown, handler: handler)
self._scheduleCountdownNotification(countdown: countdown, handler: handler)
}
fileprivate func _scheduleCountdownNotification(countdown: Countdown, handler: @escaping (Result<Date?, Error>) -> Void) {
let content = UNMutableNotificationContent()
content.title = NSLocalizedString("It's time!", comment: "")
let duration = countdown.duration
let body: String
if let name = countdown.activity?.name {
let timesup = NSLocalizedString("Time's up for %@!", comment: "")
body = String(format: timesup, name)
} else {
let timesup = NSLocalizedString("Your %@ countdown is over!", comment: "")
body = String(format: timesup, duration.minuteSecond)
}
content.body = body
self._createNotification(countdown: countdown, content: content, handler: handler)
// content.sound = UNNotificationSound.criticalSoundNamed(UNNotificationSoundName(rawValue: sound), withAudioVolume: 1.0)
content.interruptionLevel = .critical
content.relevanceScore = 1.0
// let notificationCount = 1 + countdown.repeatCount
// for i in 0..<notificationCount {
// let offset = Double(i) * 10.0 // every 30 seconds
// self._createNotification(countdown: countdown, offset: offset, content: content, handler: handler)
// }
}
fileprivate func _createNotification(countdown: Countdown, offset: TimeInterval = 0.0, content: UNMutableNotificationContent, handler: @escaping (Result<Date?, Error>) -> Void) {
let duration = countdown.duration
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: duration + offset, repeats: false)
let identifier: String = [countdown.objectID.uriRepresentation().absoluteString, "\(offset)"].joined(separator: CountdownScheduler.notificationIdSeparator)
let request = UNNotificationRequest(identifier: identifier,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
DispatchQueue.main.async {
if let error {
handler(.failure(error))
print("Scheduling error = \(error)")
} else {
// if offset == 0.0 {
// if let triggerDate = trigger.nextTriggerDate() {
// Conductor.maestro.startCountdown(triggerDate, countdown: countdown)
// handler(.success(triggerDate))
// } else {
// let backupDate = Date().addingTimeInterval(duration)
// Conductor.maestro.startCountdown(backupDate, countdown: countdown)
// }
// }
}
}
}
// DispatchQueue.main.async {
// let d = countdown.duration + offset
// let td = Date().addingTimeInterval(d)
// Conductor.maestro.startCountdown(td, countdown: countdown)
// }
}
func cancelCurrentNotifications(countdownId: String) {
UNUserNotificationCenter.current().getPendingNotificationRequests { requests in
let ids = requests.map { $0.identifier }.filter { $0.hasPrefix(countdownId) }
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ids)
}
}
}