Просмотр исходного кода

Merge pull request #443 from nightscout/dev

v0.3.0 (16)
Mike Plante 1 год назад
Родитель
Сommit
3aaad8c7bd

+ 1 - 1
DanaKit

@@ -1 +1 @@
-Subproject commit 8628a2a67783113fedc6a5ccd4762ec59bbee4fe
+Subproject commit 200937c3c985de4cb05604cf1d7af2a307dfcaf3

+ 1 - 1
MinimedKit

@@ -1 +1 @@
-Subproject commit f11abde5e2eea2cbf7ac80f3f4bc4bc6e7f6de56
+Subproject commit ecd3588bdab3844617e17601ba2da1c28e786e77

+ 1 - 2
Trio/Sources/Application/TrioApp.swift

@@ -86,9 +86,8 @@ extension Notification.Name {
 
         debug(
             .default,
-            "Trio Started: v\(Bundle.main.releaseVersionNumber ?? "")(\(Bundle.main.buildVersionNumber ?? "")) [buildDate: \(String(describing: BuildDetails.shared.buildDate()))] [buildExpires: \(String(describing: BuildDetails.shared.calculateExpirationDate()))] [submodules: \(submodulesInfo)]"
+            "Trio Started: v\(Bundle.main.releaseVersionNumber ?? "")(\(Bundle.main.buildVersionNumber ?? "")) [buildDate: \(String(describing: BuildDetails.shared.buildDate()))] [buildExpires: \(String(describing: BuildDetails.shared.calculateExpirationDate()))] [Branch: \(BuildDetails.shared.branchAndSha)] [submodules: \(submodulesInfo)]"
         )
-
         // Fix bug in iOS 18 related to the translucent tab bar
         configureTabBarAppearance()
 

+ 9 - 3
Trio/Sources/Helpers/BuildDetails.swift

@@ -23,10 +23,16 @@ class BuildDetails: Injectable {
         dict["com-trio-build-date"] as? String
     }
 
+    var trioBranch: String {
+        dict["com-trio-branch"] as? String ?? String(localized: "Unknown")
+    }
+
+    var trioCommitSHA: String {
+        dict["com-trio-commit-sha"] as? String ?? String(localized: "Unknown")
+    }
+
     var branchAndSha: String {
-        let branch = dict["com-trio-branch"] as? String ?? String(localized: "Unknown")
-        let sha = dict["com-trio-commit-sha"] as? String ?? String(localized: "Unknown")
-        return "\(branch) \(sha)"
+        "\(trioBranch) \(trioCommitSHA)"
     }
 
     /// Returns a dictionary of submodule details.

Разница между файлами не показана из-за своего большого размера
+ 29816 - 6304
Trio/Sources/Localizations/Main/Localizable.xcstrings


+ 4 - 0
Trio/Sources/Modules/AlgorithmAdvancedSettings/AlgorithmAdvancedSettingsStateModel.swift

@@ -22,6 +22,8 @@ extension AlgorithmAdvancedSettings {
         @Published var remainingCarbsCap: Decimal = 90
         @Published var noisyCGMTargetMultiplier: Decimal = 1.3
         @Published var insulinActionCurve: Decimal = 10
+        @Published var smbDeliveryRatio: Decimal = 0.5
+        @Published var smbInterval: Decimal = 3
 
         var pumpSettings: PumpSettings {
             provider.settings()
@@ -45,6 +47,8 @@ extension AlgorithmAdvancedSettings {
             subscribePreferencesSetting(\.remainingCarbsCap, on: $remainingCarbsCap) { remainingCarbsCap = $0 }
             subscribePreferencesSetting(\.noisyCGMTargetMultiplier, on: $noisyCGMTargetMultiplier) {
                 noisyCGMTargetMultiplier = $0 }
+            subscribePreferencesSetting(\.smbDeliveryRatio, on: $smbDeliveryRatio) { smbDeliveryRatio = $0 }
+            subscribePreferencesSetting(\.smbInterval, on: $smbInterval) { smbInterval = $0 }
 
             insulinActionCurve = pumpSettings.insulinActionCurve
         }

+ 52 - 0
Trio/Sources/Modules/AlgorithmAdvancedSettings/View/AlgorithmAdvancedSettingsRootView.swift

@@ -251,6 +251,58 @@ extension AlgorithmAdvancedSettings {
                 )
 
                 SettingInputSection(
+                    decimalValue: $state.smbDeliveryRatio,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0.map { AnyView($0) }
+                            hintLabel = String(localized: "SMB Delivery Ratio", comment: "SMB Delivery Ratio")
+                        }
+                    ),
+                    units: state.units,
+                    type: .decimal("smbDeliveryRatio"),
+                    label: String(localized: "SMB Delivery Ratio", comment: "SMB Delivery Ratio"),
+                    miniHint: String(localized: "Percentage of calculated insulin required that is given as SMB."),
+                    verboseHint:
+                    VStack(alignment: .leading, spacing: 10) {
+                        Text("Default: 50%").bold()
+                        Text(
+                            "Once the total insulin required is calculated, this safety limit specifies what percentage of the insulin required can be delivered as an SMB."
+                        )
+                        Text(
+                            "Due to SMBs potentially occurring every 5 minutes with each loop cycle, it is important to set this value to a reasonable level that allows Trio to safely zero temp should dosing needs suddenly change. Increase this value with caution."
+                        )
+                        Text("Note: Allowed range is 30 - 70%")
+                    }
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.smbInterval,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0.map { AnyView($0) }
+                            hintLabel = String(localized: "SMB Interval", comment: "SMB Interval")
+                        }
+                    ),
+                    units: state.units,
+                    type: .decimal("smbInterval"),
+                    label: String(localized: "SMB Interval", comment: "SMB Interval"),
+                    miniHint: String(localized: "Minimum minutes since the last SMB or manual bolus to allow an automated SMB."),
+                    verboseHint:
+                    VStack(alignment: .leading, spacing: 10) {
+                        Text("Default: 3 min").bold()
+                        Text(
+                            "This is the minimum number of minutes since the last SMB or manual bolus before Trio will permit an automated SMB."
+                        )
+                    }
+                )
+
+                SettingInputSection(
                     decimalValue: $state.min5mCarbimpact,
                     booleanValue: $booleanPlaceholder,
                     shouldDisplayHint: $shouldDisplayHint,

+ 0 - 2
Trio/Sources/Modules/DynamicSettings/DynamicSettingsStateModel.swift

@@ -34,7 +34,6 @@ extension DynamicSettings {
         @Published var adjustmentFactorSigmoid: Decimal = 0.5
         @Published var weightPercentage: Decimal = 0.65
         @Published var tddAdjBasal: Bool = false
-        @Published var threshold_setting: Decimal = 60
 
         @ObservedObject var pickerSettingsProvider = PickerSettingsProvider.shared
 
@@ -58,7 +57,6 @@ extension DynamicSettings {
             subscribePreferencesSetting(\.adjustmentFactorSigmoid, on: $adjustmentFactorSigmoid) { adjustmentFactorSigmoid = $0 }
             subscribePreferencesSetting(\.weightPercentage, on: $weightPercentage) { weightPercentage = $0 }
             subscribePreferencesSetting(\.tddAdjBasal, on: $tddAdjBasal) { tddAdjBasal = $0 }
-            subscribePreferencesSetting(\.threshold_setting, on: $threshold_setting) { threshold_setting = $0 }
 
             Task {
                 do {

+ 0 - 47
Trio/Sources/Modules/DynamicSettings/View/DynamicSettingsRootView.swift

@@ -261,53 +261,6 @@ extension DynamicSettings {
                         },
                         headerText: String(localized: "Dynamic-dependent Features")
                     )
-
-                    SettingInputSection(
-                        decimalValue: $state.threshold_setting,
-                        booleanValue: $booleanPlaceholder,
-                        shouldDisplayHint: $shouldDisplayHint,
-                        selectedVerboseHint: Binding(
-                            get: { selectedVerboseHint },
-                            set: {
-                                selectedVerboseHint = $0.map { AnyView($0) }
-                                hintLabel = String(localized: "Minimum Safety Threshold")
-                            }
-                        ),
-                        units: state.units,
-                        type: .decimal("threshold_setting"),
-                        label: String(localized: "Minimum Safety Threshold"),
-                        miniHint: String(localized: "Increase the safety threshold used to suspend insulin delivery."),
-                        verboseHint:
-                        VStack(alignment: .leading, spacing: 10) {
-                            Text("Default: Set by Algorithm").bold()
-                            Text(
-                                "Minimum Threshold Setting is, by default, determined by your set Glucose Target. This threshold automatically suspends insulin delivery if your glucose levels are forecasted to fall below this value. It’s designed to protect against hypoglycemia, particularly during sleep or other vulnerable times."
-                            )
-                            Text(
-                                "Trio will use the larger of the default setting calculation below and the value entered here."
-                            )
-                            VStack(alignment: .leading, spacing: 10) {
-                                VStack(alignment: .leading, spacing: 5) {
-                                    Text("The default setting is based on this calculation:").bold()
-                                    Text("TargetGlucose - 0.5 × (TargetGlucose - 40)")
-                                }
-                                VStack(alignment: .leading, spacing: 5) {
-                                    Text(
-                                        "If your glucose target is \(state.units == .mgdL ? "110" : 110.formattedAsMmolL) \(state.units.rawValue), Trio will use a safety threshold of \(state.units == .mgdL ? "75" : 75.formattedAsMmolL) \(state.units.rawValue), unless you set Minimum Safety Threshold to something > \(state.units == .mgdL ? "75" : 75.formattedAsMmolL) \(state.units.rawValue)."
-                                    )
-                                    Text(
-                                        "\(state.units == .mgdL ? "110" : 110.formattedAsMmolL) - 0.5 × (\(state.units == .mgdL ? "110" : 110.formattedAsMmolL) - \(state.units == .mgdL ? "40" : 40.formattedAsMmolL)) = \(state.units == .mgdL ? "75" : 75.formattedAsMmolL)"
-                                    )
-                                }
-                                Text(
-                                    "This setting is limited to values between \(state.units == .mgdL ? "60" : 60.formattedAsMmolL) - \(state.units == .mgdL ? "120" : 120.formattedAsMmolL) \(state.units.rawValue)"
-                                )
-                                Text(
-                                    "Note: Basal may be resumed if there is negative IOB and glucose is rising faster than the forecast."
-                                )
-                            }
-                        }
-                    )
                 }
             }
             .listSectionSpacing(sectionSpacing)

+ 2 - 0
Trio/Sources/Modules/GeneralSettings/UnitsLimitsSettingsStateModel.swift

@@ -14,6 +14,7 @@ extension UnitsLimitsSettings {
         @Published var maxIOB: Decimal = 0
         @Published var maxCOB: Decimal = 120
         @Published var hasChanged: Bool = false
+        @Published var threshold_setting: Decimal = 60
 
         var preferences: Preferences {
             settingsManager.preferences
@@ -31,6 +32,7 @@ extension UnitsLimitsSettings {
 
             subscribePreferencesSetting(\.maxIOB, on: $maxIOB) { maxIOB = $0 }
             subscribePreferencesSetting(\.maxCOB, on: $maxCOB) { maxCOB = $0 }
+            subscribePreferencesSetting(\.threshold_setting, on: $threshold_setting) { threshold_setting = $0 }
 
             maxBasal = pumpSettings.maxBasal
             maxBolus = pumpSettings.maxBolus

+ 48 - 1
Trio/Sources/Modules/GeneralSettings/View/UnitsLimitsSettingsRootView.swift

@@ -80,7 +80,7 @@ extension UnitsLimitsSettings {
                     VStack(alignment: .leading, spacing: 10) {
                         Text("Default: 10 units").bold()
                         Text(
-                            "This is the maximum bolus allowed to be delivered at one time. This limits manual and automatic bolus."
+                            "This is the maximum bolus allowed to be delivered at one time. This only limits manual boluses and does not limit SMBs."
                         )
                         Text("Most set this to their largest meal bolus. Then, adjust if needed.")
                         Text("If you attempt to request a bolus larger than this, the bolus will not be accepted.")
@@ -141,6 +141,53 @@ extension UnitsLimitsSettings {
                         Text("This is an important limit when UAM is ON.")
                     }
                 )
+
+                SettingInputSection(
+                    decimalValue: $state.threshold_setting,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0.map { AnyView($0) }
+                            hintLabel = String(localized: "Minimum Safety Threshold")
+                        }
+                    ),
+                    units: state.units,
+                    type: .decimal("threshold_setting"),
+                    label: String(localized: "Minimum Safety Threshold"),
+                    miniHint: String(localized: "Increase the safety threshold used to suspend insulin delivery."),
+                    verboseHint:
+                    VStack(alignment: .leading, spacing: 10) {
+                        Text("Default: Set by Algorithm").bold()
+                        Text(
+                            "Minimum Threshold Setting is, by default, determined by your set Glucose Target. This threshold automatically suspends insulin delivery if your glucose levels are forecasted to fall below this value. It’s designed to protect against hypoglycemia, particularly during sleep or other vulnerable times."
+                        )
+                        Text(
+                            "Trio will use the larger of the default setting calculation below and the value entered here."
+                        )
+                        VStack(alignment: .leading, spacing: 10) {
+                            VStack(alignment: .leading, spacing: 5) {
+                                Text("The default setting is based on this calculation:").bold()
+                                Text("TargetGlucose - 0.5 × (TargetGlucose - 40)")
+                            }
+                            VStack(alignment: .leading, spacing: 5) {
+                                Text(
+                                    "If your glucose target is \(state.units == .mgdL ? "110" : 110.formattedAsMmolL) \(state.units.rawValue), Trio will use a safety threshold of \(state.units == .mgdL ? "75" : 75.formattedAsMmolL) \(state.units.rawValue), unless you set Minimum Safety Threshold to something > \(state.units == .mgdL ? "75" : 75.formattedAsMmolL) \(state.units.rawValue)."
+                                )
+                                Text(
+                                    "\(state.units == .mgdL ? "110" : 110.formattedAsMmolL) - 0.5 × (\(state.units == .mgdL ? "110" : 110.formattedAsMmolL) - \(state.units == .mgdL ? "40" : 40.formattedAsMmolL)) = \(state.units == .mgdL ? "75" : 75.formattedAsMmolL)"
+                                )
+                            }
+                            Text(
+                                "This setting is limited to values between \(state.units == .mgdL ? "60" : 60.formattedAsMmolL) - \(state.units == .mgdL ? "120" : 120.formattedAsMmolL) \(state.units.rawValue)"
+                            )
+                            Text(
+                                "Note: Basal may be resumed if there is negative IOB and glucose is rising faster than the forecast."
+                            )
+                        }
+                    }
+                )
             }
             .listSectionSpacing(sectionSpacing)
             .sheet(isPresented: $shouldDisplayHint) {

+ 1 - 2
Trio/Sources/Modules/Home/HomeStateModel+Setup/ChartAxisSetup.swift

@@ -93,9 +93,8 @@ extension Home.StateModel {
 
             // Ensure min and max IOB values exist, or set defaults
             if let minIob = minIob, let maxIob = maxIob {
-                let adjustedMin = minIob < 0 ? minIob - 2 : 0
                 Task {
-                    await self.updateIobChartBounds(minValue: adjustedMin, maxValue: maxIob + 2)
+                    await self.updateIobChartBounds(minValue: minIob, maxValue: maxIob)
                 }
             } else {
                 Task {

+ 16 - 5
Trio/Sources/Modules/Home/View/Chart/ChartElements/CobIobChart.swift

@@ -54,8 +54,10 @@ extension MainChartView {
     }
 
     func combinedYDomain() -> ClosedRange<Double> {
-        let minValue = min(state.minValueCobChart, state.minValueIobChart)
-        let maxValue = max(state.maxValueCobChart, state.maxValueIobChart)
+        let iobMin = scaleIobAmountForChart(state.minValueIobChart)
+        let iobMax = scaleIobAmountForChart(state.maxValueIobChart)
+        let minValue = min(state.minValueCobChart, iobMin)
+        let maxValue = max(state.maxValueCobChart, iobMax)
         return Double(minValue) ... Double(maxValue)
     }
 
@@ -79,6 +81,17 @@ extension MainChartView {
         .position(by: .value("Axis", axis))
     }
 
+    /// Scales IOB amounts for chart display.
+    ///
+    /// As IOB and COB share the same Y axis and COB is usually >> IOB,
+    /// we need to visually weigh IOB by multiplying it by a scaling factor:
+    ///
+    /// - Parameter rawAmount: The unscaled IOB amount
+    /// - Returns: The scaled IOB amount for visual representation
+    private func scaleIobAmountForChart<T: Numeric & Comparable>(_ rawAmount: T) -> T where T: ExpressibleByIntegerLiteral {
+        rawAmount > 0 ? rawAmount * 8 : rawAmount * 9
+    }
+
     func drawCOBIOBChart() -> some ChartContent {
         // Filter out duplicate entries by `deliverAt`,
         // We sometimes get two determinations when editing carbs, one without the entry-to-be-edited and then another one after editing the entry.
@@ -115,9 +128,7 @@ extension MainChartView {
             // MARK: - IOB line and area mark
 
             let rawAmount = item.iob?.doubleValue ?? 0
-
-            // as iob and cob share the same y axis and cob is usually >> iob we need to weigh iob visually
-            let amountIOB: Double = rawAmount > 0 ? rawAmount * 8 : rawAmount * 9
+            let amountIOB: Double = scaleIobAmountForChart(rawAmount)
 
             AreaMark(x: .value("Time", date), y: .value("Amount", amountIOB))
                 .foregroundStyle(by: .value("Type", "IOB"))

+ 0 - 4
Trio/Sources/Modules/SMBSettings/SMBSettingsStateModel.swift

@@ -17,8 +17,6 @@ extension SMBSettings {
         @Published var enableSMB_high_bg: Bool = false
         @Published var enableSMB_high_bg_target: Decimal = 100
         @Published var maxSMBBasalMinutes: Decimal = 30
-        @Published var smbDeliveryRatio: Decimal = 0.5
-        @Published var smbInterval: Decimal = 3
         @Published var bolusIncrement: Decimal = 0.1 // get this from pump, dafuq?: Bool = false
         @Published var enableUAM: Bool = false
         @Published var maxUAMSMBBasalMinutes: Decimal = 30
@@ -37,8 +35,6 @@ extension SMBSettings {
             subscribePreferencesSetting(\.enableSMB_high_bg_target, on: $enableSMB_high_bg_target) {
                 enableSMB_high_bg_target = $0 }
             subscribePreferencesSetting(\.maxSMBBasalMinutes, on: $maxSMBBasalMinutes) { maxSMBBasalMinutes = $0 }
-            subscribePreferencesSetting(\.smbDeliveryRatio, on: $smbDeliveryRatio) { smbDeliveryRatio = $0 }
-            subscribePreferencesSetting(\.smbInterval, on: $smbInterval) { smbInterval = $0 }
             subscribePreferencesSetting(\.bolusIncrement, on: $bolusIncrement) { bolusIncrement = $0 }
             subscribePreferencesSetting(\.enableUAM, on: $enableUAM) { enableUAM = $0 }
             subscribePreferencesSetting(\.maxUAMSMBBasalMinutes, on: $maxUAMSMBBasalMinutes) { maxUAMSMBBasalMinutes = $0 }

+ 0 - 52
Trio/Sources/Modules/SMBSettings/View/SMBSettingsRootView.swift

@@ -343,58 +343,6 @@ extension SMBSettings {
                         Text("Note: This setting has a hard-coded cap of 40%")
                     }
                 )
-
-                SettingInputSection(
-                    decimalValue: $state.smbDeliveryRatio,
-                    booleanValue: $booleanPlaceholder,
-                    shouldDisplayHint: $shouldDisplayHint,
-                    selectedVerboseHint: Binding(
-                        get: { selectedVerboseHint },
-                        set: {
-                            selectedVerboseHint = $0.map { AnyView($0) }
-                            hintLabel = String(localized: "SMB Delivery Ratio", comment: "SMB Delivery Ratio")
-                        }
-                    ),
-                    units: state.units,
-                    type: .decimal("smbDeliveryRatio"),
-                    label: String(localized: "SMB Delivery Ratio", comment: "SMB Delivery Ratio"),
-                    miniHint: String(localized: "Percentage of calculated insulin required that is given as SMB."),
-                    verboseHint:
-                    VStack(alignment: .leading, spacing: 10) {
-                        Text("Default: 50%").bold()
-                        Text(
-                            "Once the total insulin required is calculated, this safety limit specifies what percentage of the insulin required can be delivered as an SMB."
-                        )
-                        Text(
-                            "Due to SMBs potentially occurring every 5 minutes with each loop cycle, it is important to set this value to a reasonable level that allows Trio to safely zero temp should dosing needs suddenly change. Increase this value with caution."
-                        )
-                        Text("Note: Allowed range is 30 - 70%")
-                    }
-                )
-
-                SettingInputSection(
-                    decimalValue: $state.smbInterval,
-                    booleanValue: $booleanPlaceholder,
-                    shouldDisplayHint: $shouldDisplayHint,
-                    selectedVerboseHint: Binding(
-                        get: { selectedVerboseHint },
-                        set: {
-                            selectedVerboseHint = $0.map { AnyView($0) }
-                            hintLabel = String(localized: "SMB Interval", comment: "SMB Interval")
-                        }
-                    ),
-                    units: state.units,
-                    type: .decimal("smbInterval"),
-                    label: String(localized: "SMB Interval", comment: "SMB Interval"),
-                    miniHint: String(localized: "Minimum minutes since the last SMB or manual bolus to allow an automated SMB."),
-                    verboseHint:
-                    VStack(alignment: .leading, spacing: 10) {
-                        Text("Default: 3 min").bold()
-                        Text(
-                            "This is the minimum number of minutes since the last SMB or manual bolus before Trio will permit an automated SMB."
-                        )
-                    }
-                )
             }
             .listSectionSpacing(sectionSpacing)
             .sheet(isPresented: $shouldDisplayHint) {

+ 12 - 10
Trio/Sources/Modules/Settings/SettingItems.swift

@@ -65,7 +65,7 @@ enum SettingItems {
         SettingItem(
             title: "Units and Limits",
             view: .unitsAndLimits,
-            searchContents: ["Glucose Units", "Max Basal", "Max Bolus", "Max IOB", "Max COB"],
+            searchContents: ["Glucose Units", "Max Basal", "Max Bolus", "Max IOB", "Max COB", "Minimum Safety Threshold"],
             path: ["Therapy Settings", "Units and Limits"]
         ),
         SettingItem(title: "Basal Rates", view: .basalProfileEditor, path: ["Therapy Settings"]),
@@ -97,9 +97,7 @@ enum SettingItems {
                 "Enable UAM",
                 "Max SMB Basal Minutes",
                 "Max UAM SMB Basal Minutes",
-                "Max Delta-BG Threshold SMB",
-                "SMB Delivery Ratio",
-                "SMB Interval"
+                "Max Delta-BG Threshold SMB"
             ],
             path: ["Algorithm", "Super Micro Bolus (SMB)"]
         ),
@@ -114,8 +112,7 @@ enum SettingItems {
                 "AF",
                 "Sigmoid Adjustment Factor",
                 "Weighted Average of TDD",
-                "Adjust Basal",
-                "Minimum Safety Threshold"
+                "Adjust Basal"
             ],
             path: ["Algorithm", "Dynamic Sensitivity"]
         ),
@@ -143,6 +140,8 @@ enum SettingItems {
                 "Skip Neutral Temps",
                 "Unsuspend If No Temp",
                 "Suspend Zeros IOB",
+                "SMB Delivery Ratio",
+                "SMB Interval",
                 "Min 5m Carbimpact",
                 "Remaining Carbs Fraction",
                 "Remaining Carbs Cap",
@@ -162,7 +161,8 @@ enum SettingItems {
                 "Enable Fatty Meal Factor",
                 "Fatty Meal Factor",
                 "Enable Super Bolus",
-                "Super Bolus Factor"
+                "Super Bolus Factor",
+                "Very Low Glucose Warning"
             ],
             path: ["Features", "Bolus Calculator"]
         ),
@@ -205,8 +205,7 @@ enum SettingItems {
                 "Low Threshold",
                 "High Threshold",
                 "X-Axis Interval Step",
-                "Override eA1c Unit",
-                "Standing / Laying TIR Chart",
+                "eA1c/GMI Display Unit",
                 "Show Carbs Required Badge",
                 "Carbs Required Threshold",
                 "Forecast Display Type",
@@ -217,7 +216,10 @@ enum SettingItems {
                 "Appearance",
                 "Dark Scheme",
                 "Light Scheme",
-                "Glucose Color Scheme"
+                "Glucose Color Scheme",
+                "Time in Range Type",
+                "Time in Tight Range (TITR)",
+                "Time in Normoglycemia (TING)"
             ],
             path: ["Features", "User Interface"]
         ),

+ 4 - 1
Trio/Sources/Modules/Settings/View/Subviews/SubmodulesView.swift

@@ -5,7 +5,10 @@ struct SubmodulesView: View {
 
     var body: some View {
         List {
-            Section {
+            Section(header: Text("Trio")) {
+                KeyValueRow(key: buildDetails.trioBranch, value: buildDetails.trioCommitSHA)
+            }
+            Section(header: Text("Submodules")) {
                 ForEach(buildDetails.submodules.sorted(by: { $0.key < $1.key }), id: \.key) { name, info in
                     KeyValueRow(key: name, value: info.commitSHA)
                 }

+ 16 - 6
Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift

@@ -458,9 +458,14 @@ extension UserInterfaceSettings {
                                                         "Time in Tight Range (TITR):"
                                                     )
                                                     .bold()
-                                                    Text(
-                                                        "Uses the fairly established Time in Tight Range definition, which is defined as time between \(state.units == .mgdL ? Decimal(70) : 70.asMmolL) and \(state.units == .mgdL ? Decimal(140) : 140.asMmolL) \(state.units.rawValue)."
-                                                    )
+                                                    let titrBottomThreshold =
+                                                        "\(state.units == .mgdL ? Decimal(70) : 70.asMmolL)"
+                                                    let titrTopThreshold =
+                                                        "\(state.units == .mgdL ? Decimal(140) : 140.asMmolL)"
+                                                    Text(String(
+                                                        localized: "Uses the fairly established Time in Tight Range definition, which is defined as time between \(titrBottomThreshold) and \(titrTopThreshold)  \(state.units.rawValue).",
+                                                        comment: "Time in Tight Range (TITR) verbose hint description"
+                                                    ))
                                                 }
                                                 VStack(
                                                     alignment: .leading,
@@ -470,9 +475,14 @@ extension UserInterfaceSettings {
                                                         "Time in Normoglycemia (TING):"
                                                     )
                                                     .bold()
-                                                    Text(
-                                                        "Uses the very new – first discussed at ATTD 2025 in Amsterdam, NL – Time in Normoglycemia definition, which adopts its range as all values between the normoglycemic minimum threshold (\(state.units == .mgdL ? Decimal(63) : 63.asMmolL) \(state.units.rawValue)) and \(state.units == .mgdL ? Decimal(140) : 140.asMmolL) \(state.units.rawValue)."
-                                                    )
+                                                    let tingBottomThreshold =
+                                                        "\(state.units == .mgdL ? Decimal(63) : 63.asMmolL)"
+                                                    let tingTopThreshold =
+                                                        "\(state.units == .mgdL ? Decimal(140) : 140.asMmolL)"
+                                                    Text(String(
+                                                        localized: "Uses the very new – first discussed at ATTD 2025 in Amsterdam, NL – Time in Normoglycemia definition, which adopts its range as all values between the normoglycemic minimum threshold (\(tingBottomThreshold) \(state.units.rawValue)) and \(tingTopThreshold) \(state.units.rawValue).",
+                                                        comment: "Time in Normoglycemia (TING) verbose hint description"
+                                                    ))
                                                 }
                                             }
                                         )