OnboardingUI.swift 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //
  2. // OnboardingUI.swift
  3. // LoopKitUI
  4. //
  5. // Created by Darin Krauss on 12/10/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. import HealthKit
  10. import LoopKit
  11. public enum NotificationAuthorization: Int {
  12. /// User has not yet made a choice regarding whether the application may schedule or receive user notifications.
  13. case notDetermined
  14. /// User has explicitly denied this application from scheduling or receiving user notifications.
  15. case denied
  16. /// User has authorized this application to schedule or receive non-interruptive user notifications.
  17. case provisional
  18. /// User has authorized this application to schedule or receive any user notifications.
  19. case authorized
  20. }
  21. public protocol NotificationAuthorizationProvider: AnyObject {
  22. /// The current notification authorization.
  23. ///
  24. /// - Parameters:
  25. /// - completion: Invoked when notification authorization is available.
  26. func getNotificationAuthorization(_ completion: @escaping (NotificationAuthorization) -> Void)
  27. /// Authorize notification. Should only be invoked if notificationAuthorization is .notDetermined.
  28. ///
  29. /// - Parameters:
  30. /// - completion: Invoked when notification authorization is complete along with the resulting authorization.
  31. func authorizeNotification(_ completion: @escaping (NotificationAuthorization) -> Void)
  32. }
  33. public enum HealthStoreAuthorization: Int {
  34. /// User has not yet made a choice regarding permissions for one or more health store data types.
  35. case notDetermined
  36. /// User has explicitly chosen permissions for each health store data type.
  37. case determined
  38. }
  39. public protocol HealthStoreAuthorizationProvider: AnyObject {
  40. /// The current health store authorization.
  41. ///
  42. /// - Parameters:
  43. /// - completion: Invoked when health store authorization is available.
  44. func getHealthStoreAuthorization(_ completion: @escaping (HealthStoreAuthorization) -> Void)
  45. /// Authorize health store. Should only be invoked if healthStoreAuthorization is .notDetermined.
  46. ///
  47. /// - Parameters:
  48. /// - completion: Invoked when health store authorization is complete along with the resulting authorization.
  49. func authorizeHealthStore(_ completion: @escaping (HealthStoreAuthorization) -> Void)
  50. }
  51. public typealias OnboardingResult = SetupUIResult
  52. public protocol CGMManagerProvider: AnyObject {
  53. /// The active CGM manager.
  54. var activeCGMManager: CGMManager? { get }
  55. /// The descriptor list of available CGM managers.
  56. var availableCGMManagers: [CGMManagerDescriptor] { get }
  57. /// An image for the CGM manager with the specified identifier.
  58. ///
  59. /// - Parameters:
  60. /// - identifier: The identifier of the CGM manager.
  61. /// - Returns: An image for the CGM manager with the specified identifier.
  62. func imageForCGMManager(withIdentifier identifier: String) -> UIImage?
  63. /// Onboard the CGM manager with the specified identifier.
  64. ///
  65. /// - Parameters:
  66. /// - identifier: The identifier of the CGM manager to onboard.
  67. /// - Returns: Either a conforming view controller to onboard the CGM manager, a newly onboarded CGM manager, or an error.
  68. func onboardCGMManager(withIdentifier identifier: String) -> Result<OnboardingResult<CGMManagerViewController, CGMManager>, Error>
  69. }
  70. public protocol PumpManagerProvider: AnyObject {
  71. /// The active pump manager.
  72. var activePumpManager: PumpManager? { get }
  73. /// The descriptor list of available pump managers.
  74. var availablePumpManagers: [PumpManagerDescriptor] { get }
  75. /// An image for the pump manager with the specified identifier.
  76. ///
  77. /// - Parameters:
  78. /// - identifier: The identifier of the pump manager.
  79. /// - Returns: An image for the pump manager with the specified identifier.
  80. func imageForPumpManager(withIdentifier identifier: String) -> UIImage?
  81. /// An supported increments for the pump manager with the specified identifier.
  82. ///
  83. /// - Parameters:
  84. /// - identifier: The identifier of the pump manager.
  85. /// - Returns: An supported increments for the pump manager with the specified identifier.
  86. func supportedIncrementsForPumpManager(withIdentifier identifier: String) -> PumpSupportedIncrements?
  87. /// Onboard the pump manager with the specified identifier.
  88. ///
  89. /// - Parameters:
  90. /// - identifier: The identifier of the pump manager to onboard.
  91. /// - Returns: Either a conforming view controller to onboard the pump manager, a newly onboarded pump manager, or an error.
  92. func onboardPumpManager(withIdentifier identifier: String, initialSettings settings: PumpManagerSetupSettings) -> Result<OnboardingResult<PumpManagerViewController, PumpManager>, Error>
  93. }
  94. public protocol ServiceProvider: AnyObject {
  95. /// The active services.
  96. var activeServices: [Service] { get }
  97. /// The descriptor list of available services.
  98. var availableServices: [ServiceDescriptor] { get }
  99. /// Onboard the service with the specified identifier.
  100. ///
  101. /// - Parameters:
  102. /// - identifier: The identifier of the service to onboard.
  103. /// - Returns: Either a conforming view controller to onboard the service, a newly onboarded service, or an error.
  104. func onboardService(withIdentifier identifier: String) -> Result<OnboardingResult<ServiceViewController, Service>, Error>
  105. }
  106. public protocol TherapySettingsProvider {
  107. var onboardingTherapySettings: TherapySettings { get }
  108. }
  109. public protocol OnboardingProvider: NotificationAuthorizationProvider, HealthStoreAuthorizationProvider, BluetoothProvider, CGMManagerProvider, PumpManagerProvider, ServiceProvider, TherapySettingsProvider {
  110. var allowDebugFeatures: Bool { get } // NOTE: DEBUG FEATURES - DEBUG AND TEST ONLY
  111. }
  112. public protocol OnboardingDelegate: AnyObject {
  113. /// Informs the delegate that the state of the onboarding was updated and the delegate should persist the onboarding. May
  114. /// be invoked prior to the onboarding being fully complete.
  115. ///
  116. /// - Parameters:
  117. /// - onboarding: The onboarding that updated state.
  118. func onboardingDidUpdateState(_ onboarding: OnboardingUI)
  119. /// Informs the delegate that onboarding has new therapy settings that should be persisted.
  120. ///
  121. /// - Parameters:
  122. /// - onboarding: The onboarding that has new therapy settings.
  123. /// - therapySettings: The new therapy settings.
  124. func onboarding(_ onboarding: OnboardingUI, hasNewTherapySettings therapySettings: TherapySettings)
  125. /// Informs the delegate that onboarding has new dosing enabled that should be persisted.
  126. ///
  127. /// - Parameters:
  128. /// - onboarding: The onboarding that has new dosing enabled.
  129. /// - isClosedLoop: The new dosing enabled.
  130. func onboarding(_ onboarding: OnboardingUI, hasNewDosingEnabled dosingEnabled: Bool)
  131. /// Informs the delegate the onboarding has suspended.
  132. ///
  133. /// - Parameters:
  134. /// - onboarding: The onboarding that has suspended.
  135. func onboardingDidSuspend(_ onboarding: OnboardingUI)
  136. }
  137. public typealias OnboardingViewController = (UIViewController & CGMManagerOnboarding & PumpManagerOnboarding & ServiceOnboarding & CompletionNotifying)
  138. public protocol OnboardingUI: AnyObject {
  139. typealias RawState = [String: Any]
  140. /// Create a new onboarding.
  141. ///
  142. /// - Returns: A newly created onboarding.
  143. static func createOnboarding() -> OnboardingUI
  144. /// Delegate to notify about onboarding changes.
  145. var onboardingDelegate: OnboardingDelegate? { get set }
  146. /// The unique identifier of this type of onboarding.
  147. var onboardingIdentifier: String { get }
  148. /// Initializes the onboarding with the previously-serialized state.
  149. ///
  150. /// - Parameters:
  151. /// - rawState: The previously-serialized state of the onboarding.
  152. init?(rawState: RawState)
  153. /// The current, serializable state of the onboarding.
  154. var rawState: RawState { get }
  155. /// Is the onboarding complete?
  156. var isOnboarded: Bool { get }
  157. /// Provides a view controller to configure onboarding, if needed.
  158. ///
  159. /// - Parameters:
  160. /// - onboardingProvider: The provider of auxillary services that support onboarding.
  161. /// - displayGlucoseUnitObservable: The glucose unit to use for display.
  162. /// - colorPalette: The colors to use in any UI,
  163. /// - Returns: A view controller to create and configure a new onboarding.
  164. func onboardingViewController(onboardingProvider: OnboardingProvider, displayGlucoseUnitObservable: DisplayGlucoseUnitObservable, colorPalette: LoopUIColorPalette) -> OnboardingViewController
  165. }