Преглед изворни кода

Merge branch 'dev' into fix-unlock-error

Sam King пре 1 година
родитељ
комит
4e9c5dc365

+ 1 - 1
Config.xcconfig

@@ -1,6 +1,6 @@
 APP_DISPLAY_NAME = Trio
 APP_DISPLAY_NAME = Trio
 APP_VERSION = 0.5.0
 APP_VERSION = 0.5.0
-APP_DEV_VERSION = 0.5.0.3
+APP_DEV_VERSION = 0.5.0.8
 APP_BUILD_NUMBER = 1
 APP_BUILD_NUMBER = 1
 COPYRIGHT_NOTICE =
 COPYRIGHT_NOTICE =
 DEVELOPER_TEAM = ##TEAM_ID##
 DEVELOPER_TEAM = ##TEAM_ID##

+ 7 - 3
Trio.xcodeproj/project.pbxproj

@@ -247,6 +247,7 @@
 		3B997DCB2DC00849006B6BB2 /* JSONImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B997DCA2DC00849006B6BB2 /* JSONImporter.swift */; };
 		3B997DCB2DC00849006B6BB2 /* JSONImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B997DCA2DC00849006B6BB2 /* JSONImporter.swift */; };
 		3B997DCF2DC00A3A006B6BB2 /* JSONImporterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B997DCE2DC00A3A006B6BB2 /* JSONImporterTests.swift */; };
 		3B997DCF2DC00A3A006B6BB2 /* JSONImporterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B997DCE2DC00A3A006B6BB2 /* JSONImporterTests.swift */; };
 		3B997DD32DC02AEF006B6BB2 /* glucose.json in Resources */ = {isa = PBXBuildFile; fileRef = 3B997DD12DC02AEF006B6BB2 /* glucose.json */; };
 		3B997DD32DC02AEF006B6BB2 /* glucose.json in Resources */ = {isa = PBXBuildFile; fileRef = 3B997DD12DC02AEF006B6BB2 /* glucose.json */; };
+		3BA8D1B32DDB87150006191F /* DecimalExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA8D1B22DDB870F0006191F /* DecimalExtensions.swift */; };
 		3BAD36B22D7CDC1A00CC298D /* MainLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */; };
 		3BAD36B22D7CDC1A00CC298D /* MainLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */; };
 		3BAD36CC2D7D420E00CC298D /* CoreDataInitializationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAD36CB2D7D420500CC298D /* CoreDataInitializationCoordinator.swift */; };
 		3BAD36CC2D7D420E00CC298D /* CoreDataInitializationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAD36CB2D7D420500CC298D /* CoreDataInitializationCoordinator.swift */; };
 		3BCA5F7C2DC7B16400A7EAC7 /* pumphistory-with-external.json in Resources */ = {isa = PBXBuildFile; fileRef = 3BCA5F7B2DC7B15400A7EAC7 /* pumphistory-with-external.json */; };
 		3BCA5F7C2DC7B16400A7EAC7 /* pumphistory-with-external.json in Resources */ = {isa = PBXBuildFile; fileRef = 3BCA5F7B2DC7B15400A7EAC7 /* pumphistory-with-external.json */; };
