62 lines
2.1 KiB
Swift
62 lines
2.1 KiB
Swift
import Foundation
|
|
import UserNotifications
|
|
|
|
class NotificationManager: NSObject, UNUserNotificationCenterDelegate {
|
|
static let shared = NotificationManager()
|
|
|
|
/// UNUserNotificationCenter requires a valid .app bundle.
|
|
/// When running the bare binary (e.g. via build-test.sh) we skip notifications.
|
|
private var isInsideBundle: Bool {
|
|
return Bundle.main.bundleIdentifier != nil
|
|
}
|
|
|
|
private override init() {
|
|
super.init()
|
|
if isInsideBundle {
|
|
UNUserNotificationCenter.current().delegate = self
|
|
}
|
|
}
|
|
|
|
func requestPermission() {
|
|
guard isInsideBundle else {
|
|
NSLog("Pommedoro: skipping notification permission (not running from .app bundle)")
|
|
return
|
|
}
|
|
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
|
|
if let error = error {
|
|
NSLog("Pommedoro: notification permission error: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
}
|
|
|
|
func postCycleStarted(durationMinutes: Int) {
|
|
guard isInsideBundle else { return }
|
|
|
|
let content = UNMutableNotificationContent()
|
|
content.title = "Pommedoro"
|
|
content.body = "Cycle started — \(durationMinutes) minutes"
|
|
content.sound = .default
|
|
|
|
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
|
|
let request = UNNotificationRequest(
|
|
identifier: "pommedoro-cycle-start-\(UUID().uuidString)",
|
|
content: content,
|
|
trigger: trigger
|
|
)
|
|
|
|
UNUserNotificationCenter.current().add(request) { error in
|
|
if let error = error {
|
|
NSLog("Pommedoro: failed to post notification: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
}
|
|
|
|
func userNotificationCenter(
|
|
_ center: UNUserNotificationCenter,
|
|
willPresent notification: UNNotification,
|
|
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
|
) {
|
|
completionHandler([.banner, .sound])
|
|
}
|
|
}
|