WatchNotificationHandler.swift 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import Foundation
  2. import UserNotifications
  3. import WatchConnectivity
  4. final class WatchNotificationHandler: NSObject, UNUserNotificationCenterDelegate {
  5. static let shared = WatchNotificationHandler()
  6. private override init() {
  7. super.init()
  8. }
  9. func configure() {
  10. let center = UNUserNotificationCenter.current()
  11. center.delegate = self
  12. registerCategories(on: center)
  13. }
  14. private func registerCategories(on center: UNUserNotificationCenter) {
  15. center.getNotificationCategories { existingCategories in
  16. let snoozeActions = NotificationResponseAction.allCases.map { action in
  17. UNNotificationAction(
  18. identifier: action.rawValue,
  19. title: self.title(for: action),
  20. options: []
  21. )
  22. }
  23. let glucoseCategory = UNNotificationCategory(
  24. identifier: NotificationCategoryIdentifier.trioAlert.rawValue,
  25. actions: snoozeActions,
  26. intentIdentifiers: [],
  27. options: []
  28. )
  29. var categories = existingCategories
  30. categories.update(with: glucoseCategory)
  31. center.setNotificationCategories(categories)
  32. }
  33. }
  34. private func title(for action: NotificationResponseAction) -> String {
  35. switch action {
  36. case .snooze20:
  37. return String(localized: "20 min", comment: "Snooze glucose alerts for 20 minutes")
  38. case .snooze1hr:
  39. return String(localized: "1 hour", comment: "Snooze glucose alerts for 1 hour")
  40. case .snooze3hr:
  41. return String(localized: "3 hours", comment: "Snooze glucose alerts for 3 hours")
  42. case .snooze6hr:
  43. return String(localized: "6 hours", comment: "Snooze glucose alerts for 6 hours")
  44. }
  45. }
  46. func userNotificationCenter(
  47. _: UNUserNotificationCenter,
  48. didReceive response: UNNotificationResponse,
  49. withCompletionHandler completionHandler: @escaping () -> Void
  50. ) {
  51. defer { completionHandler() }
  52. guard let action = NotificationResponseAction(rawValue: response.actionIdentifier) else { return }
  53. sendSnoozeRequest(for: action)
  54. }
  55. private func sendSnoozeRequest(for action: NotificationResponseAction) {
  56. guard WCSession.isSupported() else { return }
  57. let payload: [String: Any] = [WatchMessageKeys.snoozeDuration: action.minutes]
  58. let session = WCSession.default
  59. if session.delegate == nil {
  60. session.delegate = PassiveSessionDelegate.shared
  61. }
  62. if session.activationState == .notActivated {
  63. session.activate()
  64. }
  65. if session.isReachable {
  66. session.sendMessage(payload, replyHandler: nil) { _ in
  67. session.transferUserInfo(payload)
  68. }
  69. } else {
  70. session.transferUserInfo(payload)
  71. }
  72. }
  73. }
  74. private final class PassiveSessionDelegate: NSObject, WCSessionDelegate {
  75. static let shared = PassiveSessionDelegate()
  76. private override init() {}
  77. func session(
  78. _: WCSession,
  79. activationDidCompleteWith _: WCSessionActivationState,
  80. error _: Error?
  81. ) {}
  82. #if os(watchOS)
  83. func sessionReachabilityDidChange(_: WCSession) {}
  84. #endif
  85. }