@@ -1056,6 +1057,7 @@
 		3B997DCA2DC00849006B6BB2 /* JSONImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONImporter.swift; sourceTree = "<group>"; };
 		3B997DCA2DC00849006B6BB2 /* JSONImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONImporter.swift; sourceTree = "<group>"; };
 		3B997DCE2DC00A3A006B6BB2 /* JSONImporterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONImporterTests.swift; sourceTree = "<group>"; };
 		3B997DCE2DC00A3A006B6BB2 /* JSONImporterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONImporterTests.swift; sourceTree = "<group>"; };
 		3B997DD12DC02AEF006B6BB2 /* glucose.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = glucose.json; sourceTree = "<group>"; };
 		3B997DD12DC02AEF006B6BB2 /* glucose.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = glucose.json; sourceTree = "<group>"; };
+		3BA8D1B22DDB870F0006191F /* DecimalExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecimalExtensions.swift; sourceTree = "<group>"; };
 		3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainLoadingView.swift; sourceTree = "<group>"; };
 		3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainLoadingView.swift; sourceTree = "<group>"; };
 		3BAD36CB2D7D420500CC298D /* CoreDataInitializationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataInitializationCoordinator.swift; sourceTree = "<group>"; };
 		3BAD36CB2D7D420500CC298D /* CoreDataInitializationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataInitializationCoordinator.swift; sourceTree = "<group>"; };
 		3BCA5F7B2DC7B15400A7EAC7 /* pumphistory-with-external.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "pumphistory-with-external.json"; sourceTree = "<group>"; };
 		3BCA5F7B2DC7B15400A7EAC7 /* pumphistory-with-external.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "pumphistory-with-external.json"; sourceTree = "<group>"; };
@@ -2442,13 +2444,14 @@
 		38A504F625DDA0E200C5B9E8 /* Extensions */ = {
 		38A504F625DDA0E200C5B9E8 /* Extensions */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				CE2FAD39297D93F0001A872C /* BloodGlucoseExtensions.swift */,
+				3BA8D1B22DDB870F0006191F /* DecimalExtensions.swift */,
 				DDB37CC62D05127500D99BF4 /* FontExtensions.swift */,
 				DDB37CC62D05127500D99BF4 /* FontExtensions.swift */,
-				38A5049125DD9C4000C5B9E8 /* UserDefaultsExtensions.swift */,
-				38BF021625E7CBBC00579895 /* PumpManagerExtensions.swift */,
 				CEB434E628B9053300B70274 /* LoopUIColorPalette+Default.swift */,
 				CEB434E628B9053300B70274 /* LoopUIColorPalette+Default.swift */,
 				CE48C86328CA69D5007C0598 /* OmniBLEPumpManagerExtensions.swift */,
 				CE48C86328CA69D5007C0598 /* OmniBLEPumpManagerExtensions.swift */,
 				CE48C86528CA6B48007C0598 /* OmniPodManagerExtensions.swift */,
 				CE48C86528CA6B48007C0598 /* OmniPodManagerExtensions.swift */,
-				CE2FAD39297D93F0001A872C /* BloodGlucoseExtensions.swift */,
+				38BF021625E7CBBC00579895 /* PumpManagerExtensions.swift */,
+				38A5049125DD9C4000C5B9E8 /* UserDefaultsExtensions.swift */,
 			);
 			);
 			path = Extensions;
 			path = Extensions;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -4535,6 +4538,7 @@
 				DDD163122C4C689900CD525A /* AdjustmentsStateModel.swift in Sources */,
 				DDD163122C4C689900CD525A /* AdjustmentsStateModel.swift in Sources */,
 				BD47FDD72D8B64D20043966B /* CarbRatioStepView.swift in Sources */,
 				BD47FDD72D8B64D20043966B /* CarbRatioStepView.swift in Sources */,
 				3B2F77862D7E52ED005ED9FA /* TDD.swift in Sources */,
 				3B2F77862D7E52ED005ED9FA /* TDD.swift in Sources */,
+				3BA8D1B32DDB87150006191F /* DecimalExtensions.swift in Sources */,
 				DD3F1F892D9E078D00DCE7B3 /* TherapySettingEditorView.swift in Sources */,
 				DD3F1F892D9E078D00DCE7B3 /* TherapySettingEditorView.swift in Sources */,
 				DD1745132C54169400211FAC /* DevicesView.swift in Sources */,
 				DD1745132C54169400211FAC /* DevicesView.swift in Sources */,
 				7F7B756BE8543965D9FDF1A2 /* DataTableDataFlow.swift in Sources */,
 				7F7B756BE8543965D9FDF1A2 /* DataTableDataFlow.swift in Sources */,

+ 7 - 0
Trio/Sources/APS/Extensions/DecimalExtensions.swift

@@ -0,0 +1,7 @@
+import Foundation
+
+extension Decimal {
+    func clamp(to pickerSetting: PickerSetting) -> Decimal {
+        max(min(self, pickerSetting.max), pickerSetting.min)
+    }
+}

