From c80c3182e51a541305d3877b05b92164c402c696 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 1 May 2023 09:38:17 -0300 Subject: [PATCH] enhance errors --- .../ios/Sources/Notification.swift | 30 ++++++++++++++----- .../ios/Sources/NotificationCategory.swift | 26 +++++++++++----- .../ios/Sources/NotificationPlugin.swift | 6 ++-- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/plugins/notification/ios/Sources/Notification.swift b/plugins/notification/ios/Sources/Notification.swift index 3c304020..52b1016f 100644 --- a/plugins/notification/ios/Sources/Notification.swift +++ b/plugins/notification/ios/Sources/Notification.swift @@ -5,19 +5,36 @@ enum NotificationError: LocalizedError { case contentNoId case contentNoTitle case contentNoBody - case triggerConstructionFailed case triggerRepeatIntervalTooShort case attachmentNoId case attachmentNoUrl case attachmentFileNotFound(path: String) case attachmentUnableToCreate(String) + case pastScheduledTime + case invalidDate(String) var errorDescription: String? { switch self { + case .contentNoId: + return "Missing notification identifier" + case .contentNoTitle: + return "Missing notification title" + case .contentNoBody: + return "Missing notification body" + case .triggerRepeatIntervalTooShort: + return "Schedule interval too short, must be a least 1 minute" + case .attachmentNoId: + return "Missing attachment identifier" + case .attachmentNoUrl: + return "Missing attachment URL" case .attachmentFileNotFound(let path): return "Unable to find file \(path) for attachment" - default: - return "" + case .attachmentUnableToCreate(let error): + return "Failed to create attachment: \(error)" + case .pastScheduledTime: + return "Scheduled time must be *after* current time" + case .invalidDate(let date): + return "Could not parse date \(date)" } } } @@ -127,7 +144,7 @@ func makeAttachmentOptions(_ options: JSObject) -> JSObject { return opts } -func handleScheduledNotification(_ invoke: Invoke, _ schedule: JSObject) throws +func handleScheduledNotification(_ schedule: JSObject) throws -> UNNotificationTrigger? { let kind = schedule["kind"] as? String ?? "" @@ -145,8 +162,7 @@ func handleScheduledNotification(_ invoke: Invoke, _ schedule: JSObject) throws let dateInfo = Calendar.current.dateComponents(in: TimeZone.current, from: at) if dateInfo.date! < Date() { - invoke.reject("Scheduled time must be *after* current time") - return nil + throw NotificationError.pastScheduledTime } let dateInterval = DateInterval(start: Date(), end: dateInfo.date!) @@ -160,7 +176,7 @@ func handleScheduledNotification(_ invoke: Invoke, _ schedule: JSObject) throws timeInterval: dateInterval.duration, repeats: repeats) } else { - invoke.reject("could not parse `at` date \(date)") + throw NotificationError.invalidDate(date) } case "Interval": let dateComponents = getDateComponents(payload) diff --git a/plugins/notification/ios/Sources/NotificationCategory.swift b/plugins/notification/ios/Sources/NotificationCategory.swift index d6d32edf..74a1e194 100644 --- a/plugins/notification/ios/Sources/NotificationCategory.swift +++ b/plugins/notification/ios/Sources/NotificationCategory.swift @@ -1,7 +1,21 @@ import Tauri import UserNotifications -public func makeCategories(_ actionTypes: [JSObject]) { +enum CategoryError: LocalizedError { + case noId + case noActionId + + var errorDescription: String? { + switch self { + case .noId: + return "Action type `id` missing" + case .noActionId: + return "Action `id` missing" + } + } +} + +public func makeCategories(_ actionTypes: [JSObject]) throws { var createdCategories = [UNNotificationCategory]() let generalCategory = UNNotificationCategory( @@ -13,13 +27,12 @@ public func makeCategories(_ actionTypes: [JSObject]) { createdCategories.append(generalCategory) for type in actionTypes { guard let id = type["id"] as? String else { - Logger.error("Action type must have an id field") - continue + throw CategoryError.noId } let hiddenBodyPlaceholder = type["hiddenPreviewsBodyPlaceholder"] as? String ?? "" let actions = type["actions"] as? [JSObject] ?? [] - let newActions = makeActions(actions) + let newActions = try makeActions(actions) // Create the custom actions for the TIMER_EXPIRED category. var newCategory: UNNotificationCategory? @@ -38,13 +51,12 @@ public func makeCategories(_ actionTypes: [JSObject]) { center.setNotificationCategories(Set(createdCategories)) } -func makeActions(_ actions: [JSObject]) -> [UNNotificationAction] { +func makeActions(_ actions: [JSObject]) throws -> [UNNotificationAction] { var createdActions = [UNNotificationAction]() for action in actions { guard let id = action["id"] as? String else { - Logger.error("Action must have an id field") - continue + throw CategoryError.noActionId } let title = action["title"] as? String ?? "" let input = action["input"] as? Bool ?? false diff --git a/plugins/notification/ios/Sources/NotificationPlugin.swift b/plugins/notification/ios/Sources/NotificationPlugin.swift index c352e1b0..f35a3cd0 100644 --- a/plugins/notification/ios/Sources/NotificationPlugin.swift +++ b/plugins/notification/ios/Sources/NotificationPlugin.swift @@ -39,7 +39,7 @@ func showNotification(invoke: Invoke, notification: JSObject) do { if let schedule = notification["schedule"] as? JSObject { - try trigger = handleScheduledNotification(invoke, schedule) + try trigger = handleScheduledNotification(schedule) } } catch { throw ShowNotificationError.create(error) @@ -154,11 +154,11 @@ class NotificationPlugin: Plugin { }) } - @objc func registerActionTypes(_ invoke: Invoke) { + @objc func registerActionTypes(_ invoke: Invoke) throws { guard let types = invoke.getArray("types", JSObject.self) else { return } - makeCategories(types) + try makeCategories(types) invoke.resolve() }