WatchNotificationHandler.swift 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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.glucoseAlert.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: "Snooze 20 min", comment: "Snooze glucose alerts for 20 minutes")
  38. case .snooze40:
  39. return String(localized: "Snooze 40 min", comment: "Snooze glucose alerts for 40 minutes")
  40. case .snooze60:
  41. return String(localized: "Snooze 1 hr", comment: "Snooze glucose alerts for 60 minutes")
  42. }
  43. }
  44. func userNotificationCenter(
  45. _: UNUserNotificationCenter,
  46. didReceive response: UNNotificationResponse,
  47. withCompletionHandler completionHandler: @escaping () -> Void
  48. ) {
  49. defer { completionHandler() }
  50. guard let action = NotificationResponseAction(rawValue: response.actionIdentifier) else { return }
  51. sendSnoozeRequest(for: action)
  52. }
  53. private func sendSnoozeRequest(for action: NotificationResponseAction) {
  54. guard WCSession.isSupported() else { return }
  55. let payload: [String: Any] = [WatchMessageKeys.snoozeDuration: action.minutes]
  56. let session = WCSession.default
  57. if session.delegate == nil {
  58. session.delegate = PassiveSessionDelegate.shared
  59. }
  60. if session.activationState == .notActivated {
  61. session.activate()
  62. }
  63. if session.isReachable {
  64. session.sendMessage(payload, replyHandler: nil) { _ in
  65. session.transferUserInfo(payload)
  66. }
  67. } else {
  68. session.transferUserInfo(payload)
  69. }
  70. }
  71. }
  72. private final class PassiveSessionDelegate: NSObject, WCSessionDelegate {
  73. static let shared = PassiveSessionDelegate()
  74. private override init() {}
  75. func session(
  76. _: WCSession,
  77. activationDidCompleteWith _: WCSessionActivationState,
  78. error _: Error?
  79. ) {}
  80. #if os(watchOS)
  81. func sessionReachabilityDidChange(_: WCSession) {}
  82. #endif
  83. }