+ 3 - 3
Trio/Sources/APS/FetchGlucoseManager.swift

@@ -11,7 +11,7 @@ protocol FetchGlucoseManager: SourceInfoProvider {
     func updateGlucoseSource(cgmGlucoseSourceType: CGMType, cgmGlucosePluginId: String, newManager: CGMManagerUI?)
     func updateGlucoseSource(cgmGlucoseSourceType: CGMType, cgmGlucosePluginId: String, newManager: CGMManagerUI?)
     func deleteGlucoseSource() async
     func deleteGlucoseSource() async
     func removeCalibrations()
     func removeCalibrations()
-    var glucoseSource: GlucoseSource! { get }
+    var glucoseSource: GlucoseSource? { get }
     var cgmManager: CGMManagerUI? { get }
     var cgmManager: CGMManagerUI? { get }
     var cgmGlucoseSourceType: CGMType { get set }
     var cgmGlucoseSourceType: CGMType { get set }
     var cgmGlucosePluginId: String { get }
     var cgmGlucosePluginId: String { get }
@@ -113,7 +113,7 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
         timer.resume()
         timer.resume()
     }
     }
 
 
-    var glucoseSource: GlucoseSource!
+    var glucoseSource: GlucoseSource?
 
 
     func removeCalibrations() {
     func removeCalibrations() {
         calibrationService.removeAllCalibrations()
         calibrationService.removeAllCalibrations()
@@ -286,7 +286,7 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
     }
     }
 
 
     func sourceInfo() -> [String: Any]? {
     func sourceInfo() -> [String: Any]? {
-        glucoseSource.sourceInfo()
+        glucoseSource?.sourceInfo()
     }
     }
 
 
     private func overcalibrate(entries: [BloodGlucose]) -> [BloodGlucose] {
     private func overcalibrate(entries: [BloodGlucose]) -> [BloodGlucose] {

+ 18 - 10
Trio/Sources/APS/Storage/CarbsStorage.swift

@@ -27,6 +27,8 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
 
 
     private let updateSubject = PassthroughSubject<Void, Never>()
     private let updateSubject = PassthroughSubject<Void, Never>()
 
 
+    private let settingsProvider = PickerSettingsProvider.shared
+
     var updatePublisher: AnyPublisher<Void, Never> {
     var updatePublisher: AnyPublisher<Void, Never> {
         updateSubject.eraseToAnyPublisher()
         updateSubject.eraseToAnyPublisher()
     }
     }
@@ -111,7 +113,7 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
 
 
      - Returns: The computed duration in hours.
      - Returns: The computed duration in hours.
      */
      */
-    private func calculateComputedDuration(fpus: Decimal, timeCap: Int) -> Int {
+    private func calculateComputedDuration(fpus: Decimal, timeCap: Decimal) -> Decimal {
         switch fpus {
         switch fpus {
         case ..<2:
         case ..<2:
             return 3
             return 3
@@ -145,22 +147,25 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
         createdAt: Date,
         createdAt: Date,
         actualDate: Date?
         actualDate: Date?
     ) -> ([CarbsEntry], Decimal) {
     ) -> ([CarbsEntry], Decimal) {
-        let interval = settings.settings.minuteInterval
-        let timeCap = settings.settings.timeCap
-        let adjustment = settings.settings.individualAdjustmentFactor
-        let delay = settings.settings.delay
+        let trioSettings = settings.settings
+        let providerSettings = settingsProvider.settings
+
+        let interval = trioSettings.minuteInterval.clamp(to: providerSettings.minuteInterval)
+        let timeCap = trioSettings.timeCap.clamp(to: providerSettings.timeCap)
+        let adjustment = trioSettings.individualAdjustmentFactor.clamp(to: providerSettings.individualAdjustmentFactor)
+        let delay = trioSettings.delay.clamp(to: providerSettings.delay)
 
 
         let kcal = protein * 4 + fat * 9
         let kcal = protein * 4 + fat * 9
         let carbEquivalents = (kcal / 10) * adjustment
         let carbEquivalents = (kcal / 10) * adjustment
         let fpus = carbEquivalents / 10
         let fpus = carbEquivalents / 10
         var computedDuration = calculateComputedDuration(fpus: fpus, timeCap: timeCap)
         var computedDuration = calculateComputedDuration(fpus: fpus, timeCap: timeCap)
 
 
-        var carbEquivalentSize: Decimal = carbEquivalents / Decimal(computedDuration)
-        carbEquivalentSize /= Decimal(60 / interval)
+        var carbEquivalentSize: Decimal = carbEquivalents / computedDuration
+        carbEquivalentSize /= Decimal(60) / interval
 
 
         if carbEquivalentSize < 1.0 {
         if carbEquivalentSize < 1.0 {
             carbEquivalentSize = 1.0
             carbEquivalentSize = 1.0
-            computedDuration = Int(carbEquivalents / carbEquivalentSize)
+            computedDuration = min(carbEquivalents / carbEquivalentSize, timeCap)
         }
         }
 
 
         let roundedEquivalent: Double = round(Double(carbEquivalentSize * 10)) / 10
         let roundedEquivalent: Double = round(Double(carbEquivalentSize * 10)) / 10
@@ -172,9 +177,12 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
         var futureCarbArray = [CarbsEntry]()
         var futureCarbArray = [CarbsEntry]()
         var firstIndex = true
         var firstIndex = true
 
 
+        // convert Decimal minutes to TimeInterval in seconds
+        let delayTimeInterval = TimeInterval(delay * 60)
+        let intervalTimeInterval = TimeInterval(interval * 60)
         while carbEquivalents > 0, numberOfEquivalents > 0 {
         while carbEquivalents > 0, numberOfEquivalents > 0 {
-            useDate = firstIndex ? useDate.addingTimeInterval(delay.minutes.timeInterval) : useDate
-                .addingTimeInterval(interval.minutes.timeInterval)
+            useDate = firstIndex ? useDate.addingTimeInterval(delayTimeInterval) : useDate
+                .addingTimeInterval(intervalTimeInterval)
             firstIndex = false
             firstIndex = false
 
 
             let eachCarbEntry = CarbsEntry(
             let eachCarbEntry = CarbsEntry(

+ 1 - 1
Trio/Sources/Models/DecimalPickerSettings.swift

@@ -131,7 +131,7 @@ struct DecimalPickerSettings {
     )
     )
     var threshold_setting = PickerSetting(value: 60, step: 1, min: 60, max: 120, type: PickerSetting.PickerSettingType.glucose)
     var threshold_setting = PickerSetting(value: 60, step: 1, min: 60, max: 120, type: PickerSetting.PickerSettingType.glucose)
     var updateInterval = PickerSetting(value: 20, step: 5, min: 1, max: 60, type: PickerSetting.PickerSettingType.minute)
     var updateInterval = PickerSetting(value: 20, step: 5, min: 1, max: 60, type: PickerSetting.PickerSettingType.minute)
-    var delay = PickerSetting(value: 60, step: 10, min: 60, max: 120, type: PickerSetting.PickerSettingType.minute)
+    var delay = PickerSetting(value: 60, step: 5, min: 15, max: 120, type: PickerSetting.PickerSettingType.minute)
     var minuteInterval = PickerSetting(value: 30, step: 5, min: 10, max: 60, type: PickerSetting.PickerSettingType.minute)
     var minuteInterval = PickerSetting(value: 30, step: 5, min: 10, max: 60, type: PickerSetting.PickerSettingType.minute)
     var timeCap = PickerSetting(value: 8, step: 1, min: 5, max: 12, type: PickerSetting.PickerSettingType.hour)
     var timeCap = PickerSetting(value: 8, step: 1, min: 5, max: 12, type: PickerSetting.PickerSettingType.hour)
     var hours = PickerSetting(value: 6, step: 0.5, min: 2, max: 24, type: PickerSetting.PickerSettingType.hour)
     var hours = PickerSetting(value: 6, step: 0.5, min: 2, max: 24, type: PickerSetting.PickerSettingType.hour)

+ 6 - 11
Trio/Sources/Models/TrioSettings.swift

@@ -42,15 +42,14 @@ struct TrioSettings: JSON, Equatable {
     var showCarbsRequiredBadge: Bool = true
     var showCarbsRequiredBadge: Bool = true
     var useFPUconversion: Bool = true
     var useFPUconversion: Bool = true
     var individualAdjustmentFactor: Decimal = 0.5
     var individualAdjustmentFactor: Decimal = 0.5
-    var timeCap: Int = 8
-    var minuteInterval: Int = 30
-    var delay: Int = 60
+    var timeCap: Decimal = 8
+    var minuteInterval: Decimal = 30
+    var delay: Decimal = 60
     var useAppleHealth: Bool = false
     var useAppleHealth: Bool = false
     var smoothGlucose: Bool = false
     var smoothGlucose: Bool = false
     var eA1cDisplayUnit: EstimatedA1cDisplayUnit = .percent
     var eA1cDisplayUnit: EstimatedA1cDisplayUnit = .percent
     var high: Decimal = 180
     var high: Decimal = 180
     var low: Decimal = 70
     var low: Decimal = 70
-    var hours: Int = 6
     var glucoseColorScheme: GlucoseColorScheme = .staticColor
     var glucoseColorScheme: GlucoseColorScheme = .staticColor
     var xGridLines: Bool = true
     var xGridLines: Bool = true
     var yGridLines: Bool = true
     var yGridLines: Bool = true
@@ -167,15 +166,15 @@ extension TrioSettings: Decodable {
             settings.overrideFactor = overrideFactor
             settings.overrideFactor = overrideFactor
         }
         }
 
 
-        if let timeCap = try? container.decode(Int.self, forKey: .timeCap) {
+        if let timeCap = try? container.decode(Decimal.self, forKey: .timeCap) {
             settings.timeCap = timeCap
             settings.timeCap = timeCap
         }
         }
 
 
-        if let minuteInterval = try? container.decode(Int.self, forKey: .minuteInterval) {
+        if let minuteInterval = try? container.decode(Decimal.self, forKey: .minuteInterval) {
             settings.minuteInterval = minuteInterval
             settings.minuteInterval = minuteInterval
         }
         }
 
 
-        if let delay = try? container.decode(Int.self, forKey: .delay) {
+        if let delay = try? container.decode(Decimal.self, forKey: .delay) {
             settings.delay = delay
             settings.delay = delay
         }
         }
 
 
@@ -237,10 +236,6 @@ extension TrioSettings: Decodable {
             settings.high = high
             settings.high = high
         }
         }
 
 
-        if let hours = try? container.decode(Int.self, forKey: .hours) {
-            settings.hours = hours
-        }
-
         if let glucoseColorScheme = try? container.decode(GlucoseColorScheme.self, forKey: .glucoseColorScheme) {
         if let glucoseColorScheme = try? container.decode(GlucoseColorScheme.self, forKey: .glucoseColorScheme) {
             settings.glucoseColorScheme = glucoseColorScheme
             settings.glucoseColorScheme = glucoseColorScheme
         }
         }

+ 3 - 1
Trio/Sources/Modules/ContactImage/View/AddContactImageSheet.swift

@@ -189,7 +189,9 @@ struct AddContactImageSheet: View {
             Button(action: {
             Button(action: {
                 saveNewEntry()
                 saveNewEntry()
             }, label: {
             }, label: {
-                Text("Save").padding(10)
+                Text("Save")
+                    .frame(maxWidth: .infinity, alignment: .center)
+                    .padding(10)
             })
             })
                 .frame(width: UIScreen.main.bounds.width * 0.9, alignment: .center)
                 .frame(width: UIScreen.main.bounds.width * 0.9, alignment: .center)
                 .background(Color(.systemBlue))
                 .background(Color(.systemBlue))

+ 3 - 1
Trio/Sources/Modules/ContactImage/View/ContactImageDetailView.swift

@@ -164,7 +164,9 @@ struct ContactImageDetailView: View {
             Button(action: {
             Button(action: {
                 saveChanges()
                 saveChanges()
             }, label: {
             }, label: {
-                Text("Save").padding(10)
+                Text("Save")
+                    .frame(maxWidth: .infinity, alignment: .center)
+                    .padding(10)
             })
             })
                 .frame(width: UIScreen.main.bounds.width * 0.9, alignment: .center)
                 .frame(width: UIScreen.main.bounds.width * 0.9, alignment: .center)
                 .background(isUnchanged ? Color(.systemGray4) : Color(.systemBlue))
                 .background(isUnchanged ? Color(.systemGray4) : Color(.systemBlue))

+ 18 - 1
Trio/Sources/Modules/Home/View/Header/PumpView.swift

@@ -16,6 +16,23 @@ struct PumpView: View {
         return formatter
         return formatter
     }
     }
 
 
+    private var hourglassIcon: String {
+        guard let expiration = expiresAtDate else { return "hourglass" }
+
+        let hoursRemaining = expiration.timeIntervalSince(timerDate) / 3600
+
+        switch hoursRemaining {
+        case 60 ... 72:
+            return "hourglass.bottomhalf.filled"
+        case 12 ..< 60:
+            return "hourglass"
+        case -8 ..< 12:
+            return "hourglass.tophalf.filled"
+        default:
+            return "hourglass"
+        }
+    }
+
     var body: some View {
     var body: some View {
         if let pumpStatusHighlightMessage = pumpStatusHighlightMessage { // display message instead pump info
         if let pumpStatusHighlightMessage = pumpStatusHighlightMessage { // display message instead pump info
             VStack(alignment: .center) {
             VStack(alignment: .center) {
@@ -80,7 +97,7 @@ struct PumpView: View {
 
 
                 if let date = expiresAtDate {
                 if let date = expiresAtDate {
                     HStack {
                     HStack {
-                        Image(systemName: "stopwatch.fill")
+                        Image(systemName: hourglassIcon)
                             .font(.callout)
                             .font(.callout)
                             .foregroundStyle(timerColor)
                             .foregroundStyle(timerColor)
 
 

+ 1 - 1
Trio/Sources/Modules/Home/View/HomeRootView.swift

@@ -177,7 +177,7 @@ extension Home {
                 )
                 )
             }
             }
 
 
-            return rateString + " " + String(localized: " U/hr", comment: "Unit per hour with space") + manualBasalString
+            return rateString + String(localized: " U/hr", comment: "Unit per hour with space") + manualBasalString
         }
         }
 
 
         var overrideString: String? {
         var overrideString: String? {

+ 13 - 24
Trio/Sources/Modules/MealSettings/MealSettingsStateModel.swift

@@ -16,36 +16,25 @@ extension MealSettings {
         override func subscribe() {
         override func subscribe() {
             units = settingsManager.settings.units
             units = settingsManager.settings.units
 
 
-            subscribeSetting(\.useFPUconversion, on: $useFPUconversion) { useFPUconversion = $0 }
             subscribeSetting(\.maxCarbs, on: $maxCarbs) { maxCarbs = $0 }
             subscribeSetting(\.maxCarbs, on: $maxCarbs) { maxCarbs = $0 }
             subscribeSetting(\.maxFat, on: $maxFat) { maxFat = $0 }
             subscribeSetting(\.maxFat, on: $maxFat) { maxFat = $0 }
             subscribeSetting(\.maxProtein, on: $maxProtein) { maxProtein = $0 }
             subscribeSetting(\.maxProtein, on: $maxProtein) { maxProtein = $0 }
 
 
-            subscribeSetting(\.timeCap, on: $timeCap.map(Int.init), initial: {
-                timeCap = Decimal($0)
-            }, map: {
-                $0
-            })
-
             subscribePreferencesSetting(\.maxMealAbsorptionTime, on: $maxMealAbsorptionTime) { maxMealAbsorptionTime = $0 }
             subscribePreferencesSetting(\.maxMealAbsorptionTime, on: $maxMealAbsorptionTime) { maxMealAbsorptionTime = $0 }
 
 
-            subscribeSetting(\.minuteInterval, on: $minuteInterval.map(Int.init), initial: {
-                minuteInterval = Decimal($0)
-            }, map: {
-                $0
-            })
-
-            subscribeSetting(\.delay, on: $delay.map(Int.init), initial: {
-                delay = Decimal($0)
-            }, map: {
-                $0
-            })
-
-            subscribeSetting(\.individualAdjustmentFactor, on: $individualAdjustmentFactor, initial: {
-                individualAdjustmentFactor = $0
-            }, map: {
-                $0
-            })
+            subscribeSetting(\.useFPUconversion, on: $useFPUconversion) { useFPUconversion = $0 }
+
+            // "Fat and Protein Delay"
+            subscribeSetting(\.delay, on: $delay) { delay = $0 }
+
+            // "Maximum Duration"
+            subscribeSetting(\.timeCap, on: $timeCap) { timeCap = $0 }
+
+            // "Spread Interval"
+            subscribeSetting(\.minuteInterval, on: $minuteInterval) { minuteInterval = $0 }
+
+            // "Fat and Protein Percentage"
+            subscribeSetting(\.individualAdjustmentFactor, on: $individualAdjustmentFactor) { individualAdjustmentFactor = $0 }
         }
         }
     }
     }
 }
 }

+ 47 - 14
Trio/Sources/Modules/Onboarding/OnboardingStateModel.swift

@@ -61,16 +61,12 @@ extension Onboarding {
                 return false
                 return false
             }
             }
 
 
-            debug(.default, "Checking for fresh install in \(documentsURL.path)...")
-
             let expectedLogsFolder = "logs"
             let expectedLogsFolder = "logs"
             let expectedPreferencesFile = OpenAPS.Settings.preferences
             let expectedPreferencesFile = OpenAPS.Settings.preferences
 
 
             do {
             do {
                 let contents = try fileManager.contentsOfDirectory(atPath: documentsURL.path)
                 let contents = try fileManager.contentsOfDirectory(atPath: documentsURL.path)
 
 
-                debug(.default, "Found \(contents) in \(documentsURL.path)...")
-
                 // Expect exactly 2 entries: "logs" and the preferences file
                 // Expect exactly 2 entries: "logs" and the preferences file
                 guard contents.count == 2 else {
                 guard contents.count == 2 else {
                     debug(.default, "Trio install is not fresh; returning user.")
                     debug(.default, "Trio install is not fresh; returning user.")
@@ -81,8 +77,6 @@ extension Onboarding {
                 let expectedSet = Set([expectedLogsFolder, expectedPreferencesFile])
                 let expectedSet = Set([expectedLogsFolder, expectedPreferencesFile])
                 let actualSet = Set(contents)
                 let actualSet = Set(contents)
 
 
-                debug(.default, "Expected: \(expectedSet), Actual: \(actualSet)")
-
                 let isFreshInstall = expectedSet == actualSet
                 let isFreshInstall = expectedSet == actualSet
                 debug(.default, "Trio install is fresh; new user.")
                 debug(.default, "Trio install is fresh; new user.")
 
 
@@ -258,10 +252,12 @@ extension Onboarding {
             isConnectingToNS = false
             isConnectingToNS = false
             isValidNightscoutURL = false
             isValidNightscoutURL = false
 
 
-            // Attempt to fetch existing units, therapy settings and delivery limits from file
-            units = settingsManager.settings.units
-            fetchExistingTherapySettingsFromFile()
-            fetchExistingDeliveryLimtisFromFile()
+            if !isFreshTrioInstall {
+                // Attempt to fetch existing units, therapy settings and delivery limits from file
+                units = settingsManager.settings.units
+                fetchExistingTherapySettingsFromFile()
+                fetchExistingDeliveryLimtisFromFile()
+            }
         }
         }
 
 
         // MARK: - Helpers
         // MARK: - Helpers
@@ -417,15 +413,16 @@ extension Onboarding {
         ///   - `units` from app settings.
         ///   - `units` from app settings.
         func fetchExistingDeliveryLimtisFromFile() {
         func fetchExistingDeliveryLimtisFromFile() {
             let pumpSettingsFromFile = provider.pumpSettingsFromFile
             let pumpSettingsFromFile = provider.pumpSettingsFromFile
+            let providedSettings = settingsProvider.settings
 
 
             if let pumpSettingsFromFile = pumpSettingsFromFile {
             if let pumpSettingsFromFile = pumpSettingsFromFile {
-                maxBolus = pumpSettingsFromFile.maxBolus
-                maxBasal = pumpSettingsFromFile.maxBasal
+                maxBolus = pumpSettingsFromFile.maxBolus.clamp(to: providedSettings.maxBolus)
+                maxBasal = pumpSettingsFromFile.maxBasal.clamp(to: providedSettings.maxBasal)
             }
             }
 
 
             let preferences = settingsManager.preferences
             let preferences = settingsManager.preferences
-            maxIOB = preferences.maxIOB
-            maxCOB = preferences.maxCOB
+            maxIOB = preferences.maxIOB.clamp(to: providedSettings.maxIOB)
+            maxCOB = preferences.maxCOB.clamp(to: providedSettings.maxCOB)
             minimumSafetyThreshold = preferences.threshold_setting
             minimumSafetyThreshold = preferences.threshold_setting
         }
         }
 
 
@@ -702,6 +699,30 @@ extension Onboarding {
         func applyToSettings() {
         func applyToSettings() {
             var settingsCopy = settingsManager.settings
             var settingsCopy = settingsManager.settings
             settingsCopy.units = units
             settingsCopy.units = units
+
+            // ensure existing values cannot exceed new guardrails
+            if !isFreshTrioInstall {
+                let providedSettings = settingsProvider.settings
+
+                settingsCopy.lowGlucose = settingsCopy.lowGlucose.clamp(to: providedSettings.lowGlucose)
+                settingsCopy.highGlucose = settingsCopy.highGlucose.clamp(to: providedSettings.highGlucose)
+                settingsCopy.carbsRequiredThreshold = settingsCopy.carbsRequiredThreshold
+                    .clamp(to: providedSettings.carbsRequiredThreshold)
+                settingsCopy.individualAdjustmentFactor = settingsCopy.individualAdjustmentFactor
+                    .clamp(to: providedSettings.individualAdjustmentFactor)
+                settingsCopy.timeCap = settingsCopy.timeCap.clamp(to: providedSettings.timeCap)
+                settingsCopy.minuteInterval = settingsCopy.minuteInterval.clamp(to: providedSettings.minuteInterval)
+                settingsCopy.delay = settingsCopy.delay.clamp(to: providedSettings.delay)
+                settingsCopy.high = settingsCopy.high.clamp(to: providedSettings.high)
+                settingsCopy.low = settingsCopy.low.clamp(to: providedSettings.low)
+                settingsCopy.maxCarbs = settingsCopy.maxCarbs.clamp(to: providedSettings.maxCarbs)
+                settingsCopy.maxFat = settingsCopy.maxFat.clamp(to: providedSettings.maxFat)
+                settingsCopy.maxProtein = settingsCopy.maxProtein.clamp(to: providedSettings.maxProtein)
+                settingsCopy.overrideFactor = settingsCopy.overrideFactor.clamp(to: providedSettings.overrideFactor)
+                settingsCopy.fattyMealFactor = settingsCopy.fattyMealFactor.clamp(to: providedSettings.fattyMealFactor)
+                settingsCopy.sweetMealFactor = settingsCopy.sweetMealFactor.clamp(to: providedSettings.sweetMealFactor)
+            }
+
             settingsManager.settings = settingsCopy
             settingsManager.settings = settingsCopy
         }
         }
 
 
@@ -744,6 +765,18 @@ extension Onboarding {
                 preferences.suspendZerosIOB = true
                 preferences.suspendZerosIOB = true
             }
             }
 
 
+            // ensure correct bolusIncrement is set, if user is onboarding with paired pump
+            if let pumpManager = apsManager?.pumpManager {
+                let bolusIncrement = Decimal(
+                    pumpManager.supportedBolusVolumes.first ??
+                        Double(
+                            settingsManager.preferences
+                                .bolusIncrement
+                        )
+                )
+                preferences.bolusIncrement = bolusIncrement != 0.025 ? bolusIncrement : 0.1
+            }
+
             settingsManager.preferences = preferences
             settingsManager.preferences = preferences
         }
         }