PreferencesEditorViewModel.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. import Foundation
  2. import SwiftUI
  3. extension PreferencesEditor {
  4. class ViewModel<Provider>: BaseViewModel<Provider>, ObservableObject,
  5. PreferencesSettable where Provider: PreferencesEditorProvider
  6. {
  7. @Injected() var settingsManager: SettingsManager!
  8. private(set) var preferences = Preferences()
  9. @Published var unitsIndex = 1
  10. @Published var allowAnnouncements = false
  11. @Published var insulinReqFraction: Decimal = 0.7
  12. @Published var skipBolusScreenAfterCarbs = false
  13. @Published var decimalFields: [Field<Decimal>] = []
  14. @Published var boolFields: [Field<Bool>] = []
  15. @Published var insulinCurveField = Field<InsulinCurve>(
  16. displayName: "Insulin curve",
  17. keypath: \.curve,
  18. value: .rapidActing
  19. )
  20. override func subscribe() {
  21. preferences = provider.preferences
  22. unitsIndex = settingsManager.settings.units == .mgdL ? 0 : 1
  23. allowAnnouncements = settingsManager.settings.allowAnnouncements
  24. insulinCurveField.value = preferences.curve
  25. insulinCurveField.settable = self
  26. insulinReqFraction = settingsManager.settings.insulinReqFraction ?? 0.7
  27. skipBolusScreenAfterCarbs = settingsManager.settings.skipBolusScreenAfterCarbs ?? false
  28. $unitsIndex
  29. .removeDuplicates()
  30. .sink { [weak self] index in
  31. self?.settingsManager.settings.units = index == 0 ? .mgdL : .mmolL
  32. self?.provider.migrateUnits()
  33. }
  34. .store(in: &lifetime)
  35. $allowAnnouncements
  36. .removeDuplicates()
  37. .sink { [weak self] allow in
  38. self?.settingsManager.settings.allowAnnouncements = allow
  39. }
  40. .store(in: &lifetime)
  41. $insulinReqFraction
  42. .removeDuplicates()
  43. .sink { [weak self] fraction in
  44. self?.settingsManager.settings.insulinReqFraction = fraction
  45. }
  46. .store(in: &lifetime)
  47. $skipBolusScreenAfterCarbs
  48. .removeDuplicates()
  49. .sink { [weak self] skip in
  50. self?.settingsManager.settings.skipBolusScreenAfterCarbs = skip
  51. }
  52. .store(in: &lifetime)
  53. boolFields = [
  54. Field(
  55. displayName: "Rewind Resets Autosens",
  56. keypath: \.rewindResetsAutosens,
  57. value: preferences.rewindResetsAutosens,
  58. settable: self
  59. ),
  60. Field(
  61. displayName: "High Temptarget Raises Sensitivity",
  62. keypath: \.highTemptargetRaisesSensitivity,
  63. value: preferences.highTemptargetRaisesSensitivity,
  64. settable: self
  65. ),
  66. Field(
  67. displayName: "Low Temptarget Lowers Sensitivity",
  68. keypath: \.lowTemptargetLowersSensitivity,
  69. value: preferences.lowTemptargetLowersSensitivity,
  70. settable: self
  71. ),
  72. Field(
  73. displayName: "Sensitivity Raises Target",
  74. keypath: \.sensitivityRaisesTarget,
  75. value: preferences.sensitivityRaisesTarget,
  76. settable: self
  77. ),
  78. Field(
  79. displayName: "Resistance Lowers Target",
  80. keypath: \.resistanceLowersTarget,
  81. value: preferences.resistanceLowersTarget,
  82. settable: self
  83. ),
  84. Field(
  85. displayName: "Enable Auto ISF",
  86. keypath: \.autoisf,
  87. value: preferences.autoisf,
  88. settable: self
  89. ),
  90. Field(
  91. displayName: "Advanced Target Adjustments",
  92. keypath: \.advTargetAdjustments,
  93. value: preferences.advTargetAdjustments,
  94. settable: self
  95. ),
  96. Field(
  97. displayName: "Exercise Mode",
  98. keypath: \.exerciseMode,
  99. value: preferences.exerciseMode,
  100. settable: self
  101. ),
  102. Field(
  103. displayName: "Wide BG Target Range",
  104. keypath: \.wideBGTargetRange,
  105. value: preferences.wideBGTargetRange,
  106. settable: self
  107. ),
  108. Field(
  109. displayName: "Skip Neutral Temps",
  110. keypath: \.skipNeutralTemps,
  111. value: preferences.skipNeutralTemps,
  112. settable: self
  113. ),
  114. Field(
  115. displayName: "Unsuspend If No Temp",
  116. keypath: \.unsuspendIfNoTemp,
  117. value: preferences.unsuspendIfNoTemp,
  118. settable: self
  119. ),
  120. Field(
  121. displayName: "Enable UAM",
  122. keypath: \.enableUAM,
  123. value: preferences.enableUAM,
  124. settable: self
  125. ),
  126. // Field(
  127. // displayName: "A52 Risk Enable",
  128. // keypath: \.a52RiskEnable,
  129. // value: preferences.a52RiskEnable,
  130. // settable: self
  131. // ),
  132. Field(
  133. displayName: "Enable SMB With COB",
  134. keypath: \.enableSMBWithCOB,
  135. value: preferences.enableSMBWithCOB,
  136. settable: self
  137. ),
  138. Field(
  139. displayName: "Enable SMB With Temptarget",
  140. keypath: \.enableSMBWithTemptarget,
  141. value: preferences.enableSMBWithTemptarget,
  142. settable: self
  143. ),
  144. Field(
  145. displayName: "Enable SMB Always",
  146. keypath: \.enableSMBAlways,
  147. value: preferences.enableSMBAlways,
  148. settable: self
  149. ),
  150. Field(
  151. displayName: "Enable SMB After Carbs",
  152. keypath: \.enableSMBAfterCarbs,
  153. value: preferences.enableSMBAfterCarbs,
  154. settable: self
  155. ),
  156. Field(
  157. displayName: "Allow SMB With High Temptarget",
  158. keypath: \.allowSMBWithHighTemptarget,
  159. value: preferences.allowSMBWithHighTemptarget,
  160. settable: self
  161. ),
  162. Field(
  163. displayName: "Use Custom Peak Time",
  164. keypath: \.useCustomPeakTime,
  165. value: preferences.useCustomPeakTime,
  166. settable: self
  167. ),
  168. Field(
  169. displayName: "Suspend Zeros IOB",
  170. keypath: \.suspendZerosIOB,
  171. value: preferences.suspendZerosIOB,
  172. settable: self
  173. )
  174. ]
  175. decimalFields = [
  176. Field(
  177. displayName: "Max IOB",
  178. keypath: \.maxIOB,
  179. value: preferences.maxIOB,
  180. settable: self
  181. ),
  182. Field(
  183. displayName: "Max Daily Safety Multiplier",
  184. keypath: \.maxDailySafetyMultiplier,
  185. value: preferences.maxDailySafetyMultiplier,
  186. settable: self
  187. ),
  188. Field(
  189. displayName: "Current Basal Safety Multiplier",
  190. keypath: \.currentBasalSafetyMultiplier,
  191. value: preferences.currentBasalSafetyMultiplier,
  192. settable: self
  193. ),
  194. Field(
  195. displayName: "Autosens Max",
  196. keypath: \.autosensMax,
  197. value: preferences.autosensMax,
  198. settable: self
  199. ),
  200. Field(
  201. displayName: "Autosens Min",
  202. keypath: \.autosensMin,
  203. value: preferences.autosensMin,
  204. settable: self
  205. ),
  206. Field(
  207. displayName: "Auto ISF Hourly Max Change",
  208. keypath: \.autoISFhourlyChange,
  209. value: preferences.autoISFhourlyChange,
  210. settable: self
  211. ),
  212. Field(
  213. displayName: "Auto ISF Max",
  214. keypath: \.autoISFmax,
  215. value: preferences.autoISFmax,
  216. settable: self
  217. ),
  218. Field(
  219. displayName: "SMB Max Range Extension",
  220. keypath: \.smbMaxRangeExtension,
  221. value: preferences.smbMaxRangeExtension,
  222. settable: self
  223. ),
  224. Field(
  225. displayName: "SMB Delivery Ratio",
  226. keypath: \.smbDeliveryRatio,
  227. value: preferences.smbDeliveryRatio,
  228. settable: self
  229. ),
  230. Field(
  231. displayName: "Half Basal Exercise Target",
  232. keypath: \.halfBasalExerciseTarget,
  233. value: preferences.halfBasalExerciseTarget,
  234. settable: self
  235. ),
  236. Field(
  237. displayName: "Max COB",
  238. keypath: \.maxCOB,
  239. value: preferences.maxCOB,
  240. settable: self
  241. ),
  242. Field(
  243. displayName: "Bolus Snooze DIA Divisor",
  244. keypath: \.bolusSnoozeDIADivisor,
  245. value: preferences.bolusSnoozeDIADivisor,
  246. settable: self
  247. ),
  248. Field(
  249. displayName: "Min 5m Carbimpact",
  250. keypath: \.min5mCarbimpact,
  251. value: preferences.min5mCarbimpact,
  252. settable: self
  253. ),
  254. Field(
  255. displayName: "Autotune ISF Adjustment Fraction",
  256. keypath: \.autotuneISFAdjustmentFraction,
  257. value: preferences.autotuneISFAdjustmentFraction,
  258. settable: self
  259. ),
  260. Field(
  261. displayName: "Remaining Carbs Fraction",
  262. keypath: \.remainingCarbsFraction,
  263. value: preferences.remainingCarbsFraction,
  264. settable: self
  265. ),
  266. Field(
  267. displayName: "Remaining Carbs Cap",
  268. keypath: \.remainingCarbsCap,
  269. value: preferences.remainingCarbsCap,
  270. settable: self
  271. ),
  272. Field(
  273. displayName: "Max SMB Basal Minutes",
  274. keypath: \.maxSMBBasalMinutes,
  275. value: preferences.maxSMBBasalMinutes,
  276. settable: self
  277. ),
  278. Field(
  279. displayName: "Max UAM SMB Basal Minutes",
  280. keypath: \.maxUAMSMBBasalMinutes,
  281. value: preferences.maxUAMSMBBasalMinutes,
  282. settable: self
  283. ),
  284. Field(
  285. displayName: "SMB Interval",
  286. keypath: \.smbInterval,
  287. value: preferences.smbInterval,
  288. settable: self
  289. ),
  290. Field(
  291. displayName: "Bolus Increment",
  292. keypath: \.bolusIncrement,
  293. value: preferences.bolusIncrement,
  294. settable: self
  295. ),
  296. Field(
  297. displayName: "Insulin Peak Time",
  298. keypath: \.insulinPeakTime,
  299. value: preferences.insulinPeakTime,
  300. settable: self
  301. ),
  302. Field(
  303. displayName: "Carbs Req Threshold",
  304. keypath: \.carbsReqThreshold,
  305. value: preferences.carbsReqThreshold,
  306. settable: self
  307. ),
  308. Field(
  309. displayName: "Noisy CGM Target Multiplier",
  310. keypath: \.noisyCGMTargetMultiplier,
  311. value: preferences.noisyCGMTargetMultiplier,
  312. settable: self
  313. )
  314. ]
  315. }
  316. func onSet<T>(_ keypath: WritableKeyPath<Preferences, T>, value: T) {
  317. preferences[keyPath: keypath] = value
  318. save()
  319. }
  320. func save() {
  321. provider.savePreferences(preferences)
  322. }
  323. }
  324. }