MinimedPumpUICoordinator.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // MinimedPumpUICoordinator.swift
  3. // MinimedKitUI
  4. //
  5. // Created by Pete Schwamb on 11/29/22.
  6. // Copyright © 2022 LoopKit Authors. All rights reserved.
  7. //
  8. import Foundation
  9. import LoopKit
  10. import LoopKitUI
  11. import MinimedKit
  12. import RileyLinkBLEKit
  13. import RileyLinkKit
  14. import RileyLinkKitUI
  15. import SwiftUI
  16. enum MinimedUIScreen {
  17. case settings
  18. func next() -> MinimedUIScreen? {
  19. switch self {
  20. case .settings:
  21. return nil
  22. }
  23. }
  24. }
  25. class MinimedUICoordinator: UINavigationController, PumpManagerOnboarding, CompletionNotifying, UINavigationControllerDelegate {
  26. public weak var pumpManagerOnboardingDelegate: PumpManagerOnboardingDelegate?
  27. public weak var completionDelegate: CompletionDelegate?
  28. private let colorPalette: LoopUIColorPalette
  29. private var allowedInsulinTypes: [InsulinType]
  30. private var allowDebugFeatures: Bool
  31. var pumpManager: MinimedPumpManager
  32. var screenStack = [MinimedUIScreen]()
  33. var currentScreen: MinimedUIScreen {
  34. return screenStack.last!
  35. }
  36. init(pumpManager: MinimedPumpManager? = nil, colorPalette: LoopUIColorPalette, pumpManagerSettings: PumpManagerSetupSettings? = nil, allowDebugFeatures: Bool, allowedInsulinTypes: [InsulinType] = [])
  37. {
  38. if pumpManager == nil, let pumpManagerSettings = pumpManagerSettings {
  39. let basalSchedule = pumpManagerSettings.basalSchedule
  40. let deviceProvider = RileyLinkBluetoothDeviceProvider(autoConnectIDs: [])
  41. let pumpManagerState = MinimedPumpManagerState(
  42. isOnboarded: false,
  43. useMySentry: true, // TODO
  44. pumpColor: .blue, // TODO
  45. pumpID: "111111", // TODO
  46. pumpModel: .model508, // TODO
  47. pumpFirmwareVersion: "1.11", // TODO
  48. pumpRegion: .northAmerica, // TODO
  49. rileyLinkConnectionState: nil,
  50. timeZone: basalSchedule.timeZone,
  51. suspendState: .resumed(Date()), // TODO
  52. insulinType: .novolog, // TODO
  53. lastTuned: nil,
  54. lastValidFrequency: nil,
  55. basalSchedule: BasalSchedule(repeatingScheduleValues: pumpManagerSettings.basalSchedule.items)
  56. )
  57. self.pumpManager = MinimedPumpManager(state: pumpManagerState, rileyLinkDeviceProvider: deviceProvider)
  58. } else {
  59. guard let pumpManager = pumpManager else {
  60. fatalError("Unable to create Minimed PumpManager")
  61. }
  62. self.pumpManager = pumpManager
  63. }
  64. self.colorPalette = colorPalette
  65. self.allowDebugFeatures = allowDebugFeatures
  66. self.allowedInsulinTypes = allowedInsulinTypes
  67. super.init(navigationBarClass: UINavigationBar.self, toolbarClass: UIToolbar.self)
  68. }
  69. required init?(coder aDecoder: NSCoder) {
  70. fatalError("init(coder:) has not been implemented")
  71. }
  72. override func viewDidLoad() {
  73. super.viewDidLoad()
  74. self.navigationBar.prefersLargeTitles = true
  75. delegate = self
  76. }
  77. override func viewWillAppear(_ animated: Bool) {
  78. super.viewWillAppear(animated)
  79. if screenStack.isEmpty {
  80. screenStack = [determineInitialStep()]
  81. let viewController = viewControllerForScreen(currentScreen)
  82. viewController.isModalInPresentation = false
  83. setViewControllers([viewController], animated: false)
  84. }
  85. }
  86. private func determineInitialStep() -> MinimedUIScreen {
  87. return .settings
  88. }
  89. private func viewControllerForScreen(_ screen: MinimedUIScreen) -> UIViewController {
  90. switch screen {
  91. case .settings:
  92. let viewModel = MinimedPumpSettingsViewModel(pumpManager: pumpManager)
  93. viewModel.didFinish = { [weak self] in
  94. self?.stepFinished()
  95. }
  96. let rileyLinkListDataSource = RileyLinkListDataSource(rileyLinkPumpManager: pumpManager)
  97. let handleRileyLinkSelection = { [weak self] (device: RileyLinkDevice) in
  98. if let self = self {
  99. let vc = RileyLinkDeviceTableViewController(
  100. device: device,
  101. batteryAlertLevel: self.pumpManager.rileyLinkBatteryAlertLevel,
  102. batteryAlertLevelChanged: { [weak self] value in
  103. self?.pumpManager.rileyLinkBatteryAlertLevel = value
  104. }
  105. )
  106. self.show(vc, sender: self)
  107. }
  108. }
  109. let view = MinimedPumpSettingsView(viewModel: viewModel, supportedInsulinTypes: allowedInsulinTypes, handleRileyLinkSelection: handleRileyLinkSelection, rileyLinkListDataSource: rileyLinkListDataSource)
  110. return hostingController(rootView: view)
  111. }
  112. }
  113. private func hostingController<Content: View>(rootView: Content) -> DismissibleHostingController {
  114. return DismissibleHostingController(rootView: rootView, colorPalette: colorPalette)
  115. }
  116. private func stepFinished() {
  117. if let nextStep = currentScreen.next() {
  118. navigateTo(nextStep)
  119. } else {
  120. completionDelegate?.completionNotifyingDidComplete(self)
  121. }
  122. }
  123. func navigateTo(_ screen: MinimedUIScreen) {
  124. screenStack.append(screen)
  125. let viewController = viewControllerForScreen(screen)
  126. viewController.isModalInPresentation = false
  127. self.pushViewController(viewController, animated: true)
  128. viewController.view.layoutSubviews()
  129. }
  130. }