import UserNotifications import Foundation import UIKit /// Main notification service for iOS RSSuper /// Handles push and local notifications using UserNotifications framework class NotificationService { static let shared = NotificationService() private let unuserNotifications = UNUserNotificationCenter.current() private let notificationCenter = NotificationCenter.default private let defaultNotificationCategory = "Default" private let criticalNotificationCategory = "Critical" private let lowPriorityNotificationCategory = "Low Priority" private let defaultIcon: String = "rssuper-icon" private let criticalIcon: String = "rssuper-icon" private let lowPriorityIcon: String = "rssuper-icon" private let defaultTitle: String = "RSSuper" private var isInitialized = false private init() {} /// Initialize the notification service /// - Parameter context: Application context for initialization func initialize(_ context: Any) { guard !isInitialized else { return } unuserNotifications.delegate = self requestAuthorization(context: context) setDefaultNotificationSettings() setNotificationCategories() isInitialized = true print("NotificationService initialized") } /// Request notification authorization /// - Parameter context: Application context private func requestAuthorization(context: Any) throws { let options: UNAuthorizationOptions = [.alert, .sound, .badge] let authorized = try unuserNotifications.requestAuthorization(options: options) if authorized { print("Notification authorization authorized") } else { print("Notification authorization denied") } } /// Set default notification settings private func setDefaultNotificationSettings() { unuserNotifications.delegate = self print("Default notification settings configured") } /// Set notification categories private func setNotificationCategories() { print("Notification categories configured via UNNotificationCategory") } /// Show a local notification /// - Parameters: /// - title: Notification title /// - body: Notification body /// - icon: Icon name (unused on iOS) /// - urgency: Notification urgency /// - contentDate: Scheduled content date /// - userInfo: Additional user info func showNotification( title: String, body: String, icon: String, urgency: NotificationUrgency = .normal, contentDate: Date? = nil, userInfo: [AnyHashable: Any]? = nil ) { let notificationContent = UNMutableNotificationContent() notificationContent.title = title notificationContent.body = body notificationContent.sound = UNNotificationSound.default notificationContent.categoryIdentifier = urgency.rawValue if let contentDate = contentDate { notificationContent.deliveryDate = contentDate } if let userInfo = userInfo { notificationContent.userInfo = userInfo } let trigger = contentDate.map { UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: $0), repeats: false) } let request = UNNotificationRequest( identifier: UUID().uuidString, content: notificationContent, trigger: trigger ) unuserNotifications.add(request) { error in if let error = error { print("Failed to show notification: \(error)") } else { print("Notification shown: \(title)") } } } /// Show a critical notification /// - Parameters: /// - title: Notification title /// - body: Notification body /// - icon: Icon name func showCriticalNotification(title: String, body: String, icon: String) { showNotification( title: title, body: body, icon: icon, urgency: .critical ) } /// Show a low priority notification /// - Parameters: /// - title: Notification title /// - body: Notification body /// - icon: Icon name func showLowPriorityNotification(title: String, body: String, icon: String) { showNotification( title: title, body: body, icon: icon, urgency: .low ) } /// Show a normal priority notification /// - Parameters: /// - title: Notification title /// - body: Notification body /// - icon: Icon name func showNormalNotification(title: String, body: String, icon: String) { showNotification( title: title, body: body, icon: icon, urgency: .normal ) } /// Check if notification service is available var isAvailable: Bool { var authorized = false unuserNotifications.getNotificationSettings { settings in authorized = settings.authorizationStatus == .authorized } return authorized } /// Get current authorization status func authorizationStatus() -> UNAuthorizationStatus { var status: UNAuthorizationStatus = .denied unuserNotifications.getNotificationSettings { settings in status = settings.authorizationStatus } return status } /// Get the notification center func notificationCenter() -> UNUserNotificationCenter { return unuserNotifications } } extension NotificationService: UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.banner, .sound]) } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { completionHandler() } } /// Notification urgency enum enum NotificationUrgency: Int { case critical = 5 case normal = 1 case low = 0 var priority: UNNotificationPriority { switch self { case .critical: return .high case .normal: return .default case .low: return .low } } }