// // LocalNotification.swift // Reflect // // Created by Trey Tartt on 1/8/22. // import Foundation import UserNotifications class LocalNotification { public enum ActionType: String { case horrible = "HORRIBLE_ACTION" case bad = "BAD_ACTION" case average = "AVERAGE_ACTION" case good = "GOOD_ACTION" case great = "GREAT_ACTION" } static let categoryName = "MOOD_UPDATE" public class func testIfEnabled(completion: @escaping (Result) -> Void) { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in if success { Task { @MainActor in AnalyticsManager.shared.track(.notificationEnabled) } completion(.success(true)) } else if let error = error { Task { @MainActor in AnalyticsManager.shared.track(.notificationDisabled) } completion(.failure(error)) } } } public class func rescheduleNotifiations() { if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.savedOnboardingData.rawValue) as? Data, let model = try? JSONDecoder().decode(OnboardingData.self, from: data) { LocalNotification.scheduleReminder(atTime: model.date) } } public class func scheduleReminder(atTime time: Date) { self.removeNotificaiton() LocalNotification.testIfEnabled(completion: { result in switch result{ case .success(_): let _ = LocalNotification.createNotificationCategory() let notificationContent = UNMutableNotificationContent() let strings = UserDefaultsStore.personalityPackable().randomPushNotificationStrings() notificationContent.title = strings.title notificationContent.body = strings.body notificationContent.badge = NSNumber(value: 1) notificationContent.sound = .default notificationContent.categoryIdentifier = LocalNotification.categoryName let calendar = Calendar.current let time = calendar.dateComponents([.hour,.minute], from: time) var datComp = DateComponents() datComp.hour = time.hour datComp.minute = time.minute let trigger = UNCalendarNotificationTrigger(dateMatching: datComp, repeats: true) let request = UNNotificationRequest(identifier: UUID().uuidString, content: notificationContent, trigger: trigger) UNUserNotificationCenter.current().add(request) { (error : Error?) in if let theError = error { print(theError.localizedDescription) } } case .failure(let error): print(error) // Todo: show enable this break } }) } private class func createNotificationCategory() -> UNNotificationCategory { let moodCategory = UNNotificationCategory(identifier: LocalNotification.categoryName, actions: [horribleAction, badAction, averageAction, goodAction, greatAction], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: "", options: .customDismissAction) // Register the notification type. let notificationCenter = UNUserNotificationCenter.current() notificationCenter.setNotificationCategories([moodCategory]) return moodCategory } private class var horribleAction: UNNotificationAction { let acceptAction = UNNotificationAction(identifier: ActionType.horrible.rawValue, title: "Horrible", options: []) return acceptAction } private class var badAction: UNNotificationAction { let acceptAction = UNNotificationAction(identifier: ActionType.bad.rawValue, title: "Bad", options: []) return acceptAction } private class var averageAction: UNNotificationAction { let acceptAction = UNNotificationAction(identifier: ActionType.average.rawValue, title: "Average", options: []) return acceptAction } private class var goodAction: UNNotificationAction { let acceptAction = UNNotificationAction(identifier: ActionType.good.rawValue, title: "Good", options: []) return acceptAction } private class var greatAction: UNNotificationAction { let acceptAction = UNNotificationAction(identifier: ActionType.great.rawValue, title: "Great", options: []) return acceptAction } public class func removeNotificaiton() { UNUserNotificationCenter.current().removeAllPendingNotificationRequests() } // MARK: - Debug: Send All Personality Pack Notifications // MARK: - Weekly Digest Notification public class func scheduleDigestNotification(headline: String, personalityPack: PersonalityPack) { let content = UNMutableNotificationContent() content.title = String(localized: "Your Weekly Digest") content.body = headline content.sound = .default let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) let request = UNNotificationRequest( identifier: "weekly-digest-\(UUID().uuidString)", content: content, trigger: trigger ) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("Failed to schedule digest notification: \(error)") } } } #if DEBUG /// Sends one notification from each personality pack, staggered over 10 seconds for screenshot public class func sendAllPersonalityNotificationsForScreenshot() { let _ = createNotificationCategory() let packs: [(PersonalityPack, Double)] = [ (.Default, 5), (.MotivationalCoach, 6), (.ZenMaster, 7), (.BestFriend, 8), (.DataAnalyst, 9) ] for (pack, delay) in packs { let content = UNMutableNotificationContent() let strings = pack.randomPushNotificationStrings() content.title = strings.title content.body = strings.body content.sound = .default content.categoryIdentifier = LocalNotification.categoryName content.interruptionLevel = .timeSensitive let trigger = UNTimeIntervalNotificationTrigger(timeInterval: delay, repeats: false) let request = UNNotificationRequest( identifier: "debug-\(pack.rawValue)-\(UUID().uuidString)", content: content, trigger: trigger ) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("Failed to schedule \(pack) notification: \(error)") } else { print("Scheduled \(pack) notification in \(delay)s") } } } } #endif }