codeburn/mac/Sources/CodeBurnMenubar/Data/UpdateNotifier.swift

50 lines
1.9 KiB
Swift

import Foundation
import UserNotifications
/// User preference for proactive update notifications. Absent key is true, so
/// existing installs get the notification without visiting Settings first.
enum UpdateNotificationPreference {
static let defaultsKey = "codeburn.update.notificationsEnabled"
static func isEnabled(defaults: UserDefaults = .standard) -> Bool {
defaults.object(forKey: defaultsKey) as? Bool ?? true
}
}
/// The notification side of the update check, behind a protocol so tests never
/// reach `UNUserNotificationCenter.current()`, which aborts in a process that is
/// not an app bundle (`swift test`, `swift run`).
@MainActor
protocol UpdateNotifier: AnyObject {
func requestAuthorizationIfNeeded() async -> Bool
func post(title: String, body: String, identifier: String)
}
@MainActor
final class SystemUpdateNotifier: UpdateNotifier {
func requestAuthorizationIfNeeded() async -> Bool {
guard Bundle.main.bundleIdentifier != nil else { return false }
let center = UNUserNotificationCenter.current()
switch await center.notificationSettings().authorizationStatus {
case .authorized, .provisional:
return true
case .notDetermined:
do {
return try await center.requestAuthorization(options: [.alert])
} catch {
NSLog("CodeBurn: notification authorization failed: \(error)")
return false
}
default:
return false
}
}
func post(title: String, body: String, identifier: String) {
let content = UNMutableNotificationContent()
content.title = title
content.body = body
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
}