AutosensSettingsRootView.swift 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import SwiftUI
  2. import Swinject
  3. extension AutosensSettings {
  4. struct RootView: BaseView {
  5. let resolver: Resolver
  6. @StateObject var state = StateModel()
  7. @State private var shouldDisplayHint: Bool = false
  8. @State var hintDetent = PresentationDetent.large
  9. @State var selectedVerboseHint: String?
  10. @State var hintLabel: String?
  11. @State private var decimalPlaceholder: Decimal = 0.0
  12. @State private var booleanPlaceholder: Bool = false
  13. @Environment(\.colorScheme) var colorScheme
  14. @EnvironmentObject var appIcons: Icons
  15. @Environment(AppState.self) var appState
  16. private var rateFormatter: NumberFormatter {
  17. let formatter = NumberFormatter()
  18. formatter.numberStyle = .decimal
  19. formatter.maximumFractionDigits = 2
  20. return formatter
  21. }
  22. var body: some View {
  23. List {
  24. if let newISF = state.autosensISF {
  25. Section(
  26. header: !state.settingsManager.preferences
  27. .useNewFormula ? Text("Autosens") : Text("Dynamic Sensitivity")
  28. ) {
  29. VStack {
  30. let dynamicRatio = state.determinationsFromPersistence.first?.sensitivityRatio
  31. let dynamicISF = state.determinationsFromPersistence.first?.insulinSensitivity
  32. HStack {
  33. Text("Sensitivity Ratio")
  34. Spacer()
  35. Text(
  36. rateFormatter
  37. .string(from: (
  38. (
  39. !state.settingsManager.preferences.useNewFormula ? state
  40. .autosensRatio as NSDecimalNumber : dynamicRatio
  41. ) ?? 1
  42. ) as NSNumber) ?? "1"
  43. )
  44. }.padding(.vertical)
  45. HStack {
  46. Text("Calculated Sensitivity")
  47. Spacer()
  48. if state.units == .mgdL {
  49. Text(
  50. !state.settingsManager.preferences
  51. .useNewFormula ? newISF.description : (dynamicISF ?? 0).description
  52. )
  53. } else {
  54. Text((
  55. !state.settingsManager.preferences
  56. .useNewFormula ? newISF.formattedAsMmolL : dynamicISF?.decimalValue.formattedAsMmolL
  57. ) ?? "0")
  58. }
  59. Text(state.units.rawValue + "/U").foregroundColor(.secondary)
  60. }
  61. HStack(alignment: .top) {
  62. Text(
  63. "This is a snapshot in time and should not be used as your ISF setting."
  64. )
  65. .font(.footnote)
  66. .foregroundColor(.secondary)
  67. .lineLimit(nil)
  68. Spacer()
  69. Button(
  70. action: {
  71. hintLabel = "Autosens"
  72. selectedVerboseHint =
  73. "Autosens automatically adjusts insulin delivery based on how sensitive or resistant you are to insulin, by analyzing past data to keep blood sugar levels stable.\n\nHow it works: It looks at the last 8-24 hours of data, excluding meal-related changes, and adjusts insulin settings like basal rates and targets when needed to match your sensitivity or resistance to insulin.\n\nWhat it adjusts: Autosens modifies insulin sensitivity factor (ISF), basal rates, and target blood sugar levels. It doesn’t account for carbs but adjusts for insulin effectiveness based on patterns in your glucose data.\n\nKey limitations: Autosens has safety limits (1.2 for resistance and 0.7 for sensitivity) to prevent over-adjusting, and it works alongside or can be disabled by other settings like Autotune or advanced target adjustments."
  74. shouldDisplayHint.toggle()
  75. },
  76. label: {
  77. HStack {
  78. Image(systemName: "questionmark.circle")
  79. }
  80. }
  81. ).buttonStyle(BorderlessButtonStyle())
  82. }.padding(.top)
  83. }.padding(.bottom)
  84. }.listRowBackground(Color.chart)
  85. }
  86. SettingInputSection(
  87. decimalValue: $state.autosensMax,
  88. booleanValue: $booleanPlaceholder,
  89. shouldDisplayHint: $shouldDisplayHint,
  90. selectedVerboseHint: Binding(
  91. get: { selectedVerboseHint },
  92. set: {
  93. selectedVerboseHint = $0
  94. hintLabel = NSLocalizedString("Autosens Max", comment: "Autosens Max")
  95. }
  96. ),
  97. units: state.units,
  98. type: .decimal("autosensMax"),
  99. label: NSLocalizedString("Autosens Max", comment: "Autosens Max"),
  100. miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
  101. verboseHint: NSLocalizedString(
  102. "This is a multiplier cap for autosens (and autotune) to set a 20% max limit on how high the autosens ratio can be, which in turn determines how high autosens can adjust basals, how low it can adjust ISF, and how low it can set the BG target.",
  103. comment: "Autosens Max"
  104. ),
  105. headerText: "Glucose Deviations Algorithm"
  106. )
  107. SettingInputSection(
  108. decimalValue: $state.autosensMin,
  109. booleanValue: $booleanPlaceholder,
  110. shouldDisplayHint: $shouldDisplayHint,
  111. selectedVerboseHint: Binding(
  112. get: { selectedVerboseHint },
  113. set: {
  114. selectedVerboseHint = $0
  115. hintLabel = NSLocalizedString("Autosens Min", comment: "Autosens Min")
  116. }
  117. ),
  118. units: state.units,
  119. type: .decimal("autosensMin"),
  120. label: NSLocalizedString("Autosens Min", comment: "Autosens Min"),
  121. miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
  122. verboseHint: NSLocalizedString(
  123. "The other side of the autosens safety limits, putting a cap on how low autosens can adjust basals, and how high it can adjust ISF and BG targets.",
  124. comment: "Autosens Min"
  125. )
  126. )
  127. SettingInputSection(
  128. decimalValue: $decimalPlaceholder,
  129. booleanValue: $state.rewindResetsAutosens,
  130. shouldDisplayHint: $shouldDisplayHint,
  131. selectedVerboseHint: Binding(
  132. get: { selectedVerboseHint },
  133. set: {
  134. selectedVerboseHint = $0
  135. hintLabel = NSLocalizedString("Rewind Resets Autosens", comment: "Rewind Resets Autosens")
  136. }
  137. ),
  138. units: state.units,
  139. type: .boolean,
  140. label: NSLocalizedString("Rewind Resets Autosens", comment: "Rewind Resets Autosens"),
  141. miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
  142. verboseHint: NSLocalizedString(
  143. "This feature, enabled by default, resets the autosens ratio to neutral when you rewind your pump, on the assumption that this corresponds to a probable site change. Autosens will begin learning sensitivity anew from the time of the rewind, which may take up to 6 hours. If you usually rewind your pump independently of site changes, you may want to consider disabling this feature.",
  144. comment: "Rewind Resets Autosens"
  145. )
  146. )
  147. }
  148. .sheet(isPresented: $shouldDisplayHint) {
  149. SettingInputHintView(
  150. hintDetent: $hintDetent,
  151. shouldDisplayHint: $shouldDisplayHint,
  152. hintLabel: hintLabel ?? "",
  153. hintText: selectedVerboseHint ?? "",
  154. sheetTitle: "Help"
  155. )
  156. }
  157. .scrollContentBackground(.hidden).background(appState.trioBackgroundColor(for: colorScheme))
  158. .onAppear(perform: configureView)
  159. .navigationTitle("Autosens")
  160. .navigationBarTitleDisplayMode(.automatic)
  161. }
  162. }
  163. }