G7CGMManager+UI.swift 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. //
  2. // G7CGMManager+UI.swift
  3. // CGMBLEKitUI
  4. //
  5. // Created by Pete Schwamb on 9/24/22.
  6. // Copyright © 2022 LoopKit Authors. All rights reserved.
  7. //
  8. import Foundation
  9. import G7SensorKit
  10. import LoopKitUI
  11. import LoopKit
  12. public struct G7DeviceStatusHighlight: DeviceStatusHighlight, Equatable {
  13. public let localizedMessage: String
  14. public let imageName: String
  15. public let state: DeviceStatusHighlightState
  16. init(localizedMessage: String, imageName: String, state: DeviceStatusHighlightState) {
  17. self.localizedMessage = localizedMessage
  18. self.imageName = imageName
  19. self.state = state
  20. }
  21. }
  22. extension G7CGMManager: CGMManagerUI {
  23. public static var onboardingImage: UIImage? {
  24. return nil
  25. }
  26. public static func setupViewController(bluetoothProvider: BluetoothProvider, displayGlucoseUnitObservable: DisplayGlucoseUnitObservable, colorPalette: LoopUIColorPalette, allowDebugFeatures: Bool) -> SetupUIResult<CGMManagerViewController, CGMManagerUI> {
  27. let vc = G7UICoordinator(colorPalette: colorPalette, displayGlucoseUnitObservable: displayGlucoseUnitObservable, allowDebugFeatures: allowDebugFeatures)
  28. return .userInteractionRequired(vc)
  29. }
  30. public func settingsViewController(bluetoothProvider: BluetoothProvider, displayGlucoseUnitObservable: DisplayGlucoseUnitObservable, colorPalette: LoopUIColorPalette, allowDebugFeatures: Bool) ->CGMManagerViewController {
  31. return G7UICoordinator(cgmManager: self, colorPalette: colorPalette, displayGlucoseUnitObservable: displayGlucoseUnitObservable, allowDebugFeatures: allowDebugFeatures)
  32. }
  33. public var smallImage: UIImage? {
  34. UIImage(named: "g7", in: Bundle(for: G7SettingsViewModel.self), compatibleWith: nil)!
  35. }
  36. // TODO Placeholder.
  37. public var cgmStatusHighlight: DeviceStatusHighlight? {
  38. if lifecycleState == .searching {
  39. return G7DeviceStatusHighlight(
  40. localizedMessage: LocalizedString("Searching for\nSensor", comment: "G7 Status highlight text for searching for sensor"),
  41. imageName: "dot.radiowaves.left.and.right",
  42. state: .normalCGM)
  43. }
  44. if lifecycleState == .expired {
  45. return G7DeviceStatusHighlight(
  46. localizedMessage: LocalizedString("Sensor\nExpired", comment: "G7 Status highlight text for sensor expired"),
  47. imageName: "clock",
  48. state: .normalCGM)
  49. }
  50. if lifecycleState == .failed {
  51. return G7DeviceStatusHighlight(
  52. localizedMessage: LocalizedString("Sensor\nFailed", comment: "G7 Status highlight text for sensor failed"),
  53. imageName: "exclamationmark.circle.fill",
  54. state: .critical)
  55. }
  56. if let latestReadingReceivedAt = state.latestReadingTimestamp, latestReadingReceivedAt.timeIntervalSinceNow < -.minutes(15) {
  57. return G7DeviceStatusHighlight(
  58. localizedMessage: LocalizedString("Signal\nLoss", comment: "G7 Status highlight text for signal loss"),
  59. imageName: "exclamationmark.circle.fill",
  60. state: .warning)
  61. }
  62. if let latestReading = latestReading, latestReading.algorithmState.isInSensorError {
  63. return G7DeviceStatusHighlight(
  64. localizedMessage: LocalizedString("Sensor\nIssue", comment: "G7 Status highlight text for sensor error"),
  65. imageName: "exclamationmark.circle.fill",
  66. state: .warning)
  67. }
  68. if lifecycleState == .warmup {
  69. return G7DeviceStatusHighlight(
  70. localizedMessage: LocalizedString("Sensor\nWarmup", comment: "G7 Status highlight text for sensor warmup"),
  71. imageName: "clock",
  72. state: .normalCGM)
  73. }
  74. return nil
  75. }
  76. // TODO Placeholder.
  77. public var cgmStatusBadge: DeviceStatusBadge? {
  78. if lifecycleState == .gracePeriod {
  79. return G7DeviceStatusBadge(image: UIImage(systemName: "clock"), state: .critical)
  80. }
  81. return nil
  82. }
  83. // TODO Placeholder.
  84. public var cgmLifecycleProgress: DeviceLifecycleProgress? {
  85. switch lifecycleState {
  86. case .ok:
  87. // show remaining lifetime, if < 24 hours
  88. guard let expiration = sensorExpiresAt else {
  89. return nil
  90. }
  91. let remaining = max(0, expiration.timeIntervalSinceNow)
  92. if remaining < .hours(24) {
  93. return G7LifecycleProgress(percentComplete: 1-(remaining/G7Sensor.lifetime), progressState: .warning)
  94. }
  95. return nil
  96. case .gracePeriod:
  97. guard let endTime = sensorEndsAt else {
  98. return nil
  99. }
  100. let remaining = max(0, endTime.timeIntervalSinceNow)
  101. return G7LifecycleProgress(percentComplete: 1-(remaining/G7Sensor.gracePeriod), progressState: .critical)
  102. case .expired:
  103. return G7LifecycleProgress(percentComplete: 1, progressState: .critical)
  104. default:
  105. return nil
  106. }
  107. }
  108. }
  109. struct G7DeviceStatusBadge: DeviceStatusBadge {
  110. var image: UIImage?
  111. var state: LoopKitUI.DeviceStatusBadgeState
  112. }
  113. struct G7LifecycleProgress: DeviceLifecycleProgress {
  114. var percentComplete: Double
  115. var progressState: LoopKit.DeviceLifecycleProgressState
  116. }