From 08fafb2519c377b6e83beece9e29787186bd81cd Mon Sep 17 00:00:00 2001 From: munchyk <55564308+munchyk@users.noreply.github.com> Date: Sat, 19 Sep 2026 18:01:28 -0400 Subject: [PATCH 01/41] New clearer terminology for TIR and its lower threshold --- .../Localizations/Main/Localizable.xcstrings | 143 ++++++++++++++++++ Trio/Sources/Models/TimeInRangeType.swift | 8 +- .../Modules/Settings/SettingItems.swift | 10 +- .../SettingsExportStateModel.swift | 4 +- .../Glucose/GlucosePercentileChart.swift | 2 +- .../Glucose/GlucoseSectorChart.swift | 10 +- .../View/UserInterfaceSettingsRootView.swift | 49 +++--- TrioTests/SettingsSearchTests.swift | 9 ++ 8 files changed, 194 insertions(+), 41 deletions(-) diff --git a/Trio/Sources/Localizations/Main/Localizable.xcstrings b/Trio/Sources/Localizations/Main/Localizable.xcstrings index c8deedfb12..851e91d673 100644 --- a/Trio/Sources/Localizations/Main/Localizable.xcstrings +++ b/Trio/Sources/Localizations/Main/Localizable.xcstrings @@ -1089,6 +1089,149 @@ } } }, + "Choose the preferred lower threshold for Time in Range statistics." : { + "comment" : "Short description of the lower range threshold setting.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Choose the preferred lower threshold for Time in Range statistics." + } + } + } + }, + "Choose the preferred lower threshold used for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR) with an upper threshold of %@, and Time in Tight Range (TITR) with an upper threshold of %@." : { + "comment" : "Explains that the lower threshold applies to both TIR and TITR. Placeholders are the upper thresholds including units.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Choose the preferred lower threshold used for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR) with an upper threshold of %@, and Time in Tight Range (TITR) with an upper threshold of %@." + } + } + } + }, + "Extended (%@)" : { + "comment" : "Extended lower threshold for TIR and TITR statistics; placeholder includes glucose value and units.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Extended (%@)" + } + } + } + }, + "Extended Lower Threshold" : { + "comment" : "Search term for the extended lower range threshold setting.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Extended Lower Threshold" + } + } + } + }, + "Extended:" : { + "comment" : "Heading for the extended lower range threshold description.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Extended:" + } + } + } + }, + "Lower Range Threshold" : { + "comment" : "Setting for the lower glucose boundary shared by TIR and TITR statistics.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lower Range Threshold" + } + } + } + }, + "Standard (%@)" : { + "comment" : "Standard lower threshold for TIR and TITR statistics; placeholder includes glucose value and units.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standard (%@)" + } + } + } + }, + "Standard Lower Threshold" : { + "comment" : "Search term for the standard lower range threshold setting.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standard Lower Threshold" + } + } + } + }, + "Standard:" : { + "comment" : "Heading for the standard lower range threshold description.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standard:" + } + } + } + }, + "TIR (%@-%@)" : { + "comment" : "Time in Range with the selected lower threshold and the upper threshold.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TIR (%@-%@)" + } + } + } + }, + "TITR (%@-%@)" : { + "comment" : "Time in Tight Range with either the Standard or Extended lower threshold.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TITR (%@-%@)" + } + } + } + }, + "Uses the established lower threshold of %@." : { + "comment" : "Standard lower range threshold description; placeholder includes glucose value and units.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uses the established lower threshold of %@." + } + } + } + }, + "Uses the newer Time in Normoglycemia (TING) lower threshold of %@." : { + "comment" : "Extended lower range threshold description; placeholder includes glucose value and units.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uses the newer Time in Normoglycemia (TING) lower threshold of %@." + } + } + } + }, " " : { "localizations" : { "bg" : { diff --git a/Trio/Sources/Models/TimeInRangeType.swift b/Trio/Sources/Models/TimeInRangeType.swift index eb5c45c928..b1f4f46df1 100644 --- a/Trio/Sources/Models/TimeInRangeType.swift +++ b/Trio/Sources/Models/TimeInRangeType.swift @@ -1,17 +1,19 @@ import Foundation +// Keep legacy case names for saved settings compatibility. enum TimeInRangeType: String, JSON, CaseIterable, Identifiable, Codable, Hashable { var id: String { rawValue } case timeInTightRange case timeInNormoglycemia - var displayName: String { + func displayName(for units: GlucoseUnits) -> String { + let threshold = bottomThreshold.formatted(withUnits: units) switch self { case .timeInTightRange: - return String(localized: "Time in Tight Range (TITR)", comment: "") + return String(localized: "Standard (\(threshold))", comment: "Standard lower threshold for TIR and TITR statistics") case .timeInNormoglycemia: - return String(localized: "Time in Normoglycemia (TING)", comment: "") + return String(localized: "Extended (\(threshold))", comment: "Extended lower threshold for TIR and TITR statistics") } } diff --git a/Trio/Sources/Modules/Settings/SettingItems.swift b/Trio/Sources/Modules/Settings/SettingItems.swift index 8c0d27a296..0c78cb796e 100644 --- a/Trio/Sources/Modules/Settings/SettingItems.swift +++ b/Trio/Sources/Modules/Settings/SettingItems.swift @@ -289,6 +289,9 @@ enum SettingItems { "Dark Scheme", "Light Scheme", "Glucose Color Scheme", + "Lower Range Threshold", + "Standard Lower Threshold", + "Extended Lower Threshold", "Time in Range Type", "Time in Tight Range (TITR)", "Time in Normoglycemia (TING)", @@ -302,8 +305,11 @@ enum SettingItems { "Lines": "Forecast Display Type", "Dark Mode": "Appearance", "Light Mode": "Appearance", - "Time in Tight Range (TITR)": "Time in Range Type", - "Time in Normoglycemia (TING)": "Time in Range Type", + "Standard Lower Threshold": "Lower Range Threshold", + "Extended Lower Threshold": "Lower Range Threshold", + "Time in Range Type": "Lower Range Threshold", + "Time in Tight Range (TITR)": "Lower Range Threshold", + "Time in Normoglycemia (TING)": "Lower Range Threshold", "Dark Scheme": "Appearance", "Light Scheme": "Appearance", "X-Axis Interval Step": "Show X-Axis Grid Lines", diff --git a/Trio/Sources/Modules/SettingsExport/SettingsExportStateModel.swift b/Trio/Sources/Modules/SettingsExport/SettingsExportStateModel.swift index 80e1456b94..91269ec3fc 100644 --- a/Trio/Sources/Modules/SettingsExport/SettingsExportStateModel.swift +++ b/Trio/Sources/Modules/SettingsExport/SettingsExportStateModel.swift @@ -837,8 +837,8 @@ extension SettingsExport { addSetting( category: featuresCategory, subcategory: userInterfaceSubcategory, - name: String(localized: "Time in Range Type"), - value: trioSettings.timeInRangeType.rawValue + name: String(localized: "Lower Range Threshold"), + value: trioSettings.timeInRangeType.displayName(for: trioSettings.units) ) addSetting( category: featuresCategory, diff --git a/Trio/Sources/Modules/Stat/View/ViewElements/Glucose/GlucosePercentileChart.swift b/Trio/Sources/Modules/Stat/View/ViewElements/Glucose/GlucosePercentileChart.swift index 3c32464a84..a1cd190649 100644 --- a/Trio/Sources/Modules/Stat/View/ViewElements/Glucose/GlucosePercentileChart.swift +++ b/Trio/Sources/Modules/Stat/View/ViewElements/Glucose/GlucosePercentileChart.swift @@ -11,7 +11,7 @@ struct GlucosePercentileChart: View { let glucose: [GlucoseStored] /// The upper glucose limit for the chart. let highLimit: Decimal - /// TITR or TING + /// Lower threshold for TIR and TITR. let timeInRangeType: TimeInRangeType /// The units used for glucose measurement (mg/dL or mmol/L). let units: GlucoseUnits diff --git a/Trio/Sources/Modules/Stat/View/ViewElements/Glucose/GlucoseSectorChart.swift b/Trio/Sources/Modules/Stat/View/ViewElements/Glucose/GlucoseSectorChart.swift index dbeb06da4e..84c37050d8 100644 --- a/Trio/Sources/Modules/Stat/View/ViewElements/Glucose/GlucoseSectorChart.swift +++ b/Trio/Sources/Modules/Stat/View/ViewElements/Glucose/GlucoseSectorChart.swift @@ -32,13 +32,13 @@ struct GlucoseSectorChart: View { let total = Decimal(glucose.count) // Count readings greater than high limit (180 mg/dL) let high = glucose.filter { $0.glucose > Int(highLimit) }.count - // Count readings between low limit (TITR: 70 mg/dL, TING 63 mg/dL) and 140 mg/dL (tight control) + // TITR: selected lower threshold to 140 mg/dL. let tight = glucose .filter { $0.glucose >= timeInRangeType.bottomThreshold && $0.glucose <= timeInRangeType.topThreshold }.count - // Count readings between 140 and high limit (normal range) + // TIR: selected lower threshold to 180 mg/dL. let normal = glucose.filter { $0.glucose >= timeInRangeType.bottomThreshold && $0.glucose <= Int(highLimit) } .count - // Count readings less than low limit (low) (70 mg/dL if not showing chart, otherwise 70 for TITR and 63 for TING) + // Daily details retain a fixed below-70 measure. let low = glucose.filter { $0.glucose < (showChart ? Int(timeInRangeType.bottomThreshold) : 70) }.count // Count readings less than moderately low limit (63 mg/dL) let moderatelyLow = glucose.filter { $0.glucose < 63 }.count @@ -310,13 +310,13 @@ struct GlucoseSectorChart: View { items: [ ( String( - localized: "Normal (\(Decimal(timeInRangeType.bottomThreshold).formatted(for: units))-\(highLimit.formatted(for: units)))" + localized: "TIR (\(Decimal(timeInRangeType.bottomThreshold).formatted(for: units))-\(highLimit.formatted(for: units)))" ), formatPercentage(Decimal(glucoseValues.count) / total * 100) ), ( String( - localized: "\(timeInRangeType == .timeInTightRange ? "TITR" : "TING") (\(Decimal(timeInRangeType.bottomThreshold).formatted(for: units))-\(Decimal(timeInRangeType.topThreshold).formatted(for: units)))" + localized: "TITR (\(Decimal(timeInRangeType.bottomThreshold).formatted(for: units))-\(Decimal(timeInRangeType.topThreshold).formatted(for: units)))" ), formatPercentage(Decimal(tight) / total * 100) ), diff --git a/Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift b/Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift index dcace837d3..96887310b5 100644 --- a/Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift +++ b/Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift @@ -509,16 +509,16 @@ extension UserInterfaceSettings { VStack(alignment: .leading) { Picker( selection: $state.timeInRangeType, - label: Text("Time in Range Type").multilineTextAlignment(.leading) + label: Text("Lower Range Threshold").multilineTextAlignment(.leading) ) { ForEach(TimeInRangeType.allCases) { selection in - Text(selection.displayName).tag(selection) + Text(selection.displayName(for: state.units)).tag(selection) } }.padding(.top) HStack(alignment: .center) { Text( - "Choose type of time in range to be used for Trio's statistics." + "Choose the preferred lower threshold for Time in Range statistics." ) .font(.footnote) .foregroundColor(.secondary) @@ -526,48 +526,41 @@ extension UserInterfaceSettings { Spacer() Button( action: { - hintLabel = String(localized: "Time in Range Type") + hintLabel = String(localized: "Lower Range Threshold") selectedVerboseHint = AnyView( VStack( alignment: .leading, spacing: 10 ) { - Text( - "Choose which type of time in range Trio should adopt for all its statistical charts and displays:" - ) + let tirUpperThreshold = 180.formatted(withUnits: state.units) + let titrUpperThreshold = 140.formatted(withUnits: state.units) + Text(String( + localized: "Choose the preferred lower threshold used for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR) with an upper threshold of \(tirUpperThreshold), and Time in Tight Range (TITR) with an upper threshold of \(titrUpperThreshold).", + comment: "Explains that the lower threshold applies to both TIR and TITR" + )) VStack( alignment: .leading, spacing: 5 ) { - Text( - "Time in Tight Range (TITR):" - ) - .bold() - let titrBottomThreshold = - "\(state.units == .mgdL ? Decimal(70) : 70.asMmolL)" - let titrTopThreshold = - "\(state.units == .mgdL ? Decimal(140) : 140.asMmolL)" + Text("Standard:").bold() + let standardLowerThreshold = TimeInRangeType.timeInTightRange + .bottomThreshold.formatted(withUnits: state.units) 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" + localized: "Uses the established lower threshold of \(standardLowerThreshold).", + comment: "Standard lower range threshold description" )) } VStack( alignment: .leading, spacing: 5 ) { - Text( - "Time in Normoglycemia (TING):" - ) - .bold() - let tingBottomThreshold = - "\(state.units == .mgdL ? Decimal(63) : 63.asMmolL)" - let tingTopThreshold = - "\(state.units == .mgdL ? Decimal(140) : 140.asMmolL)" + Text("Extended:").bold() + let extendedLowerThreshold = TimeInRangeType.timeInNormoglycemia + .bottomThreshold.formatted(withUnits: state.units) 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" + localized: "Uses the newer Time in Normoglycemia (TING) lower threshold of \(extendedLowerThreshold).", + comment: "Extended lower range threshold description" )) } } @@ -582,7 +575,7 @@ extension UserInterfaceSettings { ).buttonStyle(BorderlessButtonStyle()) }.padding(.top) }.padding(.bottom) - }.settingsSearchTarget(label: String(localized: "Time in Range Type")) + }.settingsSearchTarget(label: String(localized: "Lower Range Threshold")) Section { VStack(alignment: .leading) { diff --git a/TrioTests/SettingsSearchTests.swift b/TrioTests/SettingsSearchTests.swift index db2c1420e6..2ebf789f8f 100644 --- a/TrioTests/SettingsSearchTests.swift +++ b/TrioTests/SettingsSearchTests.swift @@ -3,6 +3,15 @@ import Testing @testable import Trio @Suite("Settings Search Navigation") struct SettingsSearchTests { + @Test("Lower threshold names and legacy aliases navigate to the renamed setting") func searchLowerRangeThreshold() { + for query in ["Lower Range Threshold", "Standard", "Extended", "Time in Range Type", "TITR", "TING"] { + let results = SettingItems.filteredItems(searchText: query) + #expect(results.contains { + $0.settingItem.view == .userInterfaceSettings && $0.scrollLabel == "Lower Range Threshold" + }, "No lower threshold search target for \(query)") + } + } + @Test("Searching 'Dynamic ISF' finds the Dynamic Settings screen") func searchDynamicISF() { let results = SettingItems.filteredItems(searchText: "Dynamic ISF") #expect(!results.isEmpty) From cd99c253a4002e0a9c0473bbcedca2b0034475c4 Mon Sep 17 00:00:00 2001 From: munchyk <55564308+munchyk@users.noreply.github.com> Date: Thu, 24 Sep 2026 19:32:17 -0400 Subject: [PATCH 02/41] Rename TIR Lower Threshold and refine help text --- .../Sources/Localizations/Main/Localizable.xcstrings | 8 ++++---- Trio/Sources/Modules/Settings/SettingItems.swift | 12 ++++++------ .../SettingsExport/SettingsExportStateModel.swift | 2 +- .../View/UserInterfaceSettingsRootView.swift | 8 ++++---- TrioTests/SettingsSearchTests.swift | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Trio/Sources/Localizations/Main/Localizable.xcstrings b/Trio/Sources/Localizations/Main/Localizable.xcstrings index 851e91d673..6db8f51837 100644 --- a/Trio/Sources/Localizations/Main/Localizable.xcstrings +++ b/Trio/Sources/Localizations/Main/Localizable.xcstrings @@ -1100,13 +1100,13 @@ } } }, - "Choose the preferred lower threshold used for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR) with an upper threshold of %@, and Time in Tight Range (TITR) with an upper threshold of %@." : { + "Choose the preferred lower threshold for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR, upper threshold of %@) and Time in Tight Range (TITR, upper threshold of %@)." : { "comment" : "Explains that the lower threshold applies to both TIR and TITR. Placeholders are the upper thresholds including units.", "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "Choose the preferred lower threshold used for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR) with an upper threshold of %@, and Time in Tight Range (TITR) with an upper threshold of %@." + "value" : "Choose the preferred lower threshold for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR, upper threshold of %@) and Time in Tight Range (TITR, upper threshold of %@)." } } } @@ -1144,13 +1144,13 @@ } } }, - "Lower Range Threshold" : { + "TIR Lower Threshold" : { "comment" : "Setting for the lower glucose boundary shared by TIR and TITR statistics.", "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "Lower Range Threshold" + "value" : "TIR Lower Threshold" } } } diff --git a/Trio/Sources/Modules/Settings/SettingItems.swift b/Trio/Sources/Modules/Settings/SettingItems.swift index 0c78cb796e..7c4b0ec133 100644 --- a/Trio/Sources/Modules/Settings/SettingItems.swift +++ b/Trio/Sources/Modules/Settings/SettingItems.swift @@ -289,7 +289,7 @@ enum SettingItems { "Dark Scheme", "Light Scheme", "Glucose Color Scheme", - "Lower Range Threshold", + "TIR Lower Threshold", "Standard Lower Threshold", "Extended Lower Threshold", "Time in Range Type", @@ -305,11 +305,11 @@ enum SettingItems { "Lines": "Forecast Display Type", "Dark Mode": "Appearance", "Light Mode": "Appearance", - "Standard Lower Threshold": "Lower Range Threshold", - "Extended Lower Threshold": "Lower Range Threshold", - "Time in Range Type": "Lower Range Threshold", - "Time in Tight Range (TITR)": "Lower Range Threshold", - "Time in Normoglycemia (TING)": "Lower Range Threshold", + "Standard Lower Threshold": "TIR Lower Threshold", + "Extended Lower Threshold": "TIR Lower Threshold", + "Time in Range Type": "TIR Lower Threshold", + "Time in Tight Range (TITR)": "TIR Lower Threshold", + "Time in Normoglycemia (TING)": "TIR Lower Threshold", "Dark Scheme": "Appearance", "Light Scheme": "Appearance", "X-Axis Interval Step": "Show X-Axis Grid Lines", diff --git a/Trio/Sources/Modules/SettingsExport/SettingsExportStateModel.swift b/Trio/Sources/Modules/SettingsExport/SettingsExportStateModel.swift index 91269ec3fc..c710c614b3 100644 --- a/Trio/Sources/Modules/SettingsExport/SettingsExportStateModel.swift +++ b/Trio/Sources/Modules/SettingsExport/SettingsExportStateModel.swift @@ -837,7 +837,7 @@ extension SettingsExport { addSetting( category: featuresCategory, subcategory: userInterfaceSubcategory, - name: String(localized: "Lower Range Threshold"), + name: String(localized: "TIR Lower Threshold"), value: trioSettings.timeInRangeType.displayName(for: trioSettings.units) ) addSetting( diff --git a/Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift b/Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift index 96887310b5..465a763b0d 100644 --- a/Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift +++ b/Trio/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift @@ -509,7 +509,7 @@ extension UserInterfaceSettings { VStack(alignment: .leading) { Picker( selection: $state.timeInRangeType, - label: Text("Lower Range Threshold").multilineTextAlignment(.leading) + label: Text("TIR Lower Threshold").multilineTextAlignment(.leading) ) { ForEach(TimeInRangeType.allCases) { selection in Text(selection.displayName(for: state.units)).tag(selection) @@ -526,7 +526,7 @@ extension UserInterfaceSettings { Spacer() Button( action: { - hintLabel = String(localized: "Lower Range Threshold") + hintLabel = String(localized: "TIR Lower Threshold") selectedVerboseHint = AnyView( VStack( @@ -536,7 +536,7 @@ extension UserInterfaceSettings { let tirUpperThreshold = 180.formatted(withUnits: state.units) let titrUpperThreshold = 140.formatted(withUnits: state.units) Text(String( - localized: "Choose the preferred lower threshold used for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR) with an upper threshold of \(tirUpperThreshold), and Time in Tight Range (TITR) with an upper threshold of \(titrUpperThreshold).", + localized: "Choose the preferred lower threshold for Time in Range statistics across all charts and displays. This applies to both Time in Range (TIR, upper threshold of \(tirUpperThreshold)) and Time in Tight Range (TITR, upper threshold of \(titrUpperThreshold)).", comment: "Explains that the lower threshold applies to both TIR and TITR" )) VStack( @@ -575,7 +575,7 @@ extension UserInterfaceSettings { ).buttonStyle(BorderlessButtonStyle()) }.padding(.top) }.padding(.bottom) - }.settingsSearchTarget(label: String(localized: "Lower Range Threshold")) + }.settingsSearchTarget(label: String(localized: "TIR Lower Threshold")) Section { VStack(alignment: .leading) { diff --git a/TrioTests/SettingsSearchTests.swift b/TrioTests/SettingsSearchTests.swift index 2ebf789f8f..a0715eb7c9 100644 --- a/TrioTests/SettingsSearchTests.swift +++ b/TrioTests/SettingsSearchTests.swift @@ -4,10 +4,10 @@ import Testing @Suite("Settings Search Navigation") struct SettingsSearchTests { @Test("Lower threshold names and legacy aliases navigate to the renamed setting") func searchLowerRangeThreshold() { - for query in ["Lower Range Threshold", "Standard", "Extended", "Time in Range Type", "TITR", "TING"] { + for query in ["TIR Lower Threshold", "Standard", "Extended", "Time in Range Type", "TITR", "TING"] { let results = SettingItems.filteredItems(searchText: query) #expect(results.contains { - $0.settingItem.view == .userInterfaceSettings && $0.scrollLabel == "Lower Range Threshold" + $0.settingItem.view == .userInterfaceSettings && $0.scrollLabel == "TIR Lower Threshold" }, "No lower threshold search target for \(query)") } } From 135ee8e53bd86e16f0a8a0127646ba10614dfd89 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 02:44:44 +0000 Subject: [PATCH 03/41] Label pump-programmed boluses in History > Treatments Persist LoopKit's DoseEntry.wasProgrammedByPumpUI on BolusStored as isPumpUI (optional, default NO; covered by lightweight migration) on both the insert and the mutable-bolus finalize paths, and show a "Pump UI" secondary label on the treatment row next to "External". Rows stored before this change stay unlabelled, since the flag was never persisted for them. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Fpqi9Wu9PGTDMKdoD8PSfA --- Model/Classes+Properties/BolusStored+CoreDataProperties.swift | 1 + .../TrioCoreDataPersistentContainer.xcdatamodel/contents | 1 + Trio/Sources/APS/Storage/PumpHistoryStorage.swift | 2 ++ Trio/Sources/Localizations/Main/Localizable.xcstrings | 3 +++ .../Modules/History/View/HistoryRootView+Treatments.swift | 4 ++++ 5 files changed, 11 insertions(+) diff --git a/Model/Classes+Properties/BolusStored+CoreDataProperties.swift b/Model/Classes+Properties/BolusStored+CoreDataProperties.swift index 488a0743a0..654a75ceae 100644 --- a/Model/Classes+Properties/BolusStored+CoreDataProperties.swift +++ b/Model/Classes+Properties/BolusStored+CoreDataProperties.swift @@ -8,6 +8,7 @@ public extension BolusStored { @NSManaged var amount: NSDecimalNumber? @NSManaged var isExternal: Bool + @NSManaged var isPumpUI: Bool @NSManaged var isSMB: Bool @NSManaged var programmedAmount: NSDecimalNumber? @NSManaged var pumpEvent: PumpEventStored? diff --git a/Model/TrioCoreDataPersistentContainer.xcdatamodeld/TrioCoreDataPersistentContainer.xcdatamodel/contents b/Model/TrioCoreDataPersistentContainer.xcdatamodeld/TrioCoreDataPersistentContainer.xcdatamodel/contents index 37a3398e4c..44efab52ef 100644 --- a/Model/TrioCoreDataPersistentContainer.xcdatamodeld/TrioCoreDataPersistentContainer.xcdatamodel/contents +++ b/Model/TrioCoreDataPersistentContainer.xcdatamodeld/TrioCoreDataPersistentContainer.xcdatamodel/contents @@ -3,6 +3,7 @@ + diff --git a/Trio/Sources/APS/Storage/PumpHistoryStorage.swift b/Trio/Sources/APS/Storage/PumpHistoryStorage.swift index 87ed199891..ab92322f3a 100644 --- a/Trio/Sources/APS/Storage/PumpHistoryStorage.swift +++ b/Trio/Sources/APS/Storage/PumpHistoryStorage.swift @@ -155,6 +155,7 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable { toIncrement: Double(self.settings.preferences.bolusIncrement) )) newBolusEntry.isExternal = dose.manuallyEntered + newBolusEntry.isPumpUI = dose.wasProgrammedByPumpUI newBolusEntry.isSMB = dose.automatic ?? true case .tempBasal: @@ -256,6 +257,7 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable { bolus.amount = finalAmount as NSDecimalNumber } bolus.isSMB = dose.automatic ?? true + bolus.isPumpUI = dose.wasProgrammedByPumpUI event.isMutable = dose.isMutable if event.isUploadedToNS, bolus.amount != previousAmount { event.isUploadedToNS = false diff --git a/Trio/Sources/Localizations/Main/Localizable.xcstrings b/Trio/Sources/Localizations/Main/Localizable.xcstrings index c8deedfb12..6d039ce55f 100644 --- a/Trio/Sources/Localizations/Main/Localizable.xcstrings +++ b/Trio/Sources/Localizations/Main/Localizable.xcstrings @@ -244738,6 +244738,9 @@ } } }, + "Pump UI" : { + "comment" : "Bolus programmed on the pump itself" + }, "Purple = Above Range" : { "localizations" : { "bg" : { diff --git a/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift b/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift index 5d8f7c3a94..23600d5f84 100644 --- a/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift +++ b/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift @@ -62,6 +62,10 @@ extension History.RootView { if bolus.isExternal { Text(String(localized: "External", comment: "External Insulin")).foregroundColor(.secondary) } + if bolus.isPumpUI { + Text(String(localized: "Pump UI", comment: "Bolus programmed on the pump itself")) + .foregroundColor(.secondary) + } } else if let tempBasal = item.tempBasal, let rate = tempBasal.rate { Image(systemName: "circle.fill").foregroundColor(Color.insulin.opacity(0.4)) Text( From cde0a80ff34b076ed9d5e3f3f977845d6b65e202 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 02:48:24 +0000 Subject: [PATCH 04/41] Rename BolusStored.isPumpUI to isProgrammedByPumpUI Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Fpqi9Wu9PGTDMKdoD8PSfA --- Model/Classes+Properties/BolusStored+CoreDataProperties.swift | 2 +- .../TrioCoreDataPersistentContainer.xcdatamodel/contents | 2 +- Trio/Sources/APS/Storage/PumpHistoryStorage.swift | 4 ++-- .../Modules/History/View/HistoryRootView+Treatments.swift | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Model/Classes+Properties/BolusStored+CoreDataProperties.swift b/Model/Classes+Properties/BolusStored+CoreDataProperties.swift index 654a75ceae..79f489d242 100644 --- a/Model/Classes+Properties/BolusStored+CoreDataProperties.swift +++ b/Model/Classes+Properties/BolusStored+CoreDataProperties.swift @@ -8,7 +8,7 @@ public extension BolusStored { @NSManaged var amount: NSDecimalNumber? @NSManaged var isExternal: Bool - @NSManaged var isPumpUI: Bool + @NSManaged var isProgrammedByPumpUI: Bool @NSManaged var isSMB: Bool @NSManaged var programmedAmount: NSDecimalNumber? @NSManaged var pumpEvent: PumpEventStored? diff --git a/Model/TrioCoreDataPersistentContainer.xcdatamodeld/TrioCoreDataPersistentContainer.xcdatamodel/contents b/Model/TrioCoreDataPersistentContainer.xcdatamodeld/TrioCoreDataPersistentContainer.xcdatamodel/contents index 44efab52ef..724222d335 100644 --- a/Model/TrioCoreDataPersistentContainer.xcdatamodeld/TrioCoreDataPersistentContainer.xcdatamodel/contents +++ b/Model/TrioCoreDataPersistentContainer.xcdatamodeld/TrioCoreDataPersistentContainer.xcdatamodel/contents @@ -3,7 +3,7 @@ - + diff --git a/Trio/Sources/APS/Storage/PumpHistoryStorage.swift b/Trio/Sources/APS/Storage/PumpHistoryStorage.swift index ab92322f3a..cacb57ba97 100644 --- a/Trio/Sources/APS/Storage/PumpHistoryStorage.swift +++ b/Trio/Sources/APS/Storage/PumpHistoryStorage.swift @@ -155,7 +155,7 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable { toIncrement: Double(self.settings.preferences.bolusIncrement) )) newBolusEntry.isExternal = dose.manuallyEntered - newBolusEntry.isPumpUI = dose.wasProgrammedByPumpUI + newBolusEntry.isProgrammedByPumpUI = dose.wasProgrammedByPumpUI newBolusEntry.isSMB = dose.automatic ?? true case .tempBasal: @@ -257,7 +257,7 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable { bolus.amount = finalAmount as NSDecimalNumber } bolus.isSMB = dose.automatic ?? true - bolus.isPumpUI = dose.wasProgrammedByPumpUI + bolus.isProgrammedByPumpUI = dose.wasProgrammedByPumpUI event.isMutable = dose.isMutable if event.isUploadedToNS, bolus.amount != previousAmount { event.isUploadedToNS = false diff --git a/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift b/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift index 23600d5f84..0fcfbd2ccc 100644 --- a/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift +++ b/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift @@ -62,7 +62,7 @@ extension History.RootView { if bolus.isExternal { Text(String(localized: "External", comment: "External Insulin")).foregroundColor(.secondary) } - if bolus.isPumpUI { + if bolus.isProgrammedByPumpUI { Text(String(localized: "Pump UI", comment: "Bolus programmed on the pump itself")) .foregroundColor(.secondary) } From 33e1843e6fa783bdcc44d8c4fe392a539e562a49 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Thu, 8 Oct 2026 15:25:05 +0200 Subject: [PATCH 05/41] feat(cgm): add Syai Ultra as CGM --- .gitmodules | 3 + SyaiKit | 1 + Trio.xcodeproj/project.pbxproj | 443 +++++++++--------- Trio.xcworkspace/contents.xcworkspacedata | 5 +- Trio/Sources/APS/CGM/PluginSource.swift | 5 + Trio/Sources/APS/Devices/DeviceCatalog.swift | 11 + .../Sources/Modules/Home/HomeStateModel.swift | 7 + scripts/swiftformat.sh | 3 +- 8 files changed, 260 insertions(+), 218 deletions(-) create mode 160000 SyaiKit diff --git a/.gitmodules b/.gitmodules index dda73c274d..de04ca1e1c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -48,3 +48,6 @@ [submodule "LoopAlgorithm"] path = LoopAlgorithm url = https://github.com/loopandlearn/LoopAlgorithm.git +[submodule "SyaiKit"] + path = SyaiKit + url = https://github.com/nightscout/SyaiKit diff --git a/SyaiKit b/SyaiKit new file mode 160000 index 0000000000..f1c1ca6b64 --- /dev/null +++ b/SyaiKit @@ -0,0 +1 @@ +Subproject commit f1c1ca6b6496ca09e10a143eaa7c50ef038c1663 diff --git a/Trio.xcodeproj/project.pbxproj b/Trio.xcodeproj/project.pbxproj index e6f6b54ed6..19063693a9 100644 --- a/Trio.xcodeproj/project.pbxproj +++ b/Trio.xcodeproj/project.pbxproj @@ -7,8 +7,13 @@ objects = { /* Begin PBXBuildFile section */ + 03B15F4B3077CD4B00DFEBE4 /* SyaiKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03B15F4A3077CD4B00DFEBE4 /* SyaiKit.framework */; }; + 03B15F4D3077CD5400DFEBE4 /* SyaiKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03B15F4C3077CD5400DFEBE4 /* SyaiKitUI.framework */; }; + 03B15F4E3077CD6100DFEBE4 /* SyaiKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 03B15F4C3077CD5400DFEBE4 /* SyaiKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 03B15F4F3077CD6100DFEBE4 /* SyaiKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 03B15F4A3077CD4B00DFEBE4 /* SyaiKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 041D1E995A6AE92E9289DC49 /* TreatmentsDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D1A7CA8C10C4403D4BBFA7 /* TreatmentsDataFlow.swift */; }; 0D9A5E34A899219C5C4CDFAF /* HistoryStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9455FA2D92E77A6C4AFED8A3 /* HistoryStateModel.swift */; }; + 10DAA318F47843A4B894173D /* ContainerResolutionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98546920BB7247B0AC73449A /* ContainerResolutionTests.swift */; }; 110AEDE32C5193D200615CC9 /* BolusIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 110AEDE02C5193D100615CC9 /* BolusIntent.swift */; }; 110AEDE42C5193D200615CC9 /* BolusIntentRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 110AEDE12C5193D100615CC9 /* BolusIntentRequest.swift */; }; 110AEDEB2C51A0AE00615CC9 /* ShortcutsConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 110AEDE52C51A0AE00615CC9 /* ShortcutsConfigView.swift */; }; @@ -54,6 +59,7 @@ 1BBB001DAD60F3B8CEA4B1C7 /* ISFEditorStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505E09DC17A0C3D0AF4B66FE /* ISFEditorStateModel.swift */; }; 1D845DF2E3324130E1D95E67 /* HistoryProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60744C3E9BB3652895C908CC /* HistoryProvider.swift */; }; 23888883D4EA091C88480FF2 /* TreatmentsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C19984D62EFC0035A9E9644D /* TreatmentsProvider.swift */; }; + 25726254CCC5496EB7BD95C8 /* CGMSensorStateLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BEC89F0411CF3EF0F6A61B /* CGMSensorStateLog.swift */; }; 320D030F724170A637F06D50 /* (null) in Sources */ = {isa = PBXBuildFile; }; 3811DE0B25C9D32F00A708ED /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE0725C9D32E00A708ED /* BaseView.swift */; }; 3811DE0C25C9D32F00A708ED /* BaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE0825C9D32F00A708ED /* BaseProvider.swift */; }; @@ -67,16 +73,6 @@ 3811DE3125C9D49500A708ED /* HomeProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE2925C9D49500A708ED /* HomeProvider.swift */; }; 3811DE3225C9D49500A708ED /* HomeDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE2A25C9D49500A708ED /* HomeDataFlow.swift */; }; 3811DE3525C9D49500A708ED /* HomeRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE2E25C9D49500A708ED /* HomeRootView.swift */; }; - 7A11AC0DE000000000000106 /* HomeRootView+Refresh.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000006 /* HomeRootView+Refresh.swift */; }; - 7A11AC0DE000000000000111 /* HomeLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000011 /* HomeLayout.swift */; }; - 7A11AC0DE000000000000113 /* MultiUsePanelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000013 /* MultiUsePanelState.swift */; }; - DB0BB002000000000000000C /* ReleaseNotes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BB002000000000000000B /* ReleaseNotes.swift */; }; - DB0BB002000000000000000E /* ReleaseNotesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BB002000000000000000D /* ReleaseNotesService.swift */; }; - DB0BB0020000000000000010 /* ReleaseNotesSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BB002000000000000000F /* ReleaseNotesSheetView.swift */; }; - 7A11AC0DE000000000000116 /* GlassChrome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000016 /* GlassChrome.swift */; }; - 7A11AC0DE000000000000110 /* HomeRootView+BottomControls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000010 /* HomeRootView+BottomControls.swift */; }; - 7A11AC0DE00000000000010E /* HomeRootView+MealPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000000E /* HomeRootView+MealPanel.swift */; }; - 7A11AC0DE00000000000010D /* HomeRootView+Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000000D /* HomeRootView+Header.swift */; }; 3811DE3F25C9D4A100A708ED /* SettingsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE3925C9D4A100A708ED /* SettingsStateModel.swift */; }; 3811DE4125C9D4A100A708ED /* SettingsRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE3C25C9D4A100A708ED /* SettingsRootView.swift */; }; 3811DE4225C9D4A100A708ED /* SettingsDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE3D25C9D4A100A708ED /* SettingsDataFlow.swift */; }; @@ -222,12 +218,6 @@ 3B2A3BC12E2B19C600658FB9 /* DynamicISF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2A3BC02E2B19C600658FB9 /* DynamicISF.swift */; }; 3B2A3BC32E2B19F700658FB9 /* DynamicISFTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2A3BC22E2B19F700658FB9 /* DynamicISFTests.swift */; }; 3B2CE68B2E24ADF7005EF782 /* IobGenerateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2CE68A2E24ADF3005EF782 /* IobGenerateTests.swift */; }; - FAB1E00000000000000000C1 /* ParityHarness.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B1 /* ParityHarness.swift */; }; - FAB1E00000000000000000C2 /* ParityInputs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B2 /* ParityInputs.swift */; }; - FAB1E00000000000000000C3 /* ParityScenarios.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B3 /* ParityScenarios.swift */; }; - FAB1E00000000000000000C4 /* ParityGoldenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B4 /* ParityGoldenTests.swift */; }; - 7A11AC0DE000000000000060 /* WallClockParityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000160 /* WallClockParityTests.swift */; }; - FAB1E00000000000000000C5 /* ParityPerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B5 /* ParityPerformanceTests.swift */; }; 3B2F77862D7E52ED005ED9FA /* TDD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2F77852D7E52ED005ED9FA /* TDD.swift */; }; 3B2F77882D7E5387005ED9FA /* CurrentTDDSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2F77872D7E5387005ED9FA /* CurrentTDDSetup.swift */; }; 3B3B4F542E661A1200B668E3 /* DetermineBasalGlucoseFallingFasterThanExpectedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3B4F532E6619FF00B668E3 /* DetermineBasalGlucoseFallingFasterThanExpectedTests.swift */; }; @@ -235,7 +225,6 @@ 3B3B4F582E662B1E00B668E3 /* DetermineBasalIobGreaterThanMaxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3B4F572E662B1500B668E3 /* DetermineBasalIobGreaterThanMaxTests.swift */; }; 3B3B57C92DA07B3400849D16 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3B57C82DA07B3400849D16 /* GoogleService-Info.plist */; }; 3B4196E02D8C4BC00091DFF7 /* HomeStateModel+CGM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4196DF2D8C4BBB0091DFF7 /* HomeStateModel+CGM.swift */; }; - D9441F789E7043278FD01494 /* HomeStateModel+QuickPickTreatments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A1E8522E7684C6AA742F6E4 /* HomeStateModel+QuickPickTreatments.swift */; }; 3B4550532D862C0000551B0D /* PumpHistoryEvent+Duplicates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4550522D862BF200551B0D /* PumpHistoryEvent+Duplicates.swift */; }; 3B47C6102DA0A28F00B0E5EF /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 3B47C60F2DA0A28F00B0E5EF /* FirebaseCrashlytics */; }; 3B4BA76A2D8DBD690069D5B8 /* CGMBLEKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA75B2D8DBD690069D5B8 /* CGMBLEKit.framework */; }; @@ -252,10 +241,6 @@ 3B4BA7752D8DBD690069D5B8 /* LibreTransmitter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA7602D8DBD690069D5B8 /* LibreTransmitter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3B4BA7762D8DBD690069D5B8 /* LibreTransmitterUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA7612D8DBD690069D5B8 /* LibreTransmitterUI.framework */; }; 3B4BA7772D8DBD690069D5B8 /* LibreTransmitterUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA7612D8DBD690069D5B8 /* LibreTransmitterUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 5E12FE0E2EBC0000000000B1 /* LibreLoop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E12FE0E2EBC0000000000A1 /* LibreLoop.framework */; }; - 5E12FE0E2EBC0000000000C1 /* LibreLoop.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5E12FE0E2EBC0000000000A1 /* LibreLoop.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 5E12FE0E2EBC0000000000B2 /* LibreLoopUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E12FE0E2EBC0000000000A2 /* LibreLoopUI.framework */; }; - 5E12FE0E2EBC0000000000C2 /* LibreLoopUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5E12FE0E2EBC0000000000A2 /* LibreLoopUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3B4BA7782D8DBD690069D5B8 /* MinimedKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA7622D8DBD690069D5B8 /* MinimedKit.framework */; }; 3B4BA7792D8DBD690069D5B8 /* MinimedKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA7622D8DBD690069D5B8 /* MinimedKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3B4BA77A2D8DBD690069D5B8 /* MinimedKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA7632D8DBD690069D5B8 /* MinimedKitUI.framework */; }; @@ -305,8 +290,6 @@ 3BAC929B2E55FF5300B853DA /* DetermineBasalEnableSmbTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAC929A2E55FF4F00B853DA /* DetermineBasalEnableSmbTests.swift */; }; 3BAC929D2E56A85400B853DA /* TempBasalFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAC929C2E56A84E00B853DA /* TempBasalFunctions.swift */; }; 3BAC92CD2E57859D00B853DA /* SetTempBasalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAC92CC2E57859600B853DA /* SetTempBasalTests.swift */; }; - BD11A011000000000000A011 /* RoundBasalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A010000000000000A011 /* RoundBasalTests.swift */; }; - BD11A015000000000000A011 /* PumpRateTables.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A014000000000000A011 /* PumpRateTables.swift */; }; 3BAD36B22D7CDC1A00CC298D /* MainLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */; }; 3BAD36CC2D7D420E00CC298D /* CoreDataInitializationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAD36CB2D7D420500CC298D /* CoreDataInitializationCoordinator.swift */; }; 3BAE876E2E47F12900FCA8D2 /* DosingEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAE876D2E47F12900FCA8D2 /* DosingEngine.swift */; }; @@ -320,8 +303,6 @@ 3BCE75B52D4B391F009E9453 /* Decimal+rounding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BCE75B42D4B3917009E9453 /* Decimal+rounding.swift */; }; 3BD6CE262DC24CFD00FA0472 /* pumphistory-24h-zoned.json in Resources */ = {isa = PBXBuildFile; fileRef = 3BD6CE252DC24CFD00FA0472 /* pumphistory-24h-zoned.json */; }; 3BD9687C2D8DDD4600899469 /* SlideButton in Frameworks */ = {isa = PBXBuildFile; productRef = 3BD9687B2D8DDD4600899469 /* SlideButton */; }; - 5E12FE112EBC0000000000A2 /* LoopAlgorithm in Frameworks */ = {isa = PBXBuildFile; productRef = 5E12FE112EBC0000000000A1 /* LoopAlgorithm */; }; - 5E12FE112EBC0000000000B2 /* RoundWhiteDiscKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5E12FE112EBC0000000000B1 /* RoundWhiteDiscKit */; }; 3BD9687F2D8DDD8800899469 /* CryptoSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 3BD9687E2D8DDD8800899469 /* CryptoSwift */; }; 3BE2F1E82E030E2F009E2900 /* MealCobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BE2F1E72E030E2F009E2900 /* MealCobTests.swift */; }; 3BE2F1EA2E031951009E2900 /* MealCobBucketingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BE2F1E92E031951009E2900 /* MealCobBucketingTests.swift */; }; @@ -342,11 +323,11 @@ 3EF667132FE48509009FB31A /* BasalDeliveryState+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF667122FE48502009FB31A /* BasalDeliveryState+Extension.swift */; }; 3F23E18680094E6DA98628E4 /* QuickPickTreatmentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A54068ABDAE4898B243DF14 /* QuickPickTreatmentsView.swift */; }; 41740E936552456AAC0EDAC3 /* SettingsSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CA2 /* SettingsSearchTests.swift */; }; - 41740E936552456AAC0EDFC3 /* AlgorithmSuggestedBolusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CF2 /* AlgorithmSuggestedBolusTests.swift */; }; - 41740E936552456AAC0EDEC3 /* DosingModeClampTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CE2 /* DosingModeClampTests.swift */; }; - 41740E936552456AAC0EDDC3 /* LoopIndicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CD2 /* LoopIndicatorTests.swift */; }; - 41740E936552456AAC0EDCC3 /* MaxIOBSuggestionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CC2 /* MaxIOBSuggestionTests.swift */; }; 41740E936552456AAC0EDBC3 /* DosingModeMigrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CB2 /* DosingModeMigrationTests.swift */; }; + 41740E936552456AAC0EDCC3 /* MaxIOBSuggestionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CC2 /* MaxIOBSuggestionTests.swift */; }; + 41740E936552456AAC0EDDC3 /* LoopIndicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CD2 /* LoopIndicatorTests.swift */; }; + 41740E936552456AAC0EDEC3 /* DosingModeClampTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CE2 /* DosingModeClampTests.swift */; }; + 41740E936552456AAC0EDFC3 /* AlgorithmSuggestedBolusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3919BBB515547118D684CF2 /* AlgorithmSuggestedBolusTests.swift */; }; 45252C95D220E796FDB3B022 /* ConfigEditorDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F8A87AA037BD079BA3528BA /* ConfigEditorDataFlow.swift */; }; 45717281F743594AA9D87191 /* ConfigEditorRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920DDB21E5D0EB813197500D /* ConfigEditorRootView.swift */; }; 49090A8D2E9FE8D200D0F5DB /* GarminWatchSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49090A8C2E9FE8D200D0F5DB /* GarminWatchSettings.swift */; }; @@ -358,6 +339,7 @@ 4984D1D42EA2939E00263E83 /* WatchConfigGarminAppConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4984D1D32EA2939E00263E83 /* WatchConfigGarminAppConfigView.swift */; }; 49B9B57F2D5768D2009C6B59 /* AdjustmentStored+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49B9B57E2D5768D2009C6B59 /* AdjustmentStored+Helper.swift */; }; 49C782A72F73D9870062B0DD /* AlertEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C782A62F73D9870062B0DD /* AlertEntry.swift */; }; + 4A3C7DA31A04D14F83DC2957 /* CGMSensorStateLogTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A58E19DE23455CB842C50C /* CGMSensorStateLogTests.swift */; }; 5075C1608E6249A51495C422 /* TargetsEditorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDEA2DC60EDE0A3CA54DC73 /* TargetsEditorProvider.swift */; }; 53F2382465BF74DB1A967C8B /* PumpConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8630D58BDAD6D9C650B9B39 /* PumpConfigProvider.swift */; }; 581516A42BCED84A00BF67D7 /* DebuggingIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581516A32BCED84A00BF67D7 /* DebuggingIdentifiers.swift */; }; @@ -396,6 +378,12 @@ 5A2325542BFCBF66003518CA /* NightscoutFetchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2325532BFCBF65003518CA /* NightscoutFetchView.swift */; }; 5A2325582BFCC168003518CA /* NightscoutConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2325572BFCC168003518CA /* NightscoutConnectView.swift */; }; 5D16287A969E64D18CE40E44 /* PumpConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F60E97100041040446F44E7 /* PumpConfigStateModel.swift */; }; + 5E12FE0E2EBC0000000000B1 /* LibreLoop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E12FE0E2EBC0000000000A1 /* LibreLoop.framework */; }; + 5E12FE0E2EBC0000000000B2 /* LibreLoopUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E12FE0E2EBC0000000000A2 /* LibreLoopUI.framework */; }; + 5E12FE0E2EBC0000000000C1 /* LibreLoop.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5E12FE0E2EBC0000000000A1 /* LibreLoop.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 5E12FE0E2EBC0000000000C2 /* LibreLoopUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5E12FE0E2EBC0000000000A2 /* LibreLoopUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 5E12FE112EBC0000000000A2 /* LoopAlgorithm in Frameworks */ = {isa = PBXBuildFile; productRef = 5E12FE112EBC0000000000A1 /* LoopAlgorithm */; }; + 5E12FE112EBC0000000000B2 /* RoundWhiteDiscKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5E12FE112EBC0000000000B1 /* RoundWhiteDiscKit */; }; 63E890B4D951EAA91C071D5C /* BasalProfileEditorStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAFF91130F2FCCC7EBBA11AD /* BasalProfileEditorStateModel.swift */; }; 642F76A05A4FF530463A9FD0 /* NightscoutConfigRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8782B44544F38F2B2D82C38E /* NightscoutConfigRootView.swift */; }; 65070A332BFDCB83006F213F /* TidepoolStartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65070A322BFDCB83006F213F /* TidepoolStartView.swift */; }; @@ -411,10 +399,29 @@ 6B1A8D2E2B156EEF00E76752 /* LiveActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B1A8D2D2B156EEF00E76752 /* LiveActivityManager.swift */; }; 6BCF84DD2B16843A003AD46E /* LiveActitiyAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF84DC2B16843A003AD46E /* LiveActitiyAttributes.swift */; }; 6BCF84DE2B16843A003AD46E /* LiveActitiyAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF84DC2B16843A003AD46E /* LiveActitiyAttributes.swift */; }; + 6D58D168F03780DA23CB2E52 /* QuickPickTreatmentsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DA23B64976670AC36D9E84 /* QuickPickTreatmentsTests.swift */; }; 6EADD581738D64431902AC0A /* (null) in Sources */ = {isa = PBXBuildFile; }; 71D44AAB2CA5F5EA0036EE9E /* AlertPermissionsChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D44AAA2CA5F5EA0036EE9E /* AlertPermissionsChecker.swift */; }; 72F1BD388F42FCA6C52E4500 /* ConfigEditorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44080E4709E3AE4B73054563 /* ConfigEditorProvider.swift */; }; + 782BE9AEFDD94938A6F3EFE9 /* NightscoutImportRoundTripTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EFF860E684B4C9488D438DD /* NightscoutImportRoundTripTests.swift */; }; 786B6E8A8E294AE883581154 /* QuickPickTreatmentsConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D543DE17E0054AF0821411BB /* QuickPickTreatmentsConfigDataFlow.swift */; }; + 7A11AC0DE000000000000020 /* HomeStatsPanelFace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000120 /* HomeStatsPanelFace.swift */; }; + 7A11AC0DE000000000000030 /* UIHostingController+KeyboardSafeArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000130 /* UIHostingController+KeyboardSafeArea.swift */; }; + 7A11AC0DE000000000000060 /* WallClockParityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000160 /* WallClockParityTests.swift */; }; + 7A11AC0DE000000000000106 /* HomeRootView+Refresh.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000006 /* HomeRootView+Refresh.swift */; }; + 7A11AC0DE000000000000109 /* PumpEventFinalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000009 /* PumpEventFinalizationTests.swift */; }; + 7A11AC0DE00000000000010B /* ScheduledBasalInference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000000B /* ScheduledBasalInference.swift */; }; + 7A11AC0DE00000000000010C /* ScheduledBasalInferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000000C /* ScheduledBasalInferenceTests.swift */; }; + 7A11AC0DE00000000000010D /* HomeRootView+Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000000D /* HomeRootView+Header.swift */; }; + 7A11AC0DE00000000000010E /* HomeRootView+MealPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000000E /* HomeRootView+MealPanel.swift */; }; + 7A11AC0DE000000000000110 /* HomeRootView+BottomControls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000010 /* HomeRootView+BottomControls.swift */; }; + 7A11AC0DE000000000000111 /* HomeLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000011 /* HomeLayout.swift */; }; + 7A11AC0DE000000000000113 /* MultiUsePanelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000013 /* MultiUsePanelState.swift */; }; + 7A11AC0DE000000000000114 /* ManualGlucoseEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000014 /* ManualGlucoseEntryView.swift */; }; + 7A11AC0DE000000000000115 /* MultiUsePanelStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000015 /* MultiUsePanelStateTests.swift */; }; + 7A11AC0DE000000000000116 /* GlassChrome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000016 /* GlassChrome.swift */; }; + 7A11AC0DE00000000000011D /* PumpEventPredicateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000001D /* PumpEventPredicateTests.swift */; }; + 7A11AC0DE000000000000171 /* GlassActionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000170 /* GlassActionSheet.swift */; }; 7F7B756BE8543965D9FDF1A2 /* HistoryDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A401509D21F7F35D4E109EDA /* HistoryDataFlow.swift */; }; 87F4D02B8D4D4D329BA291D2 /* QuickPickTreatmentsConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91711E7CA54747EFAD6540EE /* QuickPickTreatmentsConfigStateModel.swift */; }; 88AB39B23C9552BD6E0C9461 /* ISFEditorRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBB3BAE7494CB771ABAC7B8B /* ISFEditorRootView.swift */; }; @@ -428,10 +435,10 @@ AABB00022C54389F00211FAC /* TreatmentsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AABB00012C54389F00211FAC /* TreatmentsSettingsView.swift */; }; AC19EF2C94084B5BA0175D1D /* SettingsSearchHighlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48B83503461B4F8D97B30115 /* SettingsSearchHighlight.swift */; }; AD3D2CD42CD01B9EB8F26522 /* PumpConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF65DA88F972B56090AD6AC3 /* PumpConfigDataFlow.swift */; }; - B015AFF32E600000000D7351 /* AdjustmentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015AFF12E600000000D7351 /* AdjustmentManager.swift */; }; - B015AFF52E600000000D7351 /* AdjustmentManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015AFF42E600000000D7351 /* AdjustmentManagerTests.swift */; }; B015AFE32E500000000D7351 /* BolusSafetyValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015AFE12E500000000D7351 /* BolusSafetyValidator.swift */; }; B015AFE52E500000000D7351 /* BolusSafetyValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015AFE42E500000000D7351 /* BolusSafetyValidatorTests.swift */; }; + B015AFF32E600000000D7351 /* AdjustmentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015AFF12E600000000D7351 /* AdjustmentManager.swift */; }; + B015AFF52E600000000D7351 /* AdjustmentManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015AFF42E600000000D7351 /* AdjustmentManagerTests.swift */; }; B63C9D934FC54853BC4EF29A /* NightscoutUploadSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10E61A0885164081B57C357C /* NightscoutUploadSerializer.swift */; }; B6E925132EB3932A0076D719 /* OmnipodKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6E925122EB3932A0076D719 /* OmnipodKit.framework */; }; B6E925142EB3932A0076D719 /* OmnipodKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B6E925122EB3932A0076D719 /* OmnipodKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -447,25 +454,6 @@ BD1179242F4E22C100F90001 /* TrioUserNotificationAlertScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1179252F4E22C100F90001 /* TrioUserNotificationAlertScheduler.swift */; }; BD1179282F4E22C100F90001 /* TrioAlertCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1179292F4E22C100F90001 /* TrioAlertCategory.swift */; }; BD1179322F4E22C100F90001 /* CriticalAlertAudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1179312F4E22C100F90001 /* CriticalAlertAudioPlayer.swift */; }; - CAF300000000000000000002 /* CriticalAlertAlarmScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAF300000000000000000001 /* CriticalAlertAlarmScheduler.swift */; }; - CAF200000000000000000000 /* Trio/Resources/Sounds/alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000000 /* Trio/Resources/Sounds/alarm.caf */; }; - CAF200000000000000000001 /* Trio/Resources/Sounds/bloom.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000001 /* Trio/Resources/Sounds/bloom.caf */; }; - CAF200000000000000000002 /* Trio/Resources/Sounds/bloop.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000002 /* Trio/Resources/Sounds/bloop.caf */; }; - CAF200000000000000000003 /* Trio/Resources/Sounds/bright_alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000003 /* Trio/Resources/Sounds/bright_alarm.caf */; }; - CAF200000000000000000004 /* Trio/Resources/Sounds/chime.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000004 /* Trio/Resources/Sounds/chime.caf */; }; - CAF200000000000000000005 /* Trio/Resources/Sounds/clear_chimes.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000005 /* Trio/Resources/Sounds/clear_chimes.caf */; }; - CAF200000000000000000006 /* Trio/Resources/Sounds/critical.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000006 /* Trio/Resources/Sounds/critical.caf */; }; - CAF200000000000000000007 /* Trio/Resources/Sounds/crying.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000007 /* Trio/Resources/Sounds/crying.caf */; }; - CAF200000000000000000008 /* Trio/Resources/Sounds/dings.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000008 /* Trio/Resources/Sounds/dings.caf */; }; - CAF200000000000000000009 /* Trio/Resources/Sounds/high_chimes.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000009 /* Trio/Resources/Sounds/high_chimes.caf */; }; - CAF20000000000000000000A /* Trio/Resources/Sounds/honk.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000A /* Trio/Resources/Sounds/honk.caf */; }; - CAF20000000000000000000B /* Trio/Resources/Sounds/minimal.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000B /* Trio/Resources/Sounds/minimal.caf */; }; - CAF20000000000000000000C /* Trio/Resources/Sounds/mood_synth.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000C /* Trio/Resources/Sounds/mood_synth.caf */; }; - CAF20000000000000000000D /* Trio/Resources/Sounds/simple.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000D /* Trio/Resources/Sounds/simple.caf */; }; - CAF20000000000000000000E /* Trio/Resources/Sounds/spring.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000E /* Trio/Resources/Sounds/spring.caf */; }; - CAF20000000000000000000F /* Trio/Resources/Sounds/synth.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000F /* Trio/Resources/Sounds/synth.caf */; }; - CAF200000000000000000010 /* Trio/Resources/Sounds/trill.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000010 /* Trio/Resources/Sounds/trill.caf */; }; - CAF200000000000000000011 /* Trio/Resources/Sounds/urgent_low.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000011 /* Trio/Resources/Sounds/urgent_low.caf */; }; BD1179402F4E22C100F90001 /* ForecastedGlucoseEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1179412F4E22C100F90001 /* ForecastedGlucoseEvaluator.swift */; }; BD1179522F4E22C100F90001 /* DayNightOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1179512F4E22C100F90001 /* DayNightOptions.swift */; }; BD1179542F4E22C100F90001 /* GlucoseAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1179532F4E22C100F90001 /* GlucoseAlert.swift */; }; @@ -501,8 +489,6 @@ BD1179AA2F4E22C100F90001 /* NotLoopingMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1179AB2F4E22C100F90001 /* NotLoopingMonitor.swift */; }; BD1179AC2F4E22C100F90001 /* GlucoseSourceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1179AD2F4E22C100F90001 /* GlucoseSourceKey.swift */; }; BD11A001000000000000A002 /* AlertMuterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A002 /* AlertMuterTests.swift */; }; - 6D58D168F03780DA23CB2E52 /* QuickPickTreatmentsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DA23B64976670AC36D9E84 /* QuickPickTreatmentsTests.swift */; }; - 4A3C7DA31A04D14F83DC2957 /* CGMSensorStateLogTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A58E19DE23455CB842C50C /* CGMSensorStateLogTests.swift */; }; BD11A001000000000000A003 /* DeviceAlertsStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A003 /* DeviceAlertsStoreTests.swift */; }; BD11A001000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift */; }; BD11A001000000000000A007 /* GlucoseAlertConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A007 /* GlucoseAlertConfigurationTests.swift */; }; @@ -515,11 +501,13 @@ BD11A001000000000000A00E /* DanaKitAlertEmissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A00E /* DanaKitAlertEmissionTests.swift */; }; BD11A001000000000000A00F /* MedtrumKitAlertEmissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A00F /* MedtrumKitAlertEmissionTests.swift */; }; BD11A001000000000000A010 /* MinimedKitAlertEmissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A010 /* MinimedKitAlertEmissionTests.swift */; }; - BD11A013000000000000A011 /* BasalRoundingDriverParityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A012000000000000A011 /* BasalRoundingDriverParityTests.swift */; }; BD11A001000000000000A011 /* OmnipodKitAlertEmissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A011 /* OmnipodKitAlertEmissionTests.swift */; }; BD11A001000000000000A012 /* RileyLinkKitAlertEmissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A012 /* RileyLinkKitAlertEmissionTests.swift */; }; BD11A001000000000000A013 /* TandemKitAlertEmissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A013 /* TandemKitAlertEmissionTests.swift */; }; BD11A001000000000000A014 /* AlertColdStartReplayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A014 /* AlertColdStartReplayTests.swift */; }; + BD11A011000000000000A011 /* RoundBasalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A010000000000000A011 /* RoundBasalTests.swift */; }; + BD11A013000000000000A011 /* BasalRoundingDriverParityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A012000000000000A011 /* BasalRoundingDriverParityTests.swift */; }; + BD11A015000000000000A011 /* PumpRateTables.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A014000000000000A011 /* PumpRateTables.swift */; }; BD11C001000000000000C001 /* CGMSensorDisplayState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11C000000000000000C001 /* CGMSensorDisplayState.swift */; }; BD11C001000000000000C003 /* SensorLifecycleArcView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11C000000000000000C003 /* SensorLifecycleArcView.swift */; }; BD11C001000000000000C004 /* SensorStatusTagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11C000000000000000C004 /* SensorStatusTagView.swift */; }; @@ -570,7 +558,6 @@ BD4D738D2D15A4080052227B /* TDDStored+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD4D738B2D15A4080052227B /* TDDStored+CoreDataClass.swift */; }; BD4D738E2D15A4080052227B /* TDDStored+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD4D738C2D15A4080052227B /* TDDStored+CoreDataProperties.swift */; }; BD4D73A22D15A42A0052227B /* TDDStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD4D73A12D15A4220052227B /* TDDStorage.swift */; }; - 7A11AC0DE00000000000010B /* ScheduledBasalInference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000000B /* ScheduledBasalInference.swift */; }; BD4E1A7A2D3681B700D21626 /* GlucoseTargetSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD4E1A792D3681AD00D21626 /* GlucoseTargetSetup.swift */; }; BD4E1A7C2D3686D900D21626 /* StartEndMarkerSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD4E1A7B2D3686D400D21626 /* StartEndMarkerSetup.swift */; }; BD4ED4FD2CF9D5E8000EDC9C /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD4ED4FC2CF9D5E8000EDC9C /* AppState.swift */; }; @@ -595,10 +582,6 @@ BD8E6B232D9036F700ABF8FA /* OnboardingDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8E6B222D9036F700ABF8FA /* OnboardingDataFlow.swift */; }; BD8FC0542D66186000B95AED /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8FC0532D66186000B95AED /* TestError.swift */; }; BD8FC0572D66188700B95AED /* PumpHistoryStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8FC0562D66188700B95AED /* PumpHistoryStorageTests.swift */; }; - 7A11AC0DE00000000000010C /* ScheduledBasalInferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000000C /* ScheduledBasalInferenceTests.swift */; }; - 7A11AC0DE000000000000109 /* PumpEventFinalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000009 /* PumpEventFinalizationTests.swift */; }; - 7A11AC0DE00000000000011D /* PumpEventPredicateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE00000000000001D /* PumpEventPredicateTests.swift */; }; - 7A11AC0DE000000000000115 /* MultiUsePanelStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000015 /* MultiUsePanelStateTests.swift */; }; BD8FC0592D66189700B95AED /* TestAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8FC0582D66189700B95AED /* TestAssembly.swift */; }; BD8FC05B2D6618AF00B95AED /* DeterminationStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8FC05A2D6618AF00B95AED /* DeterminationStorageTests.swift */; }; BD8FC05E2D6618CE00B95AED /* BolusCalculatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8FC05D2D6618CE00B95AED /* BolusCalculatorTests.swift */; }; @@ -607,7 +590,6 @@ BD8FC0642D6619EF00B95AED /* TempTargetStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8FC0632D6619EF00B95AED /* TempTargetStorageTests.swift */; }; BD8FC0662D661A0000B95AED /* GlucoseStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8FC0652D661A0000B95AED /* GlucoseStorageTests.swift */; }; BD8FC0712D661B0000B95AED /* TidepoolTherapySettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8FC0702D661B0000B95AED /* TidepoolTherapySettingsTests.swift */; }; - CD1235B000000000000000F2 /* TidepoolUploadSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1235A000000000000000F1 /* TidepoolUploadSerializerTests.swift */; }; BDA25EE42D260CD500035F34 /* AppleWatchManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDA25EE32D260CCF00035F34 /* AppleWatchManager.swift */; }; BDA25EE62D260D5E00035F34 /* WatchState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDA25EE52D260D5800035F34 /* WatchState.swift */; }; BDA25EFD2D261C0000035F34 /* WatchState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDA25EFC2D261BF200035F34 /* WatchState.swift */; }; @@ -628,8 +610,8 @@ BDC531122D1060FA00088832 /* ContactImageDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC531112D1060FA00088832 /* ContactImageDetailView.swift */; }; BDC531142D10611D00088832 /* AddContactImageSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC531132D10611D00088832 /* AddContactImageSheet.swift */; }; BDC531162D10629000088832 /* ContactPicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC531152D10629000088832 /* ContactPicture.swift */; }; - BDC531182D1062F300088832 /* GlucoseBobbleContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC531192D1062F400088832 /* GlucoseBobbleContactView.swift */; }; BDC531182D1062F200088832 /* ContactImageState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC531172D1062F200088832 /* ContactImageState.swift */; }; + BDC531182D1062F300088832 /* GlucoseBobbleContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC531192D1062F400088832 /* GlucoseBobbleContactView.swift */; }; BDCAF2382C639F35002DC907 /* SettingItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDCAF2372C639F35002DC907 /* SettingItems.swift */; }; BDCD47AF2C1F3F1700F8BCD5 /* OverrideStored+helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDCD47AE2C1F3F1700F8BCD5 /* OverrideStored+helper.swift */; }; BDDAF9EF2D00554500B34E7A /* ChartSelectionRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDDAF9EE2D00553E00B34E7A /* ChartSelectionRow.swift */; }; @@ -669,20 +651,38 @@ CA01000000000000000010C6 /* CGMManagerAlertOwnership.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA01000000000000000010C5 /* CGMManagerAlertOwnership.swift */; }; CA01000000000000000010C8 /* AlertColdStartReplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA01000000000000000010C7 /* AlertColdStartReplay.swift */; }; CA02000000000000000010C2 /* DeliveryLimitsSyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA02000000000000000010C1 /* DeliveryLimitsSyncTests.swift */; }; - CA07000000000000000010C2 /* TelemetrySendGateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA07000000000000000010C1 /* TelemetrySendGateTests.swift */; }; CA03000000000000000010C2 /* AlertCatalogRegistryOmniFaultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA03000000000000000010C1 /* AlertCatalogRegistryOmniFaultTests.swift */; }; CA05000000000000000010C2 /* AlarmGramsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA05000000000000000010C1 /* AlarmGramsSection.swift */; }; CA06000000000000000010C2 /* GlucoseAlertsStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA06000000000000000010C1 /* GlucoseAlertsStoreTests.swift */; }; + CA07000000000000000010C2 /* TelemetrySendGateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA07000000000000000010C1 /* TelemetrySendGateTests.swift */; }; CA370FC152BC98B3D1832968 /* BasalProfileEditorRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8BCB0C37DEB5EC377B9612 /* BasalProfileEditorRootView.swift */; }; + CAF200000000000000000000 /* Trio/Resources/Sounds/alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000000 /* Trio/Resources/Sounds/alarm.caf */; }; + CAF200000000000000000001 /* Trio/Resources/Sounds/bloom.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000001 /* Trio/Resources/Sounds/bloom.caf */; }; + CAF200000000000000000002 /* Trio/Resources/Sounds/bloop.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000002 /* Trio/Resources/Sounds/bloop.caf */; }; + CAF200000000000000000003 /* Trio/Resources/Sounds/bright_alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000003 /* Trio/Resources/Sounds/bright_alarm.caf */; }; + CAF200000000000000000004 /* Trio/Resources/Sounds/chime.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000004 /* Trio/Resources/Sounds/chime.caf */; }; + CAF200000000000000000005 /* Trio/Resources/Sounds/clear_chimes.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000005 /* Trio/Resources/Sounds/clear_chimes.caf */; }; + CAF200000000000000000006 /* Trio/Resources/Sounds/critical.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000006 /* Trio/Resources/Sounds/critical.caf */; }; + CAF200000000000000000007 /* Trio/Resources/Sounds/crying.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000007 /* Trio/Resources/Sounds/crying.caf */; }; + CAF200000000000000000008 /* Trio/Resources/Sounds/dings.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000008 /* Trio/Resources/Sounds/dings.caf */; }; + CAF200000000000000000009 /* Trio/Resources/Sounds/high_chimes.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000009 /* Trio/Resources/Sounds/high_chimes.caf */; }; + CAF20000000000000000000A /* Trio/Resources/Sounds/honk.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000A /* Trio/Resources/Sounds/honk.caf */; }; + CAF20000000000000000000B /* Trio/Resources/Sounds/minimal.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000B /* Trio/Resources/Sounds/minimal.caf */; }; + CAF20000000000000000000C /* Trio/Resources/Sounds/mood_synth.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000C /* Trio/Resources/Sounds/mood_synth.caf */; }; + CAF20000000000000000000D /* Trio/Resources/Sounds/simple.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000D /* Trio/Resources/Sounds/simple.caf */; }; + CAF20000000000000000000E /* Trio/Resources/Sounds/spring.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000E /* Trio/Resources/Sounds/spring.caf */; }; + CAF20000000000000000000F /* Trio/Resources/Sounds/synth.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF10000000000000000000F /* Trio/Resources/Sounds/synth.caf */; }; + CAF200000000000000000010 /* Trio/Resources/Sounds/trill.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000010 /* Trio/Resources/Sounds/trill.caf */; }; + CAF200000000000000000011 /* Trio/Resources/Sounds/urgent_low.caf in Resources */ = {isa = PBXBuildFile; fileRef = CAF100000000000000000011 /* Trio/Resources/Sounds/urgent_low.caf */; }; + CAF300000000000000000002 /* CriticalAlertAlarmScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAF300000000000000000001 /* CriticalAlertAlarmScheduler.swift */; }; CC6C406E2ACDD69E009B8058 /* RawFetchedProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6C406D2ACDD69E009B8058 /* RawFetchedProfile.swift */; }; CC76E9512BD4812E008BEB61 /* Forecast+helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC76E9502BD4812E008BEB61 /* Forecast+helper.swift */; }; + CD1235B000000000000000F2 /* TidepoolUploadSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1235A000000000000000F1 /* TidepoolUploadSerializerTests.swift */; }; + CD1235D000000000000000F4 /* TidepoolUploadSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1235C000000000000000F3 /* TidepoolUploadSerializer.swift */; }; CE1856F52ADC4858007E39C7 /* AddCarbPresetIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1856F42ADC4858007E39C7 /* AddCarbPresetIntent.swift */; }; CE1856F72ADC4869007E39C7 /* CarbPresetIntentRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1856F62ADC4869007E39C7 /* CarbPresetIntentRequest.swift */; }; CE1F6DD92BADF4620064EB8D /* PluginManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1F6DD82BADF4620064EB8D /* PluginManagerTests.swift */; }; - DC01A00E2E9F100000000005 /* DeviceCatalogTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC01A00D2E9F100000000004 /* DeviceCatalogTests.swift */; }; - 10DAA318F47843A4B894173D /* ContainerResolutionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98546920BB7247B0AC73449A /* ContainerResolutionTests.swift */; }; CE1F6DDB2BAE08B60064EB8D /* TidepoolManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1F6DDA2BAE08B60064EB8D /* TidepoolManager.swift */; }; - CD1235D000000000000000F4 /* TidepoolUploadSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1235C000000000000000F3 /* TidepoolUploadSerializer.swift */; }; CE1F6DE72BAF1A180064EB8D /* BuildDetails.plist in Resources */ = {isa = PBXBuildFile; fileRef = CE1F6DE62BAF1A180064EB8D /* BuildDetails.plist */; }; CE1F6DE92BAF37C90064EB8D /* TidepoolConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1F6DE82BAF37C90064EB8D /* TidepoolConfigView.swift */; }; CE2FAD3A297D93F0001A872C /* BloodGlucoseExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2FAD39297D93F0001A872C /* BloodGlucoseExtensions.swift */; }; @@ -705,9 +705,7 @@ CE94598429E9E3E60047C9C6 /* WatchConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE94598329E9E3E60047C9C6 /* WatchConfigStateModel.swift */; }; CE94598729E9E4110047C9C6 /* WatchConfigRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE94598629E9E4110047C9C6 /* WatchConfigRootView.swift */; }; CE95BF572BA5F5FE00DC3DE3 /* PluginManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE95BF562BA5F5FE00DC3DE3 /* PluginManager.swift */; }; - DC01A00B2E9F100000000002 /* DeviceCatalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC01A00A2E9F100000000001 /* DeviceCatalog.swift */; }; CE95BF5A2BA62E4A00DC3DE3 /* PluginSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE95BF592BA62E4A00DC3DE3 /* PluginSource.swift */; }; - 25726254CCC5496EB7BD95C8 /* CGMSensorStateLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BEC89F0411CF3EF0F6A61B /* CGMSensorStateLog.swift */; }; CE95BF5B2BA770C300DC3DE3 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3818AA4C274C26A300843DB3 /* LoopKit.framework */; }; CE95BF5C2BA770C300DC3DE3 /* LoopKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3818AA4C274C26A300843DB3 /* LoopKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; CE95BF5D2BA770C300DC3DE3 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3818AA4D274C26A300843DB3 /* LoopKitUI.framework */; }; @@ -733,7 +731,16 @@ D6D02515BBFBE64FEBE89856 /* HistoryRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881E04BA5E0A003DE8E0A9C6 /* HistoryRootView.swift */; }; D6DEC113821A7F1056C4AA1E /* NightscoutConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F2A13DF0EDEEEDC4106AA2A /* NightscoutConfigDataFlow.swift */; }; D7C5E1F4A7B91E2F3C5D6E70 /* TimeInterval+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C5E1F4A7B91E2F3C5D6E71 /* TimeInterval+Convenience.swift */; }; + D9441F789E7043278FD01494 /* HomeStateModel+QuickPickTreatments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A1E8522E7684C6AA742F6E4 /* HomeStateModel+QuickPickTreatments.swift */; }; + DB0BA0010000000000000003 /* DevelopmentBranchAlerter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BA0010000000000000002 /* DevelopmentBranchAlerter.swift */; }; + DB0BB002000000000000000C /* ReleaseNotes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BB002000000000000000B /* ReleaseNotes.swift */; }; + DB0BB002000000000000000E /* ReleaseNotesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BB002000000000000000D /* ReleaseNotesService.swift */; }; + DB0BB0020000000000000010 /* ReleaseNotesSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BB002000000000000000F /* ReleaseNotesSheetView.swift */; }; + DB0BB0030000000000000002 /* ReleaseNotesListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BB0030000000000000001 /* ReleaseNotesListView.swift */; }; DBA5254DBB2586C98F61220C /* ISFEditorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F9F137F126D9F8DEB799F26 /* ISFEditorProvider.swift */; }; + DC01A00B2E9F100000000002 /* DeviceCatalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC01A00A2E9F100000000001 /* DeviceCatalog.swift */; }; + DC01A00E2E9F100000000005 /* DeviceCatalogTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC01A00D2E9F100000000004 /* DeviceCatalogTests.swift */; }; + DC01A0102E9F100000000007 /* DevicePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC01A00F2E9F100000000006 /* DevicePickerView.swift */; }; DD09D47B2C5986D1003FEA5D /* CalendarEventSettingsDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD09D47A2C5986D1003FEA5D /* CalendarEventSettingsDataFlow.swift */; }; DD09D47D2C5986DA003FEA5D /* CalendarEventSettingsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD09D47C2C5986DA003FEA5D /* CalendarEventSettingsProvider.swift */; }; DD09D47F2C5986E5003FEA5D /* CalendarEventSettingsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD09D47E2C5986E5003FEA5D /* CalendarEventSettingsStateModel.swift */; }; @@ -822,8 +829,6 @@ DD4C581F2D73C43D001BFF2C /* LoopStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C581E2D73C43D001BFF2C /* LoopStatsView.swift */; }; DD4FFF332D458EE600B6CFF9 /* GarminWatchState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4FFF322D458EE600B6CFF9 /* GarminWatchState.swift */; }; DD500A712807000000000101 /* SnoozeAlertsSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD500A712807000000000100 /* SnoozeAlertsSheetView.swift */; }; - 7A11AC0DE000000000000171 /* GlassActionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000170 /* GlassActionSheet.swift */; }; - 7A11AC0DE000000000000114 /* ManualGlucoseEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000014 /* ManualGlucoseEntryView.swift */; }; DD5DC9F12CF3D97C00AB8703 /* AdjustmentsStateModel+Overrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5DC9F02CF3D96E00AB8703 /* AdjustmentsStateModel+Overrides.swift */; }; DD5DC9F32CF3D9DD00AB8703 /* AdjustmentsStateModel+TempTargets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5DC9F22CF3D9D600AB8703 /* AdjustmentsStateModel+TempTargets.swift */; }; DD5DC9F72CF3DA9300AB8703 /* TargetPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5DC9F62CF3DA9300AB8703 /* TargetPicker.swift */; }; @@ -831,7 +836,6 @@ DD5DC9FB2CF3E1B100AB8703 /* AdjustmentsStateModel+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5DC9FA2CF3E1AA00AB8703 /* AdjustmentsStateModel+Helpers.swift */; }; DD68889D2C386E17006E3C44 /* NightscoutExercise.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD68889C2C386E17006E3C44 /* NightscoutExercise.swift */; }; DD6A4E082DBD95F1008C4B26 /* BluetoothRequiredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A4E072DBD95F1008C4B26 /* BluetoothRequiredView.swift */; }; - DC01A0102E9F100000000007 /* DevicePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC01A00F2E9F100000000006 /* DevicePickerView.swift */; }; DD6A4E7E2DBEBF0F008C4B26 /* StartupReturningUserStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A4E7D2DBEBF0F008C4B26 /* StartupReturningUserStepView.swift */; }; DD6A4E802DBEC3EE008C4B26 /* StartupForceCloseWarningStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A4E7F2DBEC3EE008C4B26 /* StartupForceCloseWarningStepView.swift */; }; DD6A4E842DBEDD39008C4B26 /* AlgorithmSettingsImportantNotesStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A4E832DBEDD39008C4B26 /* AlgorithmSettingsImportantNotesStepView.swift */; }; @@ -874,7 +878,6 @@ DDA6E3202D258E0500C2988C /* OverrideHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E31F2D258E0500C2988C /* OverrideHelpView.swift */; }; DDA6E3222D25901100C2988C /* TempTargetHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E3212D25901100C2988C /* TempTargetHelpView.swift */; }; DDA6E3572D25988500C2988C /* ContactImageHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E3562D25988500C2988C /* ContactImageHelpView.swift */; }; - DB0BA0010000000000000003 /* DevelopmentBranchAlerter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BA0010000000000000002 /* DevelopmentBranchAlerter.swift */; }; DDA9AC092D672CF100E6F1A9 /* AppVersionChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA9AC082D672CEB00E6F1A9 /* AppVersionChecker.swift */; }; DDAA29832D2D1D93006546A1 /* AdjustmentsRootView+Overrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAA29822D2D1D7B006546A1 /* AdjustmentsRootView+Overrides.swift */; }; DDAA29852D2D1D9E006546A1 /* AdjustmentsRootView+TempTargets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAA29842D2D1D98006546A1 /* AdjustmentsRootView+TempTargets.swift */; }; @@ -887,7 +890,6 @@ DDC6CA6D2DD90A2A0060EE25 /* LocalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC6CA6C2DD90A2A0060EE25 /* LocalizationTests.swift */; }; DDCAE8332D78D4A800B1BB51 /* TherapySettingsUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDCAE8322D78D49C00B1BB51 /* TherapySettingsUtil.swift */; }; DDCE790F2D6F97FC000A4D7A /* SubmodulesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDCE790E2D6F97F7000A4D7A /* SubmodulesView.swift */; }; - DB0BB0030000000000000002 /* ReleaseNotesListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0BB0030000000000000001 /* ReleaseNotesListView.swift */; }; DDCEBF5B2CC1B76400DF4C36 /* LiveActivity+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDCEBF5A2CC1B76400DF4C36 /* LiveActivity+Helper.swift */; }; DDD163122C4C689900CD525A /* AdjustmentsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD163112C4C689900CD525A /* AdjustmentsStateModel.swift */; }; DDD163142C4C68D300CD525A /* AdjustmentsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD163132C4C68D300CD525A /* AdjustmentsProvider.swift */; }; @@ -935,7 +937,6 @@ DDE179702C910127003CDDB7 /* OverrideStored+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE179502C910127003CDDB7 /* OverrideStored+CoreDataClass.swift */; }; DDE179712C910127003CDDB7 /* OverrideStored+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE179512C910127003CDDB7 /* OverrideStored+CoreDataProperties.swift */; }; DDEBB05C2D89E9050032305D /* TimeInRangeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDEBB05B2D89E9050032305D /* TimeInRangeType.swift */; }; - 7A11AC0DE000000000000020 /* HomeStatsPanelFace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000120 /* HomeStatsPanelFace.swift */; }; DDF68FFC2D9ECF7F008BF16C /* OnboardingStateModel+Nightscout.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF68FFB2D9ECF77008BF16C /* OnboardingStateModel+Nightscout.swift */; }; DDF6905C2DA0AFC5008BF16C /* WelcomeStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF6905B2DA0AFC5008BF16C /* WelcomeStepView.swift */; }; DDF691012DA2CA11008BF16C /* AppDiagnosticsDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF691002DA2CA0B008BF16C /* AppDiagnosticsDataFlow.swift */; }; @@ -985,11 +986,14 @@ F90692D6274B9A450037068D /* HealthKitStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F90692D5274B9A450037068D /* HealthKitStateModel.swift */; }; FA630397F76B582C8D8681A7 /* BasalProfileEditorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42369F66CF91F30624C0B3A6 /* BasalProfileEditorProvider.swift */; }; FA6B58486AE2496F9F8589C6 /* QuickPickTreatmentsConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EEC5C2927FA4C5DA61A1A40 /* QuickPickTreatmentsConfigProvider.swift */; }; + FAB1E00000000000000000C1 /* ParityHarness.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B1 /* ParityHarness.swift */; }; + FAB1E00000000000000000C2 /* ParityInputs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B2 /* ParityInputs.swift */; }; + FAB1E00000000000000000C3 /* ParityScenarios.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B3 /* ParityScenarios.swift */; }; + FAB1E00000000000000000C4 /* ParityGoldenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B4 /* ParityGoldenTests.swift */; }; + FAB1E00000000000000000C5 /* ParityPerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB1E00000000000000000B5 /* ParityPerformanceTests.swift */; }; FB9012AE66284A92A6531037 /* NightscoutUploadSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C39FF1EC12CF4B1EBB13BE26 /* NightscoutUploadSerializerTests.swift */; }; - 782BE9AEFDD94938A6F3EFE9 /* NightscoutImportRoundTripTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EFF860E684B4C9488D438DD /* NightscoutImportRoundTripTests.swift */; }; FE41E4D629463EE20047FD55 /* NightscoutPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE41E4D529463EE20047FD55 /* NightscoutPreferences.swift */; }; FE66D16B291F74F8005D6F77 /* Bundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE66D16A291F74F8005D6F77 /* Bundle+Extensions.swift */; }; - 7A11AC0DE000000000000030 /* UIHostingController+KeyboardSafeArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11AC0DE000000000000130 /* UIHostingController+KeyboardSafeArea.swift */; }; FEFFA7A22929FE49007B8193 /* UIDevice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFFA7A12929FE49007B8193 /* UIDevice+Extensions.swift */; }; /* End PBXBuildFile section */ @@ -1038,6 +1042,8 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 03B15F4E3077CD6100DFEBE4 /* SyaiKitUI.framework in Embed Frameworks */, + 03B15F4F3077CD6100DFEBE4 /* SyaiKit.framework in Embed Frameworks */, 3B4BA78F2D8DC0EC0069D5B8 /* TidepoolServiceKit.framework in Embed Frameworks */, 3B4BA7732D8DBD690069D5B8 /* G7SensorKitUI.framework in Embed Frameworks */, 3B4BA76D2D8DBD690069D5B8 /* CGMBLEKitUI.framework in Embed Frameworks */, @@ -1106,6 +1112,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 03B15F4A3077CD4B00DFEBE4 /* SyaiKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SyaiKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 03B15F4C3077CD5400DFEBE4 /* SyaiKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SyaiKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0A1E8522E7684C6AA742F6E4 /* HomeStateModel+QuickPickTreatments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeStateModel+QuickPickTreatments.swift"; sourceTree = ""; }; 10E61A0885164081B57C357C /* NightscoutUploadSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutUploadSerializer.swift; sourceTree = ""; }; 110AEDE02C5193D100615CC9 /* BolusIntent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BolusIntent.swift; sourceTree = ""; }; 110AEDE12C5193D100615CC9 /* BolusIntentRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BolusIntentRequest.swift; sourceTree = ""; }; @@ -1165,16 +1174,6 @@ 3811DE2925C9D49500A708ED /* HomeProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeProvider.swift; sourceTree = ""; }; 3811DE2A25C9D49500A708ED /* HomeDataFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeDataFlow.swift; sourceTree = ""; }; 3811DE2E25C9D49500A708ED /* HomeRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeRootView.swift; sourceTree = ""; }; - 7A11AC0DE000000000000006 /* HomeRootView+Refresh.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeRootView+Refresh.swift"; sourceTree = ""; }; - 7A11AC0DE000000000000011 /* HomeLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeLayout.swift; sourceTree = ""; }; - 7A11AC0DE000000000000013 /* MultiUsePanelState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiUsePanelState.swift; sourceTree = ""; }; - DB0BB002000000000000000B /* ReleaseNotes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotes.swift; sourceTree = ""; }; - DB0BB002000000000000000D /* ReleaseNotesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotesService.swift; sourceTree = ""; }; - DB0BB002000000000000000F /* ReleaseNotesSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotesSheetView.swift; sourceTree = ""; }; - 7A11AC0DE000000000000016 /* GlassChrome.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlassChrome.swift; sourceTree = ""; }; - 7A11AC0DE000000000000010 /* HomeRootView+BottomControls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeRootView+BottomControls.swift"; sourceTree = ""; }; - 7A11AC0DE00000000000000E /* HomeRootView+MealPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeRootView+MealPanel.swift"; sourceTree = ""; }; - 7A11AC0DE00000000000000D /* HomeRootView+Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeRootView+Header.swift"; sourceTree = ""; }; 3811DE3925C9D4A100A708ED /* SettingsStateModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsStateModel.swift; sourceTree = ""; }; 3811DE3C25C9D4A100A708ED /* SettingsRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsRootView.swift; sourceTree = ""; }; 3811DE3D25C9D4A100A708ED /* SettingsDataFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDataFlow.swift; sourceTree = ""; }; @@ -1336,12 +1335,6 @@ 3B2A3BC02E2B19C600658FB9 /* DynamicISF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicISF.swift; sourceTree = ""; }; 3B2A3BC22E2B19F700658FB9 /* DynamicISFTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicISFTests.swift; sourceTree = ""; }; 3B2CE68A2E24ADF3005EF782 /* IobGenerateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobGenerateTests.swift; sourceTree = ""; }; - FAB1E00000000000000000B1 /* ParityHarness.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityHarness.swift; sourceTree = ""; }; - FAB1E00000000000000000B2 /* ParityInputs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityInputs.swift; sourceTree = ""; }; - FAB1E00000000000000000B3 /* ParityScenarios.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityScenarios.swift; sourceTree = ""; }; - FAB1E00000000000000000B4 /* ParityGoldenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityGoldenTests.swift; sourceTree = ""; }; - 7A11AC0DE000000000000160 /* WallClockParityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallClockParityTests.swift; sourceTree = ""; }; - FAB1E00000000000000000B5 /* ParityPerformanceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityPerformanceTests.swift; sourceTree = ""; }; 3B2F77852D7E52ED005ED9FA /* TDD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TDD.swift; sourceTree = ""; }; 3B2F77872D7E5387005ED9FA /* CurrentTDDSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentTDDSetup.swift; sourceTree = ""; }; 3B3B4F532E6619FF00B668E3 /* DetermineBasalGlucoseFallingFasterThanExpectedTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalGlucoseFallingFasterThanExpectedTests.swift; sourceTree = ""; }; @@ -1349,7 +1342,6 @@ 3B3B4F572E662B1500B668E3 /* DetermineBasalIobGreaterThanMaxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalIobGreaterThanMaxTests.swift; sourceTree = ""; }; 3B3B57C82DA07B3400849D16 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 3B4196DF2D8C4BBB0091DFF7 /* HomeStateModel+CGM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeStateModel+CGM.swift"; sourceTree = ""; }; - 0A1E8522E7684C6AA742F6E4 /* HomeStateModel+QuickPickTreatments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeStateModel+QuickPickTreatments.swift"; sourceTree = ""; }; 3B4550522D862BF200551B0D /* PumpHistoryEvent+Duplicates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PumpHistoryEvent+Duplicates.swift"; sourceTree = ""; }; 3B4BA75B2D8DBD690069D5B8 /* CGMBLEKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CGMBLEKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B4BA75C2D8DBD690069D5B8 /* CGMBLEKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CGMBLEKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1358,8 +1350,6 @@ 3B4BA75F2D8DBD690069D5B8 /* G7SensorKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = G7SensorKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B4BA7602D8DBD690069D5B8 /* LibreTransmitter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LibreTransmitter.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B4BA7612D8DBD690069D5B8 /* LibreTransmitterUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LibreTransmitterUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5E12FE0E2EBC0000000000A1 /* LibreLoop.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LibreLoop.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5E12FE0E2EBC0000000000A2 /* LibreLoopUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LibreLoopUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B4BA7622D8DBD690069D5B8 /* MinimedKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MinimedKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B4BA7632D8DBD690069D5B8 /* MinimedKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MinimedKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B4BA7672D8DBD690069D5B8 /* RileyLinkBLEKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RileyLinkBLEKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1398,8 +1388,6 @@ 3BAC929A2E55FF4F00B853DA /* DetermineBasalEnableSmbTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalEnableSmbTests.swift; sourceTree = ""; }; 3BAC929C2E56A84E00B853DA /* TempBasalFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempBasalFunctions.swift; sourceTree = ""; }; 3BAC92CC2E57859600B853DA /* SetTempBasalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetTempBasalTests.swift; sourceTree = ""; }; - BD11A010000000000000A011 /* RoundBasalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundBasalTests.swift; sourceTree = ""; }; - BD11A014000000000000A011 /* PumpRateTables.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpRateTables.swift; sourceTree = ""; }; 3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainLoadingView.swift; sourceTree = ""; }; 3BAD36CB2D7D420500CC298D /* CoreDataInitializationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataInitializationCoordinator.swift; sourceTree = ""; }; 3BAE876D2E47F12900FCA8D2 /* DosingEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DosingEngine.swift; sourceTree = ""; }; @@ -1429,6 +1417,7 @@ 3EF667122FE48502009FB31A /* BasalDeliveryState+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BasalDeliveryState+Extension.swift"; sourceTree = ""; }; 3F60E97100041040446F44E7 /* PumpConfigStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PumpConfigStateModel.swift; sourceTree = ""; }; 3F8A87AA037BD079BA3528BA /* ConfigEditorDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConfigEditorDataFlow.swift; sourceTree = ""; }; + 41BEC89F0411CF3EF0F6A61B /* CGMSensorStateLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMSensorStateLog.swift; sourceTree = ""; }; 42369F66CF91F30624C0B3A6 /* BasalProfileEditorProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BasalProfileEditorProvider.swift; sourceTree = ""; }; 44080E4709E3AE4B73054563 /* ConfigEditorProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConfigEditorProvider.swift; sourceTree = ""; }; 48B83503461B4F8D97B30115 /* SettingsSearchHighlight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSearchHighlight.swift; sourceTree = ""; }; @@ -1481,6 +1470,8 @@ 5A2325572BFCC168003518CA /* NightscoutConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutConnectView.swift; sourceTree = ""; }; 5C018D1680307A31C9ED7120 /* CGMSettingsStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CGMSettingsStateModel.swift; sourceTree = ""; }; 5D5B4F8B4194BB7E260EF251 /* ConfigEditorStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConfigEditorStateModel.swift; sourceTree = ""; }; + 5E12FE0E2EBC0000000000A1 /* LibreLoop.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LibreLoop.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E12FE0E2EBC0000000000A2 /* LibreLoopUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LibreLoopUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 60744C3E9BB3652895C908CC /* HistoryProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HistoryProvider.swift; sourceTree = ""; }; 64AA5E04A2761F6EEA6568E1 /* CarbRatioEditorStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CarbRatioEditorStateModel.swift; sourceTree = ""; }; 65070A322BFDCB83006F213F /* TidepoolStartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TidepoolStartView.swift; sourceTree = ""; }; @@ -1495,8 +1486,27 @@ 6B1A8D252B14D91700E76752 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6B1A8D2D2B156EEF00E76752 /* LiveActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivityManager.swift; sourceTree = ""; }; 6BCF84DC2B16843A003AD46E /* LiveActitiyAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActitiyAttributes.swift; sourceTree = ""; }; + 6EFF860E684B4C9488D438DD /* NightscoutImportRoundTripTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutImportRoundTripTests.swift; sourceTree = ""; }; + 71A58E19DE23455CB842C50C /* CGMSensorStateLogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMSensorStateLogTests.swift; sourceTree = ""; }; 71D44AAA2CA5F5EA0036EE9E /* AlertPermissionsChecker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertPermissionsChecker.swift; sourceTree = ""; }; 79BDA519C9B890FD9A5DFCF3 /* ISFEditorDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ISFEditorDataFlow.swift; sourceTree = ""; }; + 7A11AC0DE000000000000006 /* HomeRootView+Refresh.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeRootView+Refresh.swift"; sourceTree = ""; }; + 7A11AC0DE000000000000009 /* PumpEventFinalizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpEventFinalizationTests.swift; sourceTree = ""; }; + 7A11AC0DE00000000000000B /* ScheduledBasalInference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduledBasalInference.swift; sourceTree = ""; }; + 7A11AC0DE00000000000000C /* ScheduledBasalInferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduledBasalInferenceTests.swift; sourceTree = ""; }; + 7A11AC0DE00000000000000D /* HomeRootView+Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeRootView+Header.swift"; sourceTree = ""; }; + 7A11AC0DE00000000000000E /* HomeRootView+MealPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeRootView+MealPanel.swift"; sourceTree = ""; }; + 7A11AC0DE000000000000010 /* HomeRootView+BottomControls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeRootView+BottomControls.swift"; sourceTree = ""; }; + 7A11AC0DE000000000000011 /* HomeLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeLayout.swift; sourceTree = ""; }; + 7A11AC0DE000000000000013 /* MultiUsePanelState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiUsePanelState.swift; sourceTree = ""; }; + 7A11AC0DE000000000000014 /* ManualGlucoseEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualGlucoseEntryView.swift; sourceTree = ""; }; + 7A11AC0DE000000000000015 /* MultiUsePanelStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiUsePanelStateTests.swift; sourceTree = ""; }; + 7A11AC0DE000000000000016 /* GlassChrome.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlassChrome.swift; sourceTree = ""; }; + 7A11AC0DE00000000000001D /* PumpEventPredicateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpEventPredicateTests.swift; sourceTree = ""; }; + 7A11AC0DE000000000000120 /* HomeStatsPanelFace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeStatsPanelFace.swift; sourceTree = ""; }; + 7A11AC0DE000000000000130 /* UIHostingController+KeyboardSafeArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIHostingController+KeyboardSafeArea.swift"; sourceTree = ""; }; + 7A11AC0DE000000000000160 /* WallClockParityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallClockParityTests.swift; sourceTree = ""; }; + 7A11AC0DE000000000000170 /* GlassActionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlassActionSheet.swift; sourceTree = ""; }; 7E22146D3DF4853786C78132 /* CarbRatioEditorDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CarbRatioEditorDataFlow.swift; sourceTree = ""; }; 8782B44544F38F2B2D82C38E /* NightscoutConfigRootView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NightscoutConfigRootView.swift; sourceTree = ""; }; 881E04BA5E0A003DE8E0A9C6 /* HistoryRootView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HistoryRootView.swift; sourceTree = ""; }; @@ -1506,6 +1516,7 @@ 91711E7CA54747EFAD6540EE /* QuickPickTreatmentsConfigStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickTreatmentsConfigStateModel.swift; sourceTree = ""; }; 920DDB21E5D0EB813197500D /* ConfigEditorRootView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConfigEditorRootView.swift; sourceTree = ""; }; 9455FA2D92E77A6C4AFED8A3 /* HistoryStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HistoryStateModel.swift; sourceTree = ""; }; + 98546920BB7247B0AC73449A /* ContainerResolutionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerResolutionTests.swift; sourceTree = ""; }; 9C8D5F457B5AFF763F8CF3DF /* CarbRatioEditorProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CarbRatioEditorProvider.swift; sourceTree = ""; }; 9F9F137F126D9F8DEB799F26 /* ISFEditorProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ISFEditorProvider.swift; sourceTree = ""; }; A0A48AE3AC813A49A517846A /* NightscoutConfigStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NightscoutConfigStateModel.swift; sourceTree = ""; }; @@ -1514,16 +1525,16 @@ AABB00012C54389F00211FAC /* TreatmentsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreatmentsSettingsView.swift; sourceTree = ""; }; AAFF91130F2FCCC7EBBA11AD /* BasalProfileEditorStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BasalProfileEditorStateModel.swift; sourceTree = ""; }; AF65DA88F972B56090AD6AC3 /* PumpConfigDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PumpConfigDataFlow.swift; sourceTree = ""; }; - B015AFF12E600000000D7351 /* AdjustmentManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjustmentManager.swift; sourceTree = ""; }; - B015AFF42E600000000D7351 /* AdjustmentManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjustmentManagerTests.swift; sourceTree = ""; }; B015AFE12E500000000D7351 /* BolusSafetyValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusSafetyValidator.swift; sourceTree = ""; }; B015AFE42E500000000D7351 /* BolusSafetyValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusSafetyValidatorTests.swift; sourceTree = ""; }; + B015AFF12E600000000D7351 /* AdjustmentManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjustmentManager.swift; sourceTree = ""; }; + B015AFF42E600000000D7351 /* AdjustmentManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjustmentManagerTests.swift; sourceTree = ""; }; B3919BBB515547118D684CA2 /* SettingsSearchTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SettingsSearchTests.swift; sourceTree = ""; }; - B3919BBB515547118D684CF2 /* AlgorithmSuggestedBolusTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AlgorithmSuggestedBolusTests.swift; sourceTree = ""; }; - B3919BBB515547118D684CE2 /* DosingModeClampTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DosingModeClampTests.swift; sourceTree = ""; }; - B3919BBB515547118D684CD2 /* LoopIndicatorTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LoopIndicatorTests.swift; sourceTree = ""; }; - B3919BBB515547118D684CC2 /* MaxIOBSuggestionTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MaxIOBSuggestionTests.swift; sourceTree = ""; }; B3919BBB515547118D684CB2 /* DosingModeMigrationTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DosingModeMigrationTests.swift; sourceTree = ""; }; + B3919BBB515547118D684CC2 /* MaxIOBSuggestionTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MaxIOBSuggestionTests.swift; sourceTree = ""; }; + B3919BBB515547118D684CD2 /* LoopIndicatorTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LoopIndicatorTests.swift; sourceTree = ""; }; + B3919BBB515547118D684CE2 /* DosingModeClampTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DosingModeClampTests.swift; sourceTree = ""; }; + B3919BBB515547118D684CF2 /* AlgorithmSuggestedBolusTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AlgorithmSuggestedBolusTests.swift; sourceTree = ""; }; B6E925122EB3932A0076D719 /* OmnipodKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmnipodKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B9B5C0607505A38F256BF99A /* CGMSettingsDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CGMSettingsDataFlow.swift; sourceTree = ""; }; BA49538D56989D8DA6FCF538 /* TargetsEditorDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TargetsEditorDataFlow.swift; sourceTree = ""; }; @@ -1535,25 +1546,6 @@ BD1179252F4E22C100F90001 /* TrioUserNotificationAlertScheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioUserNotificationAlertScheduler.swift; sourceTree = ""; }; BD1179292F4E22C100F90001 /* TrioAlertCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioAlertCategory.swift; sourceTree = ""; }; BD1179312F4E22C100F90001 /* CriticalAlertAudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CriticalAlertAudioPlayer.swift; sourceTree = ""; }; - CAF300000000000000000001 /* CriticalAlertAlarmScheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CriticalAlertAlarmScheduler.swift; sourceTree = ""; }; - CAF100000000000000000000 /* Trio/Resources/Sounds/alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/alarm.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000001 /* Trio/Resources/Sounds/bloom.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/bloom.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000002 /* Trio/Resources/Sounds/bloop.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/bloop.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000003 /* Trio/Resources/Sounds/bright_alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/bright_alarm.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000004 /* Trio/Resources/Sounds/chime.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/chime.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000005 /* Trio/Resources/Sounds/clear_chimes.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/clear_chimes.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000006 /* Trio/Resources/Sounds/critical.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/critical.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000007 /* Trio/Resources/Sounds/crying.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/crying.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000008 /* Trio/Resources/Sounds/dings.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/dings.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000009 /* Trio/Resources/Sounds/high_chimes.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/high_chimes.caf; sourceTree = SOURCE_ROOT; }; - CAF10000000000000000000A /* Trio/Resources/Sounds/honk.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/honk.caf; sourceTree = SOURCE_ROOT; }; - CAF10000000000000000000B /* Trio/Resources/Sounds/minimal.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/minimal.caf; sourceTree = SOURCE_ROOT; }; - CAF10000000000000000000C /* Trio/Resources/Sounds/mood_synth.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/mood_synth.caf; sourceTree = SOURCE_ROOT; }; - CAF10000000000000000000D /* Trio/Resources/Sounds/simple.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/simple.caf; sourceTree = SOURCE_ROOT; }; - CAF10000000000000000000E /* Trio/Resources/Sounds/spring.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/spring.caf; sourceTree = SOURCE_ROOT; }; - CAF10000000000000000000F /* Trio/Resources/Sounds/synth.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/synth.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000010 /* Trio/Resources/Sounds/trill.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/trill.caf; sourceTree = SOURCE_ROOT; }; - CAF100000000000000000011 /* Trio/Resources/Sounds/urgent_low.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/urgent_low.caf; sourceTree = SOURCE_ROOT; }; BD1179412F4E22C100F90001 /* ForecastedGlucoseEvaluator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastedGlucoseEvaluator.swift; sourceTree = ""; }; BD1179512F4E22C100F90001 /* DayNightOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayNightOptions.swift; sourceTree = ""; }; BD1179532F4E22C100F90001 /* GlucoseAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlert.swift; sourceTree = ""; }; @@ -1589,8 +1581,6 @@ BD1179AB2F4E22C100F90001 /* NotLoopingMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotLoopingMonitor.swift; sourceTree = ""; }; BD1179AD2F4E22C100F90001 /* GlucoseSourceKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseSourceKey.swift; sourceTree = ""; }; BD11A000000000000000A002 /* AlertMuterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertMuterTests.swift; sourceTree = ""; }; - C7DA23B64976670AC36D9E84 /* QuickPickTreatmentsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickTreatmentsTests.swift; sourceTree = ""; }; - 71A58E19DE23455CB842C50C /* CGMSensorStateLogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMSensorStateLogTests.swift; sourceTree = ""; }; BD11A000000000000000A003 /* DeviceAlertsStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceAlertsStoreTests.swift; sourceTree = ""; }; BD11A000000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastedGlucoseEvaluatorTests.swift; sourceTree = ""; }; BD11A000000000000000A007 /* GlucoseAlertConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlertConfigurationTests.swift; sourceTree = ""; }; @@ -1603,11 +1593,13 @@ BD11A000000000000000A00E /* DanaKitAlertEmissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DanaKitAlertEmissionTests.swift; sourceTree = ""; }; BD11A000000000000000A00F /* MedtrumKitAlertEmissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MedtrumKitAlertEmissionTests.swift; sourceTree = ""; }; BD11A000000000000000A010 /* MinimedKitAlertEmissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MinimedKitAlertEmissionTests.swift; sourceTree = ""; }; - BD11A012000000000000A011 /* BasalRoundingDriverParityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasalRoundingDriverParityTests.swift; sourceTree = ""; }; BD11A000000000000000A011 /* OmnipodKitAlertEmissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OmnipodKitAlertEmissionTests.swift; sourceTree = ""; }; BD11A000000000000000A012 /* RileyLinkKitAlertEmissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RileyLinkKitAlertEmissionTests.swift; sourceTree = ""; }; BD11A000000000000000A013 /* TandemKitAlertEmissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TandemKitAlertEmissionTests.swift; sourceTree = ""; }; BD11A000000000000000A014 /* AlertColdStartReplayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertColdStartReplayTests.swift; sourceTree = ""; }; + BD11A010000000000000A011 /* RoundBasalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundBasalTests.swift; sourceTree = ""; }; + BD11A012000000000000A011 /* BasalRoundingDriverParityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasalRoundingDriverParityTests.swift; sourceTree = ""; }; + BD11A014000000000000A011 /* PumpRateTables.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpRateTables.swift; sourceTree = ""; }; BD11C000000000000000C001 /* CGMSensorDisplayState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMSensorDisplayState.swift; sourceTree = ""; }; BD11C000000000000000C003 /* SensorLifecycleArcView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SensorLifecycleArcView.swift; sourceTree = ""; }; BD11C000000000000000C004 /* SensorStatusTagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SensorStatusTagView.swift; sourceTree = ""; }; @@ -1657,7 +1649,6 @@ BD4D738B2D15A4080052227B /* TDDStored+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TDDStored+CoreDataClass.swift"; sourceTree = SOURCE_ROOT; }; BD4D738C2D15A4080052227B /* TDDStored+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TDDStored+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; }; BD4D73A12D15A4220052227B /* TDDStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TDDStorage.swift; sourceTree = ""; }; - 7A11AC0DE00000000000000B /* ScheduledBasalInference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduledBasalInference.swift; sourceTree = ""; }; BD4E1A792D3681AD00D21626 /* GlucoseTargetSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseTargetSetup.swift; sourceTree = ""; }; BD4E1A7B2D3686D400D21626 /* StartEndMarkerSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartEndMarkerSetup.swift; sourceTree = ""; }; BD4ED4FC2CF9D5E8000EDC9C /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; }; @@ -1678,10 +1669,6 @@ BD8E6B222D9036F700ABF8FA /* OnboardingDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingDataFlow.swift; sourceTree = ""; }; BD8FC0532D66186000B95AED /* TestError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestError.swift; sourceTree = ""; }; BD8FC0562D66188700B95AED /* PumpHistoryStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpHistoryStorageTests.swift; sourceTree = ""; }; - 7A11AC0DE00000000000000C /* ScheduledBasalInferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduledBasalInferenceTests.swift; sourceTree = ""; }; - 7A11AC0DE000000000000009 /* PumpEventFinalizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpEventFinalizationTests.swift; sourceTree = ""; }; - 7A11AC0DE00000000000001D /* PumpEventPredicateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpEventPredicateTests.swift; sourceTree = ""; }; - 7A11AC0DE000000000000015 /* MultiUsePanelStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiUsePanelStateTests.swift; sourceTree = ""; }; BD8FC0582D66189700B95AED /* TestAssembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAssembly.swift; sourceTree = ""; }; BD8FC05A2D6618AF00B95AED /* DeterminationStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeterminationStorageTests.swift; sourceTree = ""; }; BD8FC05D2D6618CE00B95AED /* BolusCalculatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusCalculatorTests.swift; sourceTree = ""; }; @@ -1690,7 +1677,6 @@ BD8FC0632D6619EF00B95AED /* TempTargetStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetStorageTests.swift; sourceTree = ""; }; BD8FC0652D661A0000B95AED /* GlucoseStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseStorageTests.swift; sourceTree = ""; }; BD8FC0702D661B0000B95AED /* TidepoolTherapySettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TidepoolTherapySettingsTests.swift; sourceTree = ""; }; - CD1235A000000000000000F1 /* TidepoolUploadSerializerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TidepoolUploadSerializerTests.swift; sourceTree = ""; }; BDA25EE32D260CCF00035F34 /* AppleWatchManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleWatchManager.swift; sourceTree = ""; }; BDA25EE52D260D5800035F34 /* WatchState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchState.swift; sourceTree = ""; }; BDA25EFC2D261BF200035F34 /* WatchState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchState.swift; sourceTree = ""; }; @@ -1711,8 +1697,8 @@ BDC531112D1060FA00088832 /* ContactImageDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactImageDetailView.swift; sourceTree = ""; }; BDC531132D10611D00088832 /* AddContactImageSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactImageSheet.swift; sourceTree = ""; }; BDC531152D10629000088832 /* ContactPicture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactPicture.swift; sourceTree = ""; }; - BDC531192D1062F400088832 /* GlucoseBobbleContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseBobbleContactView.swift; sourceTree = ""; }; BDC531172D1062F200088832 /* ContactImageState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactImageState.swift; sourceTree = ""; }; + BDC531192D1062F400088832 /* GlucoseBobbleContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseBobbleContactView.swift; sourceTree = ""; }; BDCAF2372C639F35002DC907 /* SettingItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingItems.swift; sourceTree = ""; }; BDCD47AE2C1F3F1700F8BCD5 /* OverrideStored+helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OverrideStored+helper.swift"; sourceTree = ""; }; BDDAF9EE2D00553E00B34E7A /* ChartSelectionRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartSelectionRow.swift; sourceTree = ""; }; @@ -1752,26 +1738,44 @@ C2BA6B962F758E7500348E6A /* WatchNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchNotificationHandler.swift; sourceTree = ""; }; C2BA6B982F758E7600348E6A /* NotificationIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationIdentifiers.swift; sourceTree = ""; }; C39FF1EC12CF4B1EBB13BE26 /* NightscoutUploadSerializerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutUploadSerializerTests.swift; sourceTree = ""; }; - 6EFF860E684B4C9488D438DD /* NightscoutImportRoundTripTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutImportRoundTripTests.swift; sourceTree = ""; }; + C7DA23B64976670AC36D9E84 /* QuickPickTreatmentsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickTreatmentsTests.swift; sourceTree = ""; }; C8D1A7CA8C10C4403D4BBFA7 /* TreatmentsDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TreatmentsDataFlow.swift; sourceTree = ""; }; CA01000000000000000010C1 /* AlertCatalogVendor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertCatalogVendor.swift; sourceTree = ""; }; CA01000000000000000010C3 /* AlertCatalogRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertCatalogRegistry.swift; sourceTree = ""; }; CA01000000000000000010C5 /* CGMManagerAlertOwnership.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMManagerAlertOwnership.swift; sourceTree = ""; }; CA01000000000000000010C7 /* AlertColdStartReplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertColdStartReplay.swift; sourceTree = ""; }; CA02000000000000000010C1 /* DeliveryLimitsSyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeliveryLimitsSyncTests.swift; sourceTree = ""; }; - CA07000000000000000010C1 /* TelemetrySendGateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetrySendGateTests.swift; sourceTree = ""; }; CA03000000000000000010C1 /* AlertCatalogRegistryOmniFaultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertCatalogRegistryOmniFaultTests.swift; sourceTree = ""; }; CA05000000000000000010C1 /* AlarmGramsSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmGramsSection.swift; sourceTree = ""; }; CA06000000000000000010C1 /* GlucoseAlertsStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlertsStoreTests.swift; sourceTree = ""; }; + CA07000000000000000010C1 /* TelemetrySendGateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetrySendGateTests.swift; sourceTree = ""; }; + CAF100000000000000000000 /* Trio/Resources/Sounds/alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/alarm.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000001 /* Trio/Resources/Sounds/bloom.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/bloom.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000002 /* Trio/Resources/Sounds/bloop.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/bloop.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000003 /* Trio/Resources/Sounds/bright_alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/bright_alarm.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000004 /* Trio/Resources/Sounds/chime.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/chime.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000005 /* Trio/Resources/Sounds/clear_chimes.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/clear_chimes.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000006 /* Trio/Resources/Sounds/critical.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/critical.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000007 /* Trio/Resources/Sounds/crying.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/crying.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000008 /* Trio/Resources/Sounds/dings.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/dings.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000009 /* Trio/Resources/Sounds/high_chimes.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/high_chimes.caf; sourceTree = SOURCE_ROOT; }; + CAF10000000000000000000A /* Trio/Resources/Sounds/honk.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/honk.caf; sourceTree = SOURCE_ROOT; }; + CAF10000000000000000000B /* Trio/Resources/Sounds/minimal.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/minimal.caf; sourceTree = SOURCE_ROOT; }; + CAF10000000000000000000C /* Trio/Resources/Sounds/mood_synth.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/mood_synth.caf; sourceTree = SOURCE_ROOT; }; + CAF10000000000000000000D /* Trio/Resources/Sounds/simple.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/simple.caf; sourceTree = SOURCE_ROOT; }; + CAF10000000000000000000E /* Trio/Resources/Sounds/spring.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/spring.caf; sourceTree = SOURCE_ROOT; }; + CAF10000000000000000000F /* Trio/Resources/Sounds/synth.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/synth.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000010 /* Trio/Resources/Sounds/trill.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/trill.caf; sourceTree = SOURCE_ROOT; }; + CAF100000000000000000011 /* Trio/Resources/Sounds/urgent_low.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Trio/Resources/Sounds/urgent_low.caf; sourceTree = SOURCE_ROOT; }; + CAF300000000000000000001 /* CriticalAlertAlarmScheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CriticalAlertAlarmScheduler.swift; sourceTree = ""; }; CC6C406D2ACDD69E009B8058 /* RawFetchedProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RawFetchedProfile.swift; sourceTree = ""; }; CC76E9502BD4812E008BEB61 /* Forecast+helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Forecast+helper.swift"; sourceTree = ""; }; + CD1235A000000000000000F1 /* TidepoolUploadSerializerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TidepoolUploadSerializerTests.swift; sourceTree = ""; }; + CD1235C000000000000000F3 /* TidepoolUploadSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TidepoolUploadSerializer.swift; sourceTree = ""; }; CE1856F42ADC4858007E39C7 /* AddCarbPresetIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddCarbPresetIntent.swift; sourceTree = ""; }; CE1856F62ADC4869007E39C7 /* CarbPresetIntentRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbPresetIntentRequest.swift; sourceTree = ""; }; CE1F6DD82BADF4620064EB8D /* PluginManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginManagerTests.swift; sourceTree = ""; }; - DC01A00D2E9F100000000004 /* DeviceCatalogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceCatalogTests.swift; sourceTree = ""; }; - 98546920BB7247B0AC73449A /* ContainerResolutionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerResolutionTests.swift; sourceTree = ""; }; CE1F6DDA2BAE08B60064EB8D /* TidepoolManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TidepoolManager.swift; sourceTree = ""; }; - CD1235C000000000000000F3 /* TidepoolUploadSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TidepoolUploadSerializer.swift; sourceTree = ""; }; CE1F6DE62BAF1A180064EB8D /* BuildDetails.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = BuildDetails.plist; sourceTree = ""; }; CE1F6DE82BAF37C90064EB8D /* TidepoolConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TidepoolConfigView.swift; sourceTree = ""; }; CE2FAD39297D93F0001A872C /* BloodGlucoseExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BloodGlucoseExtensions.swift; sourceTree = ""; }; @@ -1805,9 +1809,7 @@ CE95BF492BA5CED700DC3DE3 /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CE95BF4A2BA5CED700DC3DE3 /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CE95BF562BA5F5FE00DC3DE3 /* PluginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginManager.swift; sourceTree = ""; }; - DC01A00A2E9F100000000001 /* DeviceCatalog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceCatalog.swift; sourceTree = ""; }; CE95BF592BA62E4A00DC3DE3 /* PluginSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginSource.swift; sourceTree = ""; }; - 41BEC89F0411CF3EF0F6A61B /* CGMSensorStateLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMSensorStateLog.swift; sourceTree = ""; }; CEB434DB28B8F5B900B70274 /* MKRingProgressView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MKRingProgressView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CEB434E228B8F9DB00B70274 /* BluetoothStateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothStateManager.swift; sourceTree = ""; }; CEB434E428B8FF5D00B70274 /* UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; @@ -1824,7 +1826,15 @@ D0BDC6993C1087310EDFC428 /* CarbRatioEditorRootView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CarbRatioEditorRootView.swift; sourceTree = ""; }; D543DE17E0054AF0821411BB /* QuickPickTreatmentsConfigDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickTreatmentsConfigDataFlow.swift; sourceTree = ""; }; D7C5E1F4A7B91E2F3C5D6E71 /* TimeInterval+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TimeInterval+Convenience.swift"; sourceTree = ""; }; + DB0BA0010000000000000002 /* DevelopmentBranchAlerter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevelopmentBranchAlerter.swift; sourceTree = ""; }; + DB0BB002000000000000000B /* ReleaseNotes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotes.swift; sourceTree = ""; }; + DB0BB002000000000000000D /* ReleaseNotesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotesService.swift; sourceTree = ""; }; + DB0BB002000000000000000F /* ReleaseNotesSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotesSheetView.swift; sourceTree = ""; }; + DB0BB0030000000000000001 /* ReleaseNotesListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotesListView.swift; sourceTree = ""; }; DB3EBC8BA17C4627BD32C58F /* QuickPickTreatmentsConfigRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickTreatmentsConfigRootView.swift; sourceTree = ""; }; + DC01A00A2E9F100000000001 /* DeviceCatalog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceCatalog.swift; sourceTree = ""; }; + DC01A00D2E9F100000000004 /* DeviceCatalogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceCatalogTests.swift; sourceTree = ""; }; + DC01A00F2E9F100000000006 /* DevicePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicePickerView.swift; sourceTree = ""; }; DD09D47A2C5986D1003FEA5D /* CalendarEventSettingsDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarEventSettingsDataFlow.swift; sourceTree = ""; }; DD09D47C2C5986DA003FEA5D /* CalendarEventSettingsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarEventSettingsProvider.swift; sourceTree = ""; }; DD09D47E2C5986E5003FEA5D /* CalendarEventSettingsStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarEventSettingsStateModel.swift; sourceTree = ""; }; @@ -1911,8 +1921,6 @@ DD4C581E2D73C43D001BFF2C /* LoopStatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopStatsView.swift; sourceTree = ""; }; DD4FFF322D458EE600B6CFF9 /* GarminWatchState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GarminWatchState.swift; sourceTree = ""; }; DD500A712807000000000100 /* SnoozeAlertsSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnoozeAlertsSheetView.swift; sourceTree = ""; }; - 7A11AC0DE000000000000170 /* GlassActionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlassActionSheet.swift; sourceTree = ""; }; - 7A11AC0DE000000000000014 /* ManualGlucoseEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualGlucoseEntryView.swift; sourceTree = ""; }; DD5DC9F02CF3D96E00AB8703 /* AdjustmentsStateModel+Overrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdjustmentsStateModel+Overrides.swift"; sourceTree = ""; }; DD5DC9F22CF3D9D600AB8703 /* AdjustmentsStateModel+TempTargets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdjustmentsStateModel+TempTargets.swift"; sourceTree = ""; }; DD5DC9F62CF3DA9300AB8703 /* TargetPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetPicker.swift; sourceTree = ""; }; @@ -1920,7 +1928,6 @@ DD5DC9FA2CF3E1AA00AB8703 /* AdjustmentsStateModel+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdjustmentsStateModel+Helpers.swift"; sourceTree = ""; }; DD68889C2C386E17006E3C44 /* NightscoutExercise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutExercise.swift; sourceTree = ""; }; DD6A4E072DBD95F1008C4B26 /* BluetoothRequiredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothRequiredView.swift; sourceTree = ""; }; - DC01A00F2E9F100000000006 /* DevicePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicePickerView.swift; sourceTree = ""; }; DD6A4E7D2DBEBF0F008C4B26 /* StartupReturningUserStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartupReturningUserStepView.swift; sourceTree = ""; }; DD6A4E7F2DBEC3EE008C4B26 /* StartupForceCloseWarningStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartupForceCloseWarningStepView.swift; sourceTree = ""; }; DD6A4E832DBEDD39008C4B26 /* AlgorithmSettingsImportantNotesStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmSettingsImportantNotesStepView.swift; sourceTree = ""; }; @@ -1963,7 +1970,6 @@ DDA6E31F2D258E0500C2988C /* OverrideHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideHelpView.swift; sourceTree = ""; }; DDA6E3212D25901100C2988C /* TempTargetHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetHelpView.swift; sourceTree = ""; }; DDA6E3562D25988500C2988C /* ContactImageHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactImageHelpView.swift; sourceTree = ""; }; - DB0BA0010000000000000002 /* DevelopmentBranchAlerter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevelopmentBranchAlerter.swift; sourceTree = ""; }; DDA9AC082D672CEB00E6F1A9 /* AppVersionChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersionChecker.swift; sourceTree = ""; }; DDA9AC0A2D678DAD00E6F1A9 /* blacklisted-versions.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "blacklisted-versions.json"; sourceTree = ""; }; DDAA29822D2D1D7B006546A1 /* AdjustmentsRootView+Overrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdjustmentsRootView+Overrides.swift"; sourceTree = ""; }; @@ -1979,7 +1985,6 @@ DDC6CA6C2DD90A2A0060EE25 /* LocalizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationTests.swift; sourceTree = ""; }; DDCAE8322D78D49C00B1BB51 /* TherapySettingsUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TherapySettingsUtil.swift; sourceTree = ""; }; DDCE790E2D6F97F7000A4D7A /* SubmodulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubmodulesView.swift; sourceTree = ""; }; - DB0BB0030000000000000001 /* ReleaseNotesListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotesListView.swift; sourceTree = ""; }; DDCEBF5A2CC1B76400DF4C36 /* LiveActivity+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LiveActivity+Helper.swift"; sourceTree = ""; }; DDD163112C4C689900CD525A /* AdjustmentsStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjustmentsStateModel.swift; sourceTree = ""; }; DDD163132C4C68D300CD525A /* AdjustmentsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjustmentsProvider.swift; sourceTree = ""; }; @@ -2027,7 +2032,6 @@ DDE179502C910127003CDDB7 /* OverrideStored+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OverrideStored+CoreDataClass.swift"; sourceTree = ""; }; DDE179512C910127003CDDB7 /* OverrideStored+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OverrideStored+CoreDataProperties.swift"; sourceTree = ""; }; DDEBB05B2D89E9050032305D /* TimeInRangeType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeInRangeType.swift; sourceTree = ""; }; - 7A11AC0DE000000000000120 /* HomeStatsPanelFace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeStatsPanelFace.swift; sourceTree = ""; }; DDF68FFB2D9ECF77008BF16C /* OnboardingStateModel+Nightscout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OnboardingStateModel+Nightscout.swift"; sourceTree = ""; }; DDF6905B2DA0AFC5008BF16C /* WelcomeStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeStepView.swift; sourceTree = ""; }; DDF691002DA2CA0B008BF16C /* AppDiagnosticsDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDiagnosticsDataFlow.swift; sourceTree = ""; }; @@ -2069,10 +2073,14 @@ F90692D0274B99B60037068D /* HealthKitProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthKitProvider.swift; sourceTree = ""; }; F90692D2274B9A130037068D /* AppleHealthKitRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleHealthKitRootView.swift; sourceTree = ""; }; F90692D5274B9A450037068D /* HealthKitStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthKitStateModel.swift; sourceTree = ""; }; + FAB1E00000000000000000B1 /* ParityHarness.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityHarness.swift; sourceTree = ""; }; + FAB1E00000000000000000B2 /* ParityInputs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityInputs.swift; sourceTree = ""; }; + FAB1E00000000000000000B3 /* ParityScenarios.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityScenarios.swift; sourceTree = ""; }; + FAB1E00000000000000000B4 /* ParityGoldenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityGoldenTests.swift; sourceTree = ""; }; + FAB1E00000000000000000B5 /* ParityPerformanceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParityPerformanceTests.swift; sourceTree = ""; }; FBB3BAE7494CB771ABAC7B8B /* ISFEditorRootView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ISFEditorRootView.swift; sourceTree = ""; }; FE41E4D529463EE20047FD55 /* NightscoutPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutPreferences.swift; sourceTree = ""; }; FE66D16A291F74F8005D6F77 /* Bundle+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Extensions.swift"; sourceTree = ""; }; - 7A11AC0DE000000000000130 /* UIHostingController+KeyboardSafeArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIHostingController+KeyboardSafeArea.swift"; sourceTree = ""; }; FEFFA7A12929FE49007B8193 /* UIDevice+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDevice+Extensions.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -2086,6 +2094,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 03B15F4D3077CD5400DFEBE4 /* SyaiKitUI.framework in Frameworks */, + 03B15F4B3077CD4B00DFEBE4 /* SyaiKit.framework in Frameworks */, CE95BF632BA771BE00DC3DE3 /* LoopTestingKit.framework in Frameworks */, 3B4BA7722D8DBD690069D5B8 /* G7SensorKitUI.framework in Frameworks */, 3B4BA7742D8DBD690069D5B8 /* LibreTransmitter.framework in Frameworks */, @@ -2747,6 +2757,8 @@ 3818AA48274C267000843DB3 /* Frameworks */ = { isa = PBXGroup; children = ( + 03B15F4C3077CD5400DFEBE4 /* SyaiKitUI.framework */, + 03B15F4A3077CD4B00DFEBE4 /* SyaiKit.framework */, 3E5308A43002BC970075629E /* AccuChekKit.framework */, B6E925122EB3932A0076D719 /* OmnipodKit.framework */, 3E54EF2B2E476DA40006F54D /* MedtrumKit.framework */, @@ -2825,14 +2837,6 @@ path = Header; sourceTree = ""; }; - DC01A00C2E9F100000000003 /* Devices */ = { - isa = PBXGroup; - children = ( - DC01A00A2E9F100000000001 /* DeviceCatalog.swift */, - ); - path = Devices; - sourceTree = ""; - }; 3856933F270B57A00002C50D /* CGM */ = { isa = PBXGroup; children = ( @@ -3403,19 +3407,6 @@ path = OpenAPSSwiftTests; sourceTree = ""; }; - FAB1E00000000000000000A0 /* Parity */ = { - isa = PBXGroup; - children = ( - FAB1E00000000000000000B1 /* ParityHarness.swift */, - FAB1E00000000000000000B2 /* ParityInputs.swift */, - FAB1E00000000000000000B3 /* ParityScenarios.swift */, - FAB1E00000000000000000B4 /* ParityGoldenTests.swift */, - 7A11AC0DE000000000000160 /* WallClockParityTests.swift */, - FAB1E00000000000000000B5 /* ParityPerformanceTests.swift */, - ); - path = Parity; - sourceTree = ""; - }; 3B997DD22DC02AEF006B6BB2 /* JSONImporterData */ = { isa = PBXGroup; children = ( @@ -3596,36 +3587,36 @@ path = BasalProfileEditor; sourceTree = ""; }; - B015AFF22E600000000D7351 /* Adjustments */ = { + B015AFE22E500000000D7351 /* BolusSafety */ = { isa = PBXGroup; children = ( - B015AFF12E600000000D7351 /* AdjustmentManager.swift */, + B015AFE12E500000000D7351 /* BolusSafetyValidator.swift */, ); - path = Adjustments; + path = BolusSafety; sourceTree = ""; }; - B015AFF62E600000000D7351 /* AdjustmentsTests */ = { + B015AFE62E500000000D7351 /* BolusSafetyTests */ = { isa = PBXGroup; children = ( - B015AFF42E600000000D7351 /* AdjustmentManagerTests.swift */, + B015AFE42E500000000D7351 /* BolusSafetyValidatorTests.swift */, ); - path = AdjustmentsTests; + path = BolusSafetyTests; sourceTree = ""; }; - B015AFE22E500000000D7351 /* BolusSafety */ = { + B015AFF22E600000000D7351 /* Adjustments */ = { isa = PBXGroup; children = ( - B015AFE12E500000000D7351 /* BolusSafetyValidator.swift */, + B015AFF12E600000000D7351 /* AdjustmentManager.swift */, ); - path = BolusSafety; + path = Adjustments; sourceTree = ""; }; - B015AFE62E500000000D7351 /* BolusSafetyTests */ = { + B015AFF62E600000000D7351 /* AdjustmentsTests */ = { isa = PBXGroup; children = ( - B015AFE42E500000000D7351 /* BolusSafetyValidatorTests.swift */, + B015AFF42E600000000D7351 /* AdjustmentManagerTests.swift */, ); - path = BolusSafetyTests; + path = AdjustmentsTests; sourceTree = ""; }; B9488883C59C31550E0B4CEC /* View */ = { @@ -4160,6 +4151,31 @@ path = ISFEditor; sourceTree = ""; }; + DB0BA0010000000000000001 /* DevelopmentBranchAlerter */ = { + isa = PBXGroup; + children = ( + DB0BA0010000000000000002 /* DevelopmentBranchAlerter.swift */, + ); + path = DevelopmentBranchAlerter; + sourceTree = ""; + }; + DB0BB002000000000000000A /* ReleaseNotes */ = { + isa = PBXGroup; + children = ( + DB0BB002000000000000000B /* ReleaseNotes.swift */, + DB0BB002000000000000000D /* ReleaseNotesService.swift */, + ); + path = ReleaseNotes; + sourceTree = ""; + }; + DC01A00C2E9F100000000003 /* Devices */ = { + isa = PBXGroup; + children = ( + DC01A00A2E9F100000000001 /* DeviceCatalog.swift */, + ); + path = Devices; + sourceTree = ""; + }; DD07CA5A2CE950B9002D45A9 /* MealPreset */ = { isa = PBXGroup; children = ( @@ -4492,23 +4508,6 @@ path = View; sourceTree = ""; }; - DB0BA0010000000000000001 /* DevelopmentBranchAlerter */ = { - isa = PBXGroup; - children = ( - DB0BA0010000000000000002 /* DevelopmentBranchAlerter.swift */, - ); - path = DevelopmentBranchAlerter; - sourceTree = ""; - }; - DB0BB002000000000000000A /* ReleaseNotes */ = { - isa = PBXGroup; - children = ( - DB0BB002000000000000000B /* ReleaseNotes.swift */, - DB0BB002000000000000000D /* ReleaseNotesService.swift */, - ); - path = ReleaseNotes; - sourceTree = ""; - }; DDA9AC072D67291600E6F1A9 /* AppVersionChecker */ = { isa = PBXGroup; children = ( @@ -4796,6 +4795,19 @@ path = View; sourceTree = ""; }; + FAB1E00000000000000000A0 /* Parity */ = { + isa = PBXGroup; + children = ( + FAB1E00000000000000000B1 /* ParityHarness.swift */, + FAB1E00000000000000000B2 /* ParityInputs.swift */, + FAB1E00000000000000000B3 /* ParityScenarios.swift */, + FAB1E00000000000000000B4 /* ParityGoldenTests.swift */, + 7A11AC0DE000000000000160 /* WallClockParityTests.swift */, + FAB1E00000000000000000B5 /* ParityPerformanceTests.swift */, + ); + path = Parity; + sourceTree = ""; + }; FDB1D1005DA54C048E622761 /* QuickPickTreatments */ = { isa = PBXGroup; children = ( @@ -5480,7 +5492,6 @@ 7A11AC0DE000000000000110 /* HomeRootView+BottomControls.swift in Sources */, 7A11AC0DE00000000000010E /* HomeRootView+MealPanel.swift in Sources */, 7A11AC0DE00000000000010D /* HomeRootView+Header.swift in Sources */, - 584C79A91D034426A1DE60CB /* SlideToConfirmView.swift in Sources */, 38E98A2925F52C9300C0CED0 /* Error+Extensions.swift in Sources */, 3E62C7822F54CC1B00433237 /* BolusDisplayThreshold.swift in Sources */, 38EA05DA261F6E7C0064E39B /* SimpleLogReporter.swift in Sources */, @@ -6744,6 +6755,17 @@ }; /* End XCConfigurationList section */ +/* Begin XCLocalSwiftPackageReference section */ + 5E12FE112EBC0000000000A0 /* XCLocalSwiftPackageReference "LoopAlgorithm" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = LoopAlgorithm; + }; + 5E12FE112EBC0000000000B0 /* XCLocalSwiftPackageReference "RoundWhiteDiscKit" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = RoundWhiteDiscKit; + }; +/* End XCLocalSwiftPackageReference section */ + /* Begin XCRemoteSwiftPackageReference section */ 3811DE0E25C9D37700A708ED /* XCRemoteSwiftPackageReference "Swinject" */ = { isa = XCRemoteSwiftPackageReference; @@ -6827,17 +6849,6 @@ }; /* End XCRemoteSwiftPackageReference section */ -/* Begin XCLocalSwiftPackageReference section */ - 5E12FE112EBC0000000000A0 /* XCLocalSwiftPackageReference "LoopAlgorithm" */ = { - isa = XCLocalSwiftPackageReference; - relativePath = LoopAlgorithm; - }; - 5E12FE112EBC0000000000B0 /* XCLocalSwiftPackageReference "RoundWhiteDiscKit" */ = { - isa = XCLocalSwiftPackageReference; - relativePath = RoundWhiteDiscKit; - }; -/* End XCLocalSwiftPackageReference section */ - /* Begin XCSwiftPackageProductDependency section */ 3811DE0F25C9D37700A708ED /* Swinject */ = { isa = XCSwiftPackageProductDependency; @@ -6874,6 +6885,16 @@ package = 3E28F2A92EB5337F00FB9EEB /* XCRemoteSwiftPackageReference "connectiq-companion-app-sdk-ios" */; productName = ConnectIQ; }; + 5E12FE112EBC0000000000A1 /* LoopAlgorithm */ = { + isa = XCSwiftPackageProductDependency; + package = 5E12FE112EBC0000000000A0 /* XCLocalSwiftPackageReference "LoopAlgorithm" */; + productName = LoopAlgorithm; + }; + 5E12FE112EBC0000000000B1 /* RoundWhiteDiscKit */ = { + isa = XCSwiftPackageProductDependency; + package = 5E12FE112EBC0000000000B0 /* XCLocalSwiftPackageReference "RoundWhiteDiscKit" */; + productName = RoundWhiteDiscKit; + }; B958F1B62BA0711600484851 /* MKRingProgressView */ = { isa = XCSwiftPackageProductDependency; package = B958F1B52BA0711600484851 /* XCRemoteSwiftPackageReference "MKRingProgressView" */; @@ -6889,16 +6910,6 @@ package = DD868FD92E381E1C005D3308 /* XCRemoteSwiftPackageReference "Swift-JWT" */; productName = SwiftJWT; }; - 5E12FE112EBC0000000000A1 /* LoopAlgorithm */ = { - isa = XCSwiftPackageProductDependency; - package = 5E12FE112EBC0000000000A0 /* XCLocalSwiftPackageReference "LoopAlgorithm" */; - productName = LoopAlgorithm; - }; - 5E12FE112EBC0000000000B1 /* RoundWhiteDiscKit */ = { - isa = XCSwiftPackageProductDependency; - package = 5E12FE112EBC0000000000B0 /* XCLocalSwiftPackageReference "RoundWhiteDiscKit" */; - productName = RoundWhiteDiscKit; - }; /* End XCSwiftPackageProductDependency section */ /* Begin XCVersionGroup section */ diff --git a/Trio.xcworkspace/contents.xcworkspacedata b/Trio.xcworkspace/contents.xcworkspacedata index 7239825e9f..edc3da0af8 100644 --- a/Trio.xcworkspace/contents.xcworkspacedata +++ b/Trio.xcworkspace/contents.xcworkspacedata @@ -43,7 +43,7 @@ - + + diff --git a/Trio/Sources/APS/CGM/PluginSource.swift b/Trio/Sources/APS/CGM/PluginSource.swift index 1b97ed09e8..49671c0232 100644 --- a/Trio/Sources/APS/CGM/PluginSource.swift +++ b/Trio/Sources/APS/CGM/PluginSource.swift @@ -8,6 +8,7 @@ import LibreLoop import LibreTransmitter import LoopKit import LoopKitUI +import SyaiKit final class PluginSource: GlucoseSource { private let processQueue = DispatchQueue(label: "CGMPluginSource.processQueue") @@ -306,6 +307,10 @@ extension PluginSource: CGMManagerDelegate { sensorActivatedAt = cgmTransmitterManager.state.activatedAt sensorStartDate = cgmTransmitterManager.state.activatedAt sensorTransmitterID = cgmTransmitterManager.state.bleNameString + } else if let cgmTransmitterManager = cgmManager as? SyaiCGMManager { + sensorActivatedAt = cgmTransmitterManager.state.activatedAt + sensorStartDate = cgmTransmitterManager.state.activatedAt + sensorTransmitterID = cgmTransmitterManager.state.mac } // isDisplayOnly means "shifted for visual consistency after calibration" diff --git a/Trio/Sources/APS/Devices/DeviceCatalog.swift b/Trio/Sources/APS/Devices/DeviceCatalog.swift index 195eb8f63b..63672e03f1 100644 --- a/Trio/Sources/APS/Devices/DeviceCatalog.swift +++ b/Trio/Sources/APS/Devices/DeviceCatalog.swift @@ -22,6 +22,8 @@ import MockKit import MockKitUI import ObjectiveC import OmnipodKit +import SyaiKit +import SyaiKitUI import UIKit /// Single source of truth for every CGM and pump Trio can pair with. @@ -45,6 +47,7 @@ enum DeviceManufacturer: CaseIterable { case roche case senseonics case sooil + case syai case otherSources case simulator @@ -59,6 +62,7 @@ enum DeviceManufacturer: CaseIterable { case .roche: return "Roche" case .senseonics: return "Senseonics" case .sooil: return "SOOIL" + case .syai: return "Syai" case .otherSources: return String(localized: "Other Sources", comment: "Device picker section for data relays") case .simulator: return String(localized: "Simulator", comment: "Device picker section for simulated devices") } @@ -389,6 +393,13 @@ extension DeviceCatalog { icon: .managerBundle(asset: "transmitter") ), + CGMCatalogEntry( + .managed(SyaiCGMManager.self), + manufacturer: .syai, + name: "Syai Ultra", + icon: .uiBundle(identifier: "org.loopkit.SyaiKitUI", asset: "sensor") + ), + CGMCatalogEntry(.native(.nightscout), manufacturer: .otherSources, icon: .trio(asset: "owl")), CGMCatalogEntry(.native(.xdrip), manufacturer: .otherSources), diff --git a/Trio/Sources/Modules/Home/HomeStateModel.swift b/Trio/Sources/Modules/Home/HomeStateModel.swift index f595ffe9c5..7841333110 100644 --- a/Trio/Sources/Modules/Home/HomeStateModel.swift +++ b/Trio/Sources/Modules/Home/HomeStateModel.swift @@ -13,6 +13,7 @@ import LoopKitUI import Observation import SwiftDate import SwiftUI +import SyaiKit extension Home { @Observable final class StateModel: BaseStateModel { @@ -923,6 +924,9 @@ extension Home { case let accuChek as AccuChekCgmManager: return accuChek.state.cgmEndTime + case let syai as SyaiCGMManager: + return syai.sensorExpirationDate + default: return nil } @@ -968,6 +972,9 @@ extension Home { } return nil + case let syai as SyaiCGMManager: + return syai.sensorWarmupEndDate + default: return nil } diff --git a/scripts/swiftformat.sh b/scripts/swiftformat.sh index c16ee68bbb..a9811027e4 100755 --- a/scripts/swiftformat.sh +++ b/scripts/swiftformat.sh @@ -122,5 +122,6 @@ trailingClosures \ --exclude RoundWhiteDiscKit \ --exclude LoopAlgorithm \ --exclude AccuChekKit \ ---exclude EversenseKit +--exclude EversenseKit \ +--exclude SyaiKit From 78288eb7edc72d9ba757df115df1ed8b107057d2 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 17 Oct 2026 03:54:02 +0000 Subject: [PATCH 06/41] Use pump icon with accessibility label for pump-UI boluses in History Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01FL5GiaxDEST1SqpMm7pnSM --- Trio/Sources/Localizations/Main/Localizable.xcstrings | 6 +++--- .../Modules/History/View/HistoryRootView+Treatments.swift | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Trio/Sources/Localizations/Main/Localizable.xcstrings b/Trio/Sources/Localizations/Main/Localizable.xcstrings index 6d039ce55f..52b2124517 100644 --- a/Trio/Sources/Localizations/Main/Localizable.xcstrings +++ b/Trio/Sources/Localizations/Main/Localizable.xcstrings @@ -241059,6 +241059,9 @@ } } }, + "Programmed on pump" : { + "comment" : "Accessibility label for bolus programmed on the pump itself" + }, "Protein / Fat" : { "comment" : "Treatment type", "localizations" : { @@ -244738,9 +244741,6 @@ } } }, - "Pump UI" : { - "comment" : "Bolus programmed on the pump itself" - }, "Purple = Above Range" : { "localizations" : { "bg" : { diff --git a/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift b/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift index 0fcfbd2ccc..232f2277df 100644 --- a/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift +++ b/Trio/Sources/Modules/History/View/HistoryRootView+Treatments.swift @@ -63,8 +63,14 @@ extension History.RootView { Text(String(localized: "External", comment: "External Insulin")).foregroundColor(.secondary) } if bolus.isProgrammedByPumpUI { - Text(String(localized: "Pump UI", comment: "Bolus programmed on the pump itself")) + Image(systemName: "keyboard.onehanded.left") .foregroundColor(.secondary) + .accessibilityLabel( + String( + localized: "Programmed on pump", + comment: "Accessibility label for bolus programmed on the pump itself" + ) + ) } } else if let tempBasal = item.tempBasal, let rate = tempBasal.rate { Image(systemName: "circle.fill").foregroundColor(Color.insulin.opacity(0.4)) From b29cc886fccd228c86ebe1126fddb0cf884e1c00 Mon Sep 17 00:00:00 2001 From: Ostap Korkuna Date: Sun, 18 Oct 2026 17:34:34 -0700 Subject: [PATCH 07/41] Replace carb entry in a single transaction Editing a meal deleted the old entry and inserted the replacement as two separate Core Data commits. If the insert failed the delete was already durable, and because the save error was only printed the edit still reported success, so the meal was dropped locally and then from Nightscout, Apple Health and Tidepool. A crash between the two commits had the same effect. Add CarbsStorage.replaceCarbs, which deletes the old meal root and its carb equivalents and inserts the new ones on one context, committed by a single save(). Deletes and inserts go through the context rather than batch requests, which would commit on their own. CarbEntryMutationService uses it for replaceMeal, so a failure now leaves the old meal in place and skips the remote deletes. --- .../Storage/CarbEntryMutationService.swift | 4 +- Trio/Sources/APS/Storage/CarbsStorage.swift | 103 ++++++++++-- .../CoreDataTests/CarbsStorageTests.swift | 149 ++++++++++++++++++ 3 files changed, 238 insertions(+), 18 deletions(-) diff --git a/Trio/Sources/APS/Storage/CarbEntryMutationService.swift b/Trio/Sources/APS/Storage/CarbEntryMutationService.swift index 235c7642e5..48e46fd477 100644 --- a/Trio/Sources/APS/Storage/CarbEntryMutationService.swift +++ b/Trio/Sources/APS/Storage/CarbEntryMutationService.swift @@ -62,8 +62,8 @@ final class BaseCarbEntryMutationService: CarbEntryMutationService, Injectable { } let snapshot = try await localMutations.run { let snapshot = try await self.snapshotRoot(rootObjectID) - await self.carbsStorage.deleteCarbsEntryStored(rootObjectID) - try await self.carbsStorage.storeCarbs([replacement], areFetchedFromRemote: false) + // One transaction, so a failed insert cannot leave the meal deleted without a replacement. + try await self.carbsStorage.replaceCarbs(rootObjectID, with: replacement) return snapshot } let failures = await deleteFromServices(snapshot) diff --git a/Trio/Sources/APS/Storage/CarbsStorage.swift b/Trio/Sources/APS/Storage/CarbsStorage.swift index 148c2c78d0..3b396660cb 100644 --- a/Trio/Sources/APS/Storage/CarbsStorage.swift +++ b/Trio/Sources/APS/Storage/CarbsStorage.swift @@ -13,6 +13,8 @@ protocol CarbsStorage { func storeCarbs(_ carbs: [CarbsEntry], areFetchedFromRemote: Bool) async throws /// Builds a single, real, locally-entered carb entry ready to pass to `storeCarbs`. func makeCarbEntry(carbs: Decimal, date: Date) -> CarbsEntry + /// Swaps a stored meal in one Core Data transaction. + func replaceCarbs(_ treatmentObjectID: NSManagedObjectID, with entry: CarbsEntry) async throws func deleteCarbsEntryStored(_ treatmentObjectID: NSManagedObjectID) async func syncDate() -> Date func getCarbsForAlgorithm(additionalCarbs: Decimal?, carbsDate: Date?) async throws -> [CarbsEntry] @@ -294,22 +296,7 @@ final class BaseCarbsStorage: CarbsStorage, Injectable { let context = makeContext() context.name = "saveCarbsToCoreData" await context.perform { - let newItem = CarbEntryStored(context: context) - newItem.date = entry.actualDate ?? entry.createdAt - newItem.carbs = Double(truncating: NSDecimalNumber(decimal: entry.carbs)) - newItem.fat = Double(truncating: NSDecimalNumber(decimal: entry.fat ?? 0)) - newItem.protein = Double(truncating: NSDecimalNumber(decimal: entry.protein ?? 0)) - newItem.note = entry.note - // Nightscout `_id` values are not UUIDs and are replaced. - newItem.id = entry.id.flatMap(UUID.init(uuidString:)) ?? UUID() - newItem.isFPU = false - newItem.isUploadedToNS = areFetchedFromRemote ? true : false - newItem.isUploadedToHealth = false - newItem.isUploadedToTidepool = false - - if entry.fat != nil, entry.protein != nil, let fpuId = entry.fpuID { - newItem.fpuID = UUID(uuidString: fpuId) - } + self.insertCarbEntry(entry, into: context, areFetchedFromRemote: areFetchedFromRemote) do { guard context.hasChanges else { return } @@ -320,6 +307,90 @@ final class BaseCarbsStorage: CarbsStorage, Injectable { } } + /// Inserts a meal root row into `context` without saving, so callers decide when to commit. + private func insertCarbEntry(_ entry: CarbsEntry, into context: NSManagedObjectContext, areFetchedFromRemote: Bool) { + let newItem = CarbEntryStored(context: context) + newItem.date = entry.actualDate ?? entry.createdAt + newItem.carbs = Double(truncating: NSDecimalNumber(decimal: entry.carbs)) + newItem.fat = Double(truncating: NSDecimalNumber(decimal: entry.fat ?? 0)) + newItem.protein = Double(truncating: NSDecimalNumber(decimal: entry.protein ?? 0)) + newItem.note = entry.note + // Nightscout `_id` values are not UUIDs and are replaced. + newItem.id = entry.id.flatMap(UUID.init(uuidString:)) ?? UUID() + newItem.isFPU = false + newItem.isUploadedToNS = areFetchedFromRemote ? true : false + newItem.isUploadedToHealth = false + newItem.isUploadedToTidepool = false + + if entry.fat != nil, entry.protein != nil, let fpuId = entry.fpuID { + newItem.fpuID = UUID(uuidString: fpuId) + } + } + + /// Inserts a locally created carb equivalent row into `context` without saving. + private func insertCarbEquivalent(_ entry: CarbsEntry, into context: NSManagedObjectContext) { + let newItem = CarbEntryStored(context: context) + newItem.date = entry.actualDate + newItem.carbs = Double(truncating: NSDecimalNumber(decimal: entry.carbs)) + newItem.id = entry.id.flatMap(UUID.init(uuidString:)) + newItem.fpuID = entry.fpuID.flatMap(UUID.init(uuidString:)) + newItem.isFPU = true + newItem.isUploadedToNS = false + // do NOT set Health and Tidepool flags to ensure they will NOT be uploaded + } + + /// Replaces a stored meal, together with any carb equivalents sharing its `fpuID`. + /// + /// The deletes and the inserts go through the same context and are committed by a single `save()`. + /// A failure therefore leaves the old meal in place rather than deleting it without a replacement. + func replaceCarbs(_ treatmentObjectID: NSManagedObjectID, with entry: CarbsEntry) async throws { + var carbEquivalents: [CarbsEntry] = [] + if let fat = entry.fat, let protein = entry.protein, fat > 0 || protein > 0 { + (carbEquivalents, _) = processFPU( + entries: [entry], + fat: fat, + protein: protein, + createdAt: entry.createdAt, + actualDate: entry.actualDate + ) + } + + let context = makeContext() + context.name = "replaceCarbs" + context.transactionAuthor = "replaceCarbs" + + // A fetch reads the store, so rows removed by a batch delete are not served from the row cache. + let rootRequest: NSFetchRequest = CarbEntryStored.fetchRequest() + rootRequest.predicate = NSPredicate(format: "SELF == %@", treatmentObjectID) + rootRequest.fetchLimit = 1 + + try await context.perform { + guard let storedEntry = try context.fetch(rootRequest).first else { + throw CoreDataError.fetchError(function: #function, file: #file) + } + + // Deleted through the context instead of an NSBatchDeleteRequest, which would commit on its own. + if let fpuID = storedEntry.fpuID { + let familyRequest: NSFetchRequest = CarbEntryStored.fetchRequest() + familyRequest.predicate = NSPredicate(format: "fpuID == %@", fpuID as CVarArg) + for entryToDelete in try context.fetch(familyRequest) { + context.delete(entryToDelete) + } + } else { + context.delete(storedEntry) + } + + self.insertCarbEntry(entry, into: context, areFetchedFromRemote: false) + for carbEquivalent in carbEquivalents { + self.insertCarbEquivalent(carbEquivalent, into: context) + } + + try context.save() + } + + updateSubject.send(()) + } + private func saveFPUToCoreDataAsBatchInsert(entries: [CarbsEntry], areFetchedFromRemote: Bool) async { let commonFPUID = UUID( uuidString: entries.first?.fpuID ?? UUID() diff --git a/TrioTests/CoreDataTests/CarbsStorageTests.swift b/TrioTests/CoreDataTests/CarbsStorageTests.swift index 3a6d7f58d6..0c8337cf4d 100644 --- a/TrioTests/CoreDataTests/CarbsStorageTests.swift +++ b/TrioTests/CoreDataTests/CarbsStorageTests.swift @@ -537,4 +537,153 @@ import Testing #expect(!children.isEmpty) #expect(children.allSatisfy { $0.id == fpuID && $0.fpuID == fpuID }) } + + // MARK: - replaceCarbs + + private func allStoredRows() async throws -> [CarbEntryStored] { + guard let rows = try await coreDataStack.fetchEntitiesAsync( + ofType: CarbEntryStored.self, + onContext: testContext, + predicate: NSPredicate(format: "TRUEPREDICATE"), + key: "date", + ascending: true + ) as? [CarbEntryStored] else { + throw TestError("Failed to fetch stored rows") + } + return rows + } + + @Test("Replace swaps the stored values") func testReplaceCarbs() async throws { + let original = CarbsEntry( + id: UUID().uuidString, createdAt: Date(), actualDate: Date(), carbs: 25, fat: nil, protein: nil, + note: "Before edit", enteredBy: "Test", isFPU: false, fpuID: nil + ) + try await storage.storeCarbs([original], areFetchedFromRemote: false) + guard let objectID = try await allStoredRows().first?.objectID else { + throw TestError("Failed to get stored entry's ObjectID") + } + + let editedDate = Date(timeIntervalSince1970: 1_700_003_000) + let edited = CarbsEntry( + id: UUID().uuidString, createdAt: Date(), actualDate: editedDate, carbs: 45, fat: 0, protein: 0, + note: "After edit", enteredBy: "Test", isFPU: false, fpuID: nil + ) + try await storage.replaceCarbs(objectID, with: edited) + + let rows = try await allStoredRows() + #expect(rows.count == 1, "Edit must not duplicate or drop the entry") + #expect(rows.first?.carbs == 45) + #expect(rows.first?.note == "After edit") + #expect(rows.first?.date == editedDate) + #expect(rows.first?.id?.uuidString == edited.id) + } + + @Test("Replace rebuilds the carb equivalents") func testReplaceCarbsRebuildsCarbEquivalents() async throws { + let originalFpuID = UUID().uuidString + let baseDate = Date(timeIntervalSince1970: 1_700_002_000) + let original = CarbsEntry( + id: UUID().uuidString, createdAt: baseDate, actualDate: baseDate, carbs: 30, fat: 200, protein: 200, + note: "Before edit", enteredBy: "Test", isFPU: false, fpuID: originalFpuID + ) + try await storage.storeCarbs([original], areFetchedFromRemote: false) + guard let objectID = try await allStoredRows().first(where: { !$0.isFPU })?.objectID else { + throw TestError("Failed to get stored entry's ObjectID") + } + + // Fat and protein are reduced, so the carb equivalents have to be recalculated + let editedFpuID = UUID().uuidString + let edited = CarbsEntry( + id: UUID().uuidString, createdAt: baseDate, actualDate: baseDate, carbs: 30, fat: 50, protein: 100, + note: "After edit", enteredBy: "Test", isFPU: false, fpuID: editedFpuID + ) + try await storage.replaceCarbs(objectID, with: edited) + + let rows = try await allStoredRows() + #expect(rows.allSatisfy { $0.fpuID?.uuidString != originalFpuID }, "Old meal and its carb equivalents are gone") + + let roots = rows.filter { !$0.isFPU } + #expect(roots.count == 1, "Edit must leave exactly one meal root") + #expect(roots.first?.fat == 50) + #expect(roots.first?.protein == 100) + #expect(roots.first?.fpuID?.uuidString == editedFpuID) + + // fat=50g + protein=100g -> 850 kcal -> (850/10) * 0.5 = 42 equivalents -> two entries of 21g + let carbEquivalents = rows.filter(\.isFPU) + #expect(carbEquivalents.map { Int($0.carbs) } == [21, 21]) + #expect(carbEquivalents.allSatisfy { $0.fpuID?.uuidString == editedFpuID }) + #expect(carbEquivalents.allSatisfy { $0.isUploadedToNS == false }) + } + + @Test("Replace commits the delete and the insert in one transaction") func testReplaceCarbsIsAtomic() async throws { + let original = CarbsEntry( + id: UUID().uuidString, createdAt: Date(), actualDate: Date(), carbs: 25, fat: nil, protein: nil, + note: nil, enteredBy: "Test", isFPU: false, fpuID: nil + ) + try await storage.storeCarbs([original], areFetchedFromRemote: false) + guard let objectID = try await allStoredRows().first?.objectID else { + throw TestError("Failed to get stored entry's ObjectID") + } + + let saves = SaveCounter() + let observer = NotificationCenter.default.addObserver( + forName: .NSManagedObjectContextDidSave, + object: testContext, + queue: nil + ) { _ in saves.increment() } + defer { NotificationCenter.default.removeObserver(observer) } + + let edited = CarbsEntry( + id: UUID().uuidString, createdAt: Date(), actualDate: Date(), carbs: 45, fat: 0, protein: 0, + note: nil, enteredBy: "Test", isFPU: false, fpuID: nil + ) + try await storage.replaceCarbs(objectID, with: edited) + + #expect(saves.count == 1, "A separate delete commit would leave the meal gone if the insert then failed") + } + + @Test("Replace of a missing meal throws and keeps the other entries") func testReplaceCarbsMissingRoot() async throws { + let other = CarbsEntry( + id: UUID().uuidString, createdAt: Date(), actualDate: Date(), carbs: 12, fat: nil, protein: nil, + note: "Keep me", enteredBy: "Test", isFPU: false, fpuID: nil + ) + let doomed = CarbsEntry( + id: UUID().uuidString, createdAt: Date(), actualDate: Date().addingTimeInterval(60), carbs: 25, + fat: nil, protein: nil, note: nil, enteredBy: "Test", isFPU: false, fpuID: nil + ) + try await storage.storeCarbs([other], areFetchedFromRemote: false) + try await storage.storeCarbs([doomed], areFetchedFromRemote: false) + guard let objectID = try await allStoredRows().first(where: { $0.id?.uuidString == doomed.id })?.objectID else { + throw TestError("Failed to get stored entry's ObjectID") + } + await storage.deleteCarbsEntryStored(objectID) + + await #expect(throws: CoreDataError.self) { + let replacement = CarbsEntry( + id: UUID().uuidString, createdAt: Date(), actualDate: Date(), carbs: 99, fat: nil, protein: nil, + note: nil, enteredBy: "Test", isFPU: false, fpuID: nil + ) + try await storage.replaceCarbs(objectID, with: replacement) + } + + let rows = try await allStoredRows() + #expect(rows.count == 1) + #expect(rows.first?.id?.uuidString == other.id, "A failed replace must not touch other meals") + } +} + +private final class SaveCounter: @unchecked Sendable { + private let lock = NSLock() + private var value = 0 + + func increment() { + lock.lock() + value += 1 + lock.unlock() + } + + var count: Int { + lock.lock() + defer { lock.unlock() } + return value + } } From 75e44e2ef3bdf65268d384f9a740676b629ddc02 Mon Sep 17 00:00:00 2001 From: Luka Zivkovic Date: Mon, 19 Oct 2026 15:59:28 +0200 Subject: [PATCH 08/41] Fix inverted SMB low temp rate for sub 30m zero temps --- .../DetermineBasal/DosingEngine.swift | 2 +- .../DetermineBasalAggressiveDosingTests.swift | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift b/Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift index 00da8fbd6b..5e131be44d 100644 --- a/Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift +++ b/Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift @@ -799,7 +799,7 @@ enum DosingEngine { durationRequired = min(60, max(0, durationRequired)) } else { // Note: we're using the fully adjusted basal here - smbLowTempRequired = (basal * durationRequired / 30).jsRounded(scale: 2) + smbLowTempRequired = (basal * (30 - durationRequired) / 30).jsRounded(scale: 2) durationRequired = 30 } diff --git a/TrioTests/OpenAPSSwiftTests/DetermineBasalAggressiveDosingTests.swift b/TrioTests/OpenAPSSwiftTests/DetermineBasalAggressiveDosingTests.swift index da2ed87f78..8714e480d1 100644 --- a/TrioTests/OpenAPSSwiftTests/DetermineBasalAggressiveDosingTests.swift +++ b/TrioTests/OpenAPSSwiftTests/DetermineBasalAggressiveDosingTests.swift @@ -1029,7 +1029,13 @@ import Testing #expect(result.determination.duration == 60) } - @Test("should set low temp if durationReq < 30") func testSetLowTemp() throws { + @Test("should set low temp if durationReq < 30", arguments: [ + (Decimal(95.85), Decimal(83) / 100), // durationRequired = 5m, rate = 1.0 * (30 - 5) / 30 = 0.83 + (Decimal(91.65), Decimal(67) / 100), // durationRequired = 10m, rate = 1.0 * (30 - 10) / 30 = 0.67 + (Decimal(87.5), Decimal(50) / 100), // durationRequired = 15m, rate = 1.0 * (30 - 15) / 30 = 0.50 + (Decimal(79.15), Decimal(17) / 100), // durationRequired = 25m, rate = 1.0 * (30 - 25) / 30 = 0.17 + (Decimal(75.85), Decimal(3) / 100) // durationRequired = 29m, rate = 1.0 * (30 - 29) / 30 = 0.03 + ]) func testSetLowTemp(avgGlucose: Decimal, expectedRate: Decimal) throws { var profile = Profile() profile.currentBasal = 1.0 profile.maxSMBBasalMinutes = 30 @@ -1060,22 +1066,17 @@ import Testing lastTemp: nil )] - // worstCaseInsulinReq needs to result in durationReq = 15 - // 15 = 60 * worst / 1.0 => worst = 0.25 - // worst = (100 - avg)/50 => avg = 87.5 - let result = try callDetermineSMBDelivery( insulinRequired: 1.0, profile: profile, iobData: iobData, basal: 1.0, - naiveEventualGlucose: 87.5, - minIOBForecastedGlucose: 87.5 + naiveEventualGlucose: avgGlucose, + minIOBForecastedGlucose: avgGlucose ) - // Rate = basal * 15/30 = 1.0 * 0.5 = 0.5 #expect(result.shouldSetTempBasal == true) - #expect(result.determination.rate == 0.5) + #expect(result.determination.rate == expectedRate) #expect(result.determination.duration == 30) } From 547abe44ba34b2b67ee0470ca6af5ef92d16804a Mon Sep 17 00:00:00 2001 From: Luka Zivkovic Date: Mon, 19 Oct 2026 17:10:29 +0200 Subject: [PATCH 09/41] Fix OpenAPS golden parity test --- .../Parity/goldens/autosens-resistance/determination.json | 4 ++-- .../Parity/goldens/dynamic-isf-sigmoid/determination.json | 4 ++-- .../Parity/goldens/override-active/determination.json | 4 ++-- .../Parity/goldens/post-meal-cob-active/determination.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/TrioTests/OpenAPSSwiftTests/Parity/goldens/autosens-resistance/determination.json b/TrioTests/OpenAPSSwiftTests/Parity/goldens/autosens-resistance/determination.json index 9cacae7a07..995ec75d7f 100644 --- a/TrioTests/OpenAPSSwiftTests/Parity/goldens/autosens-resistance/determination.json +++ b/TrioTests/OpenAPSSwiftTests/Parity/goldens/autosens-resistance/determination.json @@ -145,8 +145,8 @@ 126 ] }, - "rate" : 0.27, - "reason" : "Autosens ratio: 1, ISF: 55→55, COB: 0, Dev: 37, BGI: -4, CR: 12, Target: 95, minPredBG 125, minGuardBG 134, IOBpredBG 108, UAMpredBG 135; Eventual BG 135 >= 95, insulinReq 0.55; setting 30m low temp of 0.27U/h. Microbolusing 0.2U. ", + "rate" : 0.63, + "reason" : "Autosens ratio: 1, ISF: 55→55, COB: 0, Dev: 37, BGI: -4, CR: 12, Target: 95, minPredBG 125, minGuardBG 134, IOBpredBG 108, UAMpredBG 135; Eventual BG 135 >= 95, insulinReq 0.55; setting 30m low temp of 0.63U/h. Microbolusing 0.2U. ", "received" : false, "sensitivityRatio" : 1, "threshold" : 68, diff --git a/TrioTests/OpenAPSSwiftTests/Parity/goldens/dynamic-isf-sigmoid/determination.json b/TrioTests/OpenAPSSwiftTests/Parity/goldens/dynamic-isf-sigmoid/determination.json index 18780ad8c8..b07c975649 100644 --- a/TrioTests/OpenAPSSwiftTests/Parity/goldens/dynamic-isf-sigmoid/determination.json +++ b/TrioTests/OpenAPSSwiftTests/Parity/goldens/dynamic-isf-sigmoid/determination.json @@ -147,8 +147,8 @@ 98 ] }, - "rate" : 0.87, - "reason" : "Autosens ratio: 1.15, ISF: 55→48, COB: 0, Dev: 56, BGI: -4, CR: 12, Target: 95, minPredBG 114, minGuardBG 125, IOBpredBG 104, UAMpredBG 125, Dynamic ISF: On, Sigmoid function, AF: 0.6, Basal ratio: 1.01; Eventual BG 125 >= 95, insulinReq 0.4; setting 30m low temp of 0.87U/h. Microbolusing 0.2U. ", + "rate" : 0.03, + "reason" : "Autosens ratio: 1.15, ISF: 55→48, COB: 0, Dev: 56, BGI: -4, CR: 12, Target: 95, minPredBG 114, minGuardBG 125, IOBpredBG 104, UAMpredBG 125, Dynamic ISF: On, Sigmoid function, AF: 0.6, Basal ratio: 1.01; Eventual BG 125 >= 95, insulinReq 0.4; setting 30m low temp of 0.03U/h. Microbolusing 0.2U. ", "received" : false, "sensitivityRatio" : 1.152552507138643740284, "threshold" : 68, diff --git a/TrioTests/OpenAPSSwiftTests/Parity/goldens/override-active/determination.json b/TrioTests/OpenAPSSwiftTests/Parity/goldens/override-active/determination.json index 91912f3684..69bcbd6064 100644 --- a/TrioTests/OpenAPSSwiftTests/Parity/goldens/override-active/determination.json +++ b/TrioTests/OpenAPSSwiftTests/Parity/goldens/override-active/determination.json @@ -148,8 +148,8 @@ 104 ] }, - "rate" : 0.38, - "reason" : "Autosens ratio: 1, ISF: 42→42, COB: 0, Dev: 54, BGI: -3, CR: 9.2, Target: 90, minPredBG 120, minGuardBG 128, IOBpredBG 112, UAMpredBG 128; Eventual BG 128 >= 90, insulinReq 0.71; setting 30m low temp of 0.38U/h. Microbolusing 0.3U. ", + "rate" : 0.77, + "reason" : "Autosens ratio: 1, ISF: 42→42, COB: 0, Dev: 54, BGI: -3, CR: 9.2, Target: 90, minPredBG 120, minGuardBG 128, IOBpredBG 112, UAMpredBG 128; Eventual BG 128 >= 90, insulinReq 0.71; setting 30m low temp of 0.77U/h. Microbolusing 0.3U. ", "received" : false, "sensitivityRatio" : 1, "threshold" : 65, diff --git a/TrioTests/OpenAPSSwiftTests/Parity/goldens/post-meal-cob-active/determination.json b/TrioTests/OpenAPSSwiftTests/Parity/goldens/post-meal-cob-active/determination.json index 6ac15e90b2..71745075b3 100644 --- a/TrioTests/OpenAPSSwiftTests/Parity/goldens/post-meal-cob-active/determination.json +++ b/TrioTests/OpenAPSSwiftTests/Parity/goldens/post-meal-cob-active/determination.json @@ -196,8 +196,8 @@ 104 ] }, - "rate" : 0.57, - "reason" : "Autosens ratio: 1, ISF: 55→55, COB: 26, Dev: 67, BGI: -4, CR: 12, Target: 95, minPredBG 141, minGuardBG 141, IOBpredBG 114, COBpredBG 168, UAMpredBG 105; Eventual BG 168 >= 95, insulinReq 0.84; setting 30m low temp of 0.57U/h. Microbolusing 0.4U. ", + "rate" : 0.33, + "reason" : "Autosens ratio: 1, ISF: 55→55, COB: 26, Dev: 67, BGI: -4, CR: 12, Target: 95, minPredBG 141, minGuardBG 141, IOBpredBG 114, COBpredBG 168, UAMpredBG 105; Eventual BG 168 >= 95, insulinReq 0.84; setting 30m low temp of 0.33U/h. Microbolusing 0.4U. ", "received" : false, "sensitivityRatio" : 1, "threshold" : 68, From 915881e60ef24d6b31140364e43271b4a78f206e Mon Sep 17 00:00:00 2001 From: Lamercho <33007090+Lamercho@users.noreply.github.com> Date: Tue, 20 Oct 2026 01:17:29 +0300 Subject: [PATCH 10/41] Close the Edit Override form when the Nightscout profile upload fails Saving an edited override awaited uploadProfiles() before it disabled the previous active override, refreshed the configuration and dismissed the form. When the upload threw (e.g. unknown host, non-200 reply), the edit was saved but the form stayed open and the follow-up steps never ran. Upload the profiles after the dismiss, in their own do/catch, and log the error like the other profile editors do. Fixes #1601 --- .../View/Overrides/EditOverrideForm.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Trio/Sources/Modules/Adjustments/View/Overrides/EditOverrideForm.swift b/Trio/Sources/Modules/Adjustments/View/Overrides/EditOverrideForm.swift index 274e0cac18..1113f04471 100644 --- a/Trio/Sources/Modules/Adjustments/View/Overrides/EditOverrideForm.swift +++ b/Trio/Sources/Modules/Adjustments/View/Overrides/EditOverrideForm.swift @@ -520,8 +520,6 @@ struct EditOverrideForm: View { guard moc.hasChanges else { return } try moc.save() - try await state.nightscoutManager.uploadProfiles() - // Disable previous active Override if let currentActiveOverride = state.currentActiveOverride { Task { @@ -536,6 +534,16 @@ struct EditOverrideForm: View { hasChanges = false presentationMode.wrappedValue.dismiss() + + // Upload after dismiss, so a Nightscout error does not keep the form open + do { + try await state.nightscoutManager.uploadProfiles() + } catch { + debug( + .default, + "\(DebuggingIdentifiers.failed) failed to upload profiles to Nightscout: \(error)" + ) + } } catch { debugPrint("\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to edit Override") } From 6b94bd0a02d17c516b9c914cf23a38cdfbfb34a7 Mon Sep 17 00:00:00 2001 From: Luka Zivkovic Date: Tue, 20 Oct 2026 10:35:43 +0200 Subject: [PATCH 11/41] Document intentional deviation from oref JS in SMB low temp --- .../Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift b/Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift index 5e131be44d..ce6bb90952 100644 --- a/Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift +++ b/Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DosingEngine.swift @@ -799,6 +799,9 @@ enum DosingEngine { durationRequired = min(60, max(0, durationRequired)) } else { // Note: we're using the fully adjusted basal here + // Intentional deviation from oref JS (basal * durationReq / 30) as that formula is, + // inverted, so a longer required suspension gets a higher rate instead of a lower one. + // See https://github.com/nightscout/Trio/issues/1359 smbLowTempRequired = (basal * (30 - durationRequired) / 30).jsRounded(scale: 2) durationRequired = 30 } From d78bc821333ed81136d56ccc500efdc16c3598ce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 20 Oct 2026 14:12:53 +0000 Subject: [PATCH 12/41] CI: Bump APP_DEV_VERSION to 1.0.2.15 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 19bcffdc6f..7344440859 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.14 +APP_DEV_VERSION = 1.0.2.15 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From 0c690f14346ce22fba446766d4c2cb2de41f48fe Mon Sep 17 00:00:00 2001 From: dnzxy <48965855+dnzxy@users.noreply.github.com> Date: Thu, 22 Oct 2026 21:52:13 +0200 Subject: [PATCH 13/41] Update submodules to current upstream - G7SensorKit: flag unusable readings as a sensor issue - OmnipodKit: shared signal-loss test, simplified PKA view - EversenseKit: 365 GetTxCertificate retry with inverted tx_flags - LoopAlgorithm: per-point correction range, emulation options - Pin G7SensorKit to feat/trio-g7-direct in the update script, matching .gitmodules --- EversenseKit | 2 +- G7SensorKit | 2 +- LoopAlgorithm | 2 +- OmnipodKit | 2 +- scripts/define_common_trio.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/EversenseKit b/EversenseKit index e1bb6faf01..e7a1850fd2 160000 --- a/EversenseKit +++ b/EversenseKit @@ -1 +1 @@ -Subproject commit e1bb6faf01bb4bd79872ae6d12787aea8bfe2ad5 +Subproject commit e7a1850fd28665de2e61831d606abc1e4112c545 diff --git a/G7SensorKit b/G7SensorKit index 5c0fc075a3..e99d631ced 160000 --- a/G7SensorKit +++ b/G7SensorKit @@ -1 +1 @@ -Subproject commit 5c0fc075a323ccceca0cec28a1ea094570bdfc5d +Subproject commit e99d631cedc0afe65ea030e72ff95b0b6cc32792 diff --git a/LoopAlgorithm b/LoopAlgorithm index 4604ee36f5..7ef67243ad 160000 --- a/LoopAlgorithm +++ b/LoopAlgorithm @@ -1 +1 @@ -Subproject commit 4604ee36f5acc3d00b2d07331a3a477570761374 +Subproject commit 7ef67243adb0445f5138083c30908a4745eafc83 diff --git a/OmnipodKit b/OmnipodKit index 928bb79503..3de1ac2f49 160000 --- a/OmnipodKit +++ b/OmnipodKit @@ -1 +1 @@ -Subproject commit 928bb79503fc7eaf20fe9b26caa55fded09f7f0c +Subproject commit 3de1ac2f491c95c527f246d0335a3fd825deec8a diff --git a/scripts/define_common_trio.sh b/scripts/define_common_trio.sh index 88c13311ab..287937cb89 100755 --- a/scripts/define_common_trio.sh +++ b/scripts/define_common_trio.sh @@ -23,7 +23,7 @@ TRIO_PROJECTS=( \ loopandlearn:DanaKit:dev \ loopandlearn:dexcom-share-client-swift:dev \ loopandlearn:EversenseKit:dev \ - loopandlearn:G7SensorKit:main \ + loopandlearn:G7SensorKit:feat/trio-g7-direct \ loopandlearn:LibreLoop:legacy-loopkit-compat \ loopandlearn:LibreTransmitter:main \ loopandlearn:LoopKit:trio \ From 9f0a1ccfd35955d115ccc1ed96692da35993b1d6 Mon Sep 17 00:00:00 2001 From: dnzxy <48965855+dnzxy@users.noreply.github.com> Date: Thu, 22 Oct 2026 21:52:26 +0200 Subject: [PATCH 14/41] Bump LoopKit to current trio Carries next-dev's Core Data model (v4 to v8) and its migration. Trio instantiates no LoopKit PersistenceController, so nothing migrates. --- LoopKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LoopKit b/LoopKit index f974241f5f..0d8025b2fa 160000 --- a/LoopKit +++ b/LoopKit @@ -1 +1 @@ -Subproject commit f974241f5f25053d51da3e80833c85b13c387e6f +Subproject commit 0d8025b2fa824b7dd751a52a54a36855ebd799bd From ab11fea572596f9de6d127ee65f7d332e22a4247 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 22 Oct 2026 22:00:01 +0000 Subject: [PATCH 15/41] CI: Bump APP_DEV_VERSION to 1.0.2.16 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 7344440859..ffde9bf4b5 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.15 +APP_DEV_VERSION = 1.0.2.16 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From c9299563974f89a6badab0fffa8101d6db85d25b Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 23 Oct 2026 11:23:51 +0200 Subject: [PATCH 16/41] chore: update syaikit submodule --- SyaiKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SyaiKit b/SyaiKit index f1c1ca6b64..042924be26 160000 --- a/SyaiKit +++ b/SyaiKit @@ -1 +1 @@ -Subproject commit f1c1ca6b6496ca09e10a143eaa7c50ef038c1663 +Subproject commit 042924be26da3403cb8dc4a84de9c6dd4b9e2ebb From 2420af7b838e9bc64f60050f4d6557a0516ba7ef Mon Sep 17 00:00:00 2001 From: dnzxy <48965855+dnzxy@users.noreply.github.com> Date: Fri, 23 Oct 2026 16:35:28 +0200 Subject: [PATCH 17/41] Record the CC0 licence for the alarm sounds --- ACKNOWLEDGEMENTS.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md index 3e583ba60b..37e19d8182 100644 --- a/ACKNOWLEDGEMENTS.md +++ b/ACKNOWLEDGEMENTS.md @@ -4,8 +4,25 @@ Third-party material bundled with Trio, and the terms it is used under. ## Alarm and alert sounds -The themed alarm sets (Acoustic, Electronic) and the one-off tones were -created for Trio by a sound designer and are distributed as part of Trio. +The themed alarm sets (`acoustic_*.caf`, `electronic_*.caf`) and the one-off +tones (`glass_bell.caf`, `harp.caf`, `meow.caf`, `saw_wave.caf`, +`hard_saw_wave.caf`, `sine_wave.caf`, `open_can.caf`, `open_wrapper.caf`) were +created for Trio by **an anonymous diabetes dad and Trio user**. + +- Licence: **Creative Commons Zero 1.0 Universal (CC0 1.0)** — + +- The author states that they are the author of these files, that they hold + the right to license them, and that they contain no third-party material + they cannot license. +- CC0 requires no attribution. The credit above is given at the author's + request; they have asked to remain anonymous. +- Changes made by Trio: the one-off tones were looped by whole repeats to at + least five seconds, so that every alarm sounds for a comparable time. The + themed sets were left exactly as delivered — their length and level are + part of the design, and carry the urgency along with the timbre. + +The spoken alert sounds are generated from third-party voice models and are +*not* covered by that dedication — see below. ## Voice alerts From 7b7121b361076cc63d9b9a67fa55f686b9973680 Mon Sep 17 00:00:00 2001 From: dnzxy <48965855+dnzxy@users.noreply.github.com> Date: Fri, 23 Oct 2026 16:38:13 +0200 Subject: [PATCH 18/41] Bump submodules for the 22 Oct translation round --- CGMBLEKit | 2 +- DanaKit | 2 +- LoopKit | 2 +- MedtrumKit | 2 +- OmnipodKit | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CGMBLEKit b/CGMBLEKit index ea224e771f..776543fca9 160000 --- a/CGMBLEKit +++ b/CGMBLEKit @@ -1 +1 @@ -Subproject commit ea224e771fb3329a957a753296232c62a003a9fe +Subproject commit 776543fca902ad74e3a068a3ec402d62d716a322 diff --git a/DanaKit b/DanaKit index e157a861c6..eadb9fefc0 160000 --- a/DanaKit +++ b/DanaKit @@ -1 +1 @@ -Subproject commit e157a861c691f44c84df6071233edb935c06e7dc +Subproject commit eadb9fefc0e48df6639e1a9de5147ecf6a110caf diff --git a/LoopKit b/LoopKit index 0d8025b2fa..ff8c30e281 160000 --- a/LoopKit +++ b/LoopKit @@ -1 +1 @@ -Subproject commit 0d8025b2fa824b7dd751a52a54a36855ebd799bd +Subproject commit ff8c30e281d04edc2237a18834e5e783ae8c63d3 diff --git a/MedtrumKit b/MedtrumKit index ef866fa68d..c33699595b 160000 --- a/MedtrumKit +++ b/MedtrumKit @@ -1 +1 @@ -Subproject commit ef866fa68db22932271af9bce86372ced8604203 +Subproject commit c33699595b6f636d8ca1bff377a8765df5597c34 diff --git a/OmnipodKit b/OmnipodKit index 3de1ac2f49..0c6d68b00d 160000 --- a/OmnipodKit +++ b/OmnipodKit @@ -1 +1 @@ -Subproject commit 3de1ac2f491c95c527f246d0335a3fd825deec8a +Subproject commit 0c6d68b00d45f4fecd9b0fc0477fc00e2d7e4c02 From f61cefbc5ac0f98d1767f603c4d74934154b0d19 Mon Sep 17 00:00:00 2001 From: dnzxy <48965855+dnzxy@users.noreply.github.com> Date: Fri, 23 Oct 2026 17:07:12 +0200 Subject: [PATCH 19/41] Bump LibreLoop to current upstream --- LibreLoop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibreLoop b/LibreLoop index 82c92f2cfb..a76748161d 160000 --- a/LibreLoop +++ b/LibreLoop @@ -1 +1 @@ -Subproject commit 82c92f2cfb265dd7147a2b36ee1796e30cb49ab9 +Subproject commit a76748161d31089ba102a05204afbaca448f5f09 From 3951550b8d7c1f6ac3cc194a1654e4698c434d5f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Oct 2026 15:43:18 +0000 Subject: [PATCH 20/41] CI: Bump APP_DEV_VERSION to 1.0.2.17 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index ffde9bf4b5..b52bac9215 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.16 +APP_DEV_VERSION = 1.0.2.17 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From 0a8c2587ec23e700a234c8cf5a3f09d08216c50a Mon Sep 17 00:00:00 2001 From: dnzxy <48965855+dnzxy@users.noreply.github.com> Date: Fri, 23 Oct 2026 17:45:37 +0200 Subject: [PATCH 21/41] Bump G7SensorKit for the SystemMemoryReset reconnect fix --- G7SensorKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/G7SensorKit b/G7SensorKit index e99d631ced..f455451853 160000 --- a/G7SensorKit +++ b/G7SensorKit @@ -1 +1 @@ -Subproject commit e99d631cedc0afe65ea030e72ff95b0b6cc32792 +Subproject commit f45545185370bc9ebc57d06e8eea5773b1ef868c From 9b593b2835333572b3da7d925f235e9d74bd125c Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:24:02 +0200 Subject: [PATCH 22/41] Show CGM sensor warnings whatever the sensor's age MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The status tag was gated behind the arc's 48h-to-expiry window, so a warning or critical highlight — sensor issue, signal loss, connection refused, sensor failed — could not reach the home screen until the last two days of a session. Until then the user saw a stale reading and a timestamp with no reason for either. --- .../Home/View/Header/CurrentGlucoseView.swift | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Trio/Sources/Modules/Home/View/Header/CurrentGlucoseView.swift b/Trio/Sources/Modules/Home/View/Header/CurrentGlucoseView.swift index 53f3c8696b..fc38064d97 100644 --- a/Trio/Sources/Modules/Home/View/Header/CurrentGlucoseView.swift +++ b/Trio/Sources/Modules/Home/View/Header/CurrentGlucoseView.swift @@ -299,6 +299,14 @@ struct CurrentGlucoseView: View { return (status.imageName, oneLine, color) } + /// A status the user has to act on — sensor issue, signal loss, failure. + /// Not gated by sensor age: it is the reason the readings stopped making + /// sense, whether the sensor is on day two or day ten. + private var statusDemandsAttention: Bool { + guard let status = cgmStatus else { return false } + return status.status != .normal + } + /// Arc shown for warmup, the last 48 h of a time-based sensor (incl. /// grace period), or any non-normal state from a battery-based manager. private var shouldShowArc: Bool { @@ -336,14 +344,17 @@ struct CurrentGlucoseView: View { if isStabilizing { return ("Stabilizing", .orange, "hourglass") } - guard shouldShowArc else { return nil } if let status = cgmStatus { + // Only the normal tier is gated to the arc's 48h window; a warning + // or critical status has to show whatever the sensor's age. + guard statusDemandsAttention || shouldShowArc else { return nil } // LibreLoop's cgmStatusHighlight uses "\n" to split two-line pill // labels ("Signal\nLoss", "Sensor\nWarmup"); we render in a // single-line tag, so collapse newlines to spaces here. let oneLine = status.localizedMessage.replacingOccurrences(of: "\n", with: " ") return (oneLine, theme(for: status.status), nil) } + guard shouldShowArc else { return nil } if let expiresAt = cgmSensorExpiresAt { let text = SensorRemainingTimeFormatter.format(until: expiresAt) let theme: SensorStatusTagTheme From 0c511a797b50243c63f5c13974a480d85690a76c Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:24:09 +0200 Subject: [PATCH 23/41] Catalog the G7 sensor lifecycle alerts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit G7 was the only CGM with no catalog entries, so its lifecycle alerts passed through with no sound, no tier config and no snooze mapping: a sensor-expired notification reached the user as a silent banner. Levels are identical to the LibreLoop set — every CGM lifecycle alert is Time-Sensitive. --- .../Alerts/AlertCatalogRegistry.swift | 85 ++++++++++++++++++- .../AlertCatalogRegistryEntriesTests.swift | 60 +++++++++++++ 2 files changed, 142 insertions(+), 3 deletions(-) diff --git a/Trio/Sources/Services/Alerts/AlertCatalogRegistry.swift b/Trio/Sources/Services/Alerts/AlertCatalogRegistry.swift index 3173b4c3c8..fb6fe5fa53 100644 --- a/Trio/Sources/Services/Alerts/AlertCatalogRegistry.swift +++ b/Trio/Sources/Services/Alerts/AlertCatalogRegistry.swift @@ -8,13 +8,14 @@ import LoopKit /// move out of here and into the plugin repo. /// /// Scope covers pump + CGM-issued alerts (LibreLoop sensor expiry / attention -/// / reconnect). G5/G6/One/G7/One+ don't go through `issueAlert` — their -/// status surfaces via `cgmStatusHighlight` instead. Trio-internal alerts +/// / reconnect, G7 sensor lifecycle). G5/G6/One don't go through `issueAlert` +/// — their status surfaces via `cgmStatusHighlight` only. Trio-internal alerts /// (glucose thresholds, algorithm error, not-looping) set their level at /// construction and don't need a catalog entry. enum AlertCatalogRegistry { static let entries: [Alert.CatalogEntry] = - omniEntries + minimedEntries + danaEntries + medtrumEntries + libreLoopEntries + trioAlgorithmEntries + omniEntries + minimedEntries + danaEntries + medtrumEntries + libreLoopEntries + g7Entries + + trioAlgorithmEntries static func lookup(_ identifier: Alert.Identifier) -> Alert.CatalogEntry? { if let exact = entries.first(where: { $0.identifier == identifier }) { @@ -246,6 +247,84 @@ private extension AlertCatalogRegistry { ] } +// MARK: - Dexcom G7 / ONE+ / Stelo + +private extension AlertCatalogRegistry { + /// The plugin issues these without a sound, so without an entry here they + /// reach the user as a silent banner with no tier config and no snooze + /// mapping. G7 was the one CGM with no entries at all. + /// + /// Levels are identical to the LibreLoop set — every CGM lifecycle alert + /// is `.timeSensitive`. Nothing is `.critical`, sensor failure included: a + /// dead sensor stops CGM, it doesn't dose, and once readings stop + /// `loop.notActive` escalates to Critical on its own. Nothing is `.active` + /// either, matching how the catalog escalates LibreLoop's 24h warning. + /// + /// Both plugins declare their own levels and the catalog overrides both + /// the same way (`G7LifecycleAlert.interruptionLevel`, + /// `LibreLoopExpiryAlerts`), so these rows are what the user actually gets. + static let g7Entries: [Alert.CatalogEntry] = [ + addEntry( + "G7CGMManager", + "sensorExpiringSoon", + .timeSensitive, + "Sensor Expires in 24 Hours", + "Sensor", + .cgmExpiringSoon + ), + addEntry( + "G7CGMManager", + "sensorExpiringImminently", + .timeSensitive, + "Sensor Expires in 2 Hours", + "Sensor", + .cgmExpiringSoon + ), + addEntry( + "G7CGMManager", + "sensorExpired", + .timeSensitive, + "Sensor Expired", + "Sensor", + .cgmExpired + ), + addEntry( + "G7CGMManager", + "sessionEnded", + .timeSensitive, + "Sensor Session Ended", + "Sensor", + .cgmExpired + ), + addEntry( + "G7CGMManager", + "sensorFailed", + .timeSensitive, + "Sensor Failed", + "Sensor", + .cgmReplacementNeeded + ), + addEntry( + "G7CGMManager", + "connectionRefused", + .timeSensitive, + "Sensor Connection Refused", + "Connectivity", + .cgmReconnectNeeded + ), + // The plugin no longer raises this one, only retracts it; the entry + // stays so a build that re-enables it is configured, not silent. + addEntry( + "G7CGMManager", + "signalLoss", + .timeSensitive, + "No Sensor Readings", + "Connectivity", + .cgmReconnectNeeded + ) + ] +} + // MARK: - Trio internal — Algorithm private extension AlertCatalogRegistry { diff --git a/TrioTests/AlertCatalogRegistryEntriesTests.swift b/TrioTests/AlertCatalogRegistryEntriesTests.swift index eddeba8b5b..b91d0a2095 100644 --- a/TrioTests/AlertCatalogRegistryEntriesTests.swift +++ b/TrioTests/AlertCatalogRegistryEntriesTests.swift @@ -58,6 +58,17 @@ import Testing ("LibreLoopCGMManager", "sensorExpiry.warning2h"), ("LibreLoopCGMManager", "sensorExpiry.sessionEnded"), ("LibreLoopCGMManager", "sensorAttention"), + // G7 matches LibreLoop row for row: every CGM lifecycle alert is + // .timeSensitive. Not .critical — once readings stop, + // loop.notActive escalates on its own; and not .active, the same + // escalation the catalog applies to LibreLoop's 24h warning. + ("G7CGMManager", "sensorExpiringSoon"), + ("G7CGMManager", "sensorExpiringImminently"), + ("G7CGMManager", "sensorFailed"), + ("G7CGMManager", "sensorExpired"), + ("G7CGMManager", "sessionEnded"), + ("G7CGMManager", "connectionRefused"), + ("G7CGMManager", "signalLoss"), ("trio.aps", "glucoseDataStale") ] ) func timeSensitiveEntries(manager: String, alertID: String) { @@ -164,6 +175,55 @@ import Testing #expect(AlertCatalogRegistry.lookup(id("LibreLoopCGMManager", "reconnectNeedsReScan"))?.category == "Connectivity") } + // MARK: - I2: Dexcom G7 lifecycle entries + + /// The plugin issues these without a sound, so a missing entry is what + /// turns a sensor alert into a silent banner. The catalog is the tier + /// source, so these levels — not the plugin's own — are what the user + /// gets, and they must stay equal to the LibreLoop rows above. + @Test( + "G7 lifecycle entries map to CGM-side concepts", + arguments: [ + ("sensorExpiringSoon", Alert.CatalogConcept.cgmExpiringSoon), + ("sensorExpiringImminently", Alert.CatalogConcept.cgmExpiringSoon), + ("sensorExpired", Alert.CatalogConcept.cgmExpired), + ("sessionEnded", Alert.CatalogConcept.cgmExpired), + ("sensorFailed", Alert.CatalogConcept.cgmReplacementNeeded), + ("connectionRefused", Alert.CatalogConcept.cgmReconnectNeeded), + ("signalLoss", Alert.CatalogConcept.cgmReconnectNeeded) + ] + ) func g7Concepts(alertID: String, expected: Alert.CatalogConcept) { + #expect(AlertCatalogRegistry.lookup(id("G7CGMManager", alertID))?.concept == expected) + } + + @Test( + "G7 lifecycle entries are categorized Sensor or Connectivity", + arguments: [ + ("sensorExpiringSoon", "Sensor"), + ("sensorExpiringImminently", "Sensor"), + ("sensorExpired", "Sensor"), + ("sessionEnded", "Sensor"), + ("sensorFailed", "Sensor"), + ("connectionRefused", "Connectivity"), + ("signalLoss", "Connectivity") + ] + ) func g7Categories(alertID: String, expected: String) { + #expect(AlertCatalogRegistry.lookup(id("G7CGMManager", alertID))?.category == expected) + } + + /// Every case of `G7LifecycleAlert` is catalogued. The raw values are + /// duplicated here because the enum is internal to the plugin; if one is + /// renamed upstream this fails rather than going quietly silent. + @Test("every G7 lifecycle alert has an entry") func g7EntriesAreComplete() { + let allCases = [ + "sensorExpiringSoon", "sensorExpiringImminently", "sensorExpired", + "sessionEnded", "sensorFailed", "signalLoss", "connectionRefused" + ] + for alertID in allCases { + #expect(AlertCatalogRegistry.lookup(id("G7CGMManager", alertID)) != nil) + } + } + // MARK: - J: Trio-internal Algorithm entries @Test( From 3a57aef800cd7956c910f3f31265f9e298098675 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Oct 2026 16:27:58 +0000 Subject: [PATCH 24/41] CI: Bump APP_DEV_VERSION to 1.0.2.18 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index b52bac9215..e2db565337 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.17 +APP_DEV_VERSION = 1.0.2.18 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From aec0e43dbad21db8073e0a72c4a3395a80df390a Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 23 Oct 2026 19:49:26 +0200 Subject: [PATCH 25/41] feat(alerts): add Syai entries to alert catalog --- .../Services/Alerts/AlertCatalogRegistry.swift | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Trio/Sources/Services/Alerts/AlertCatalogRegistry.swift b/Trio/Sources/Services/Alerts/AlertCatalogRegistry.swift index 3173b4c3c8..77af8cd327 100644 --- a/Trio/Sources/Services/Alerts/AlertCatalogRegistry.swift +++ b/Trio/Sources/Services/Alerts/AlertCatalogRegistry.swift @@ -14,7 +14,8 @@ import LoopKit /// construction and don't need a catalog entry. enum AlertCatalogRegistry { static let entries: [Alert.CatalogEntry] = - omniEntries + minimedEntries + danaEntries + medtrumEntries + libreLoopEntries + trioAlgorithmEntries + omniEntries + minimedEntries + danaEntries + medtrumEntries + libreLoopEntries + syaiEntries + + trioAlgorithmEntries static func lookup(_ identifier: Alert.Identifier) -> Alert.CatalogEntry? { if let exact = entries.first(where: { $0.identifier == identifier }) { @@ -246,6 +247,17 @@ private extension AlertCatalogRegistry { ] } +// MARK: - Syai (Ultra) + +private extension AlertCatalogRegistry { + static let syaiEntries: [Alert.CatalogEntry] = [ + addEntry("SyaiCGMManager", "syai.signalLost", .timeSensitive, "Signal Loss", "Connectivity", .cgmReconnectNeeded), + addEntry("SyaiCGMManager", "syai.expired", .timeSensitive, "Sensor Expired", "Sensor", .cgmExpired), + addEntry("SyaiCGMManager", "syai.failed", .timeSensitive, "Sensor Malfunction", "Sensor", .cgmReplacementNeeded), + addEntry("SyaiCGMManager", "syai.unactivated", .timeSensitive, "Sensor Not Activated", "Sensor", .cgmReplacementNeeded) + ] +} + // MARK: - Trio internal — Algorithm private extension AlertCatalogRegistry { From 457fe4890e769844a3b08d2b0619d113aa4cdc22 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 23 Oct 2026 20:39:36 +0200 Subject: [PATCH 26/41] chore: update syaikit submodule --- SyaiKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SyaiKit b/SyaiKit index 042924be26..67dad3d6ae 160000 --- a/SyaiKit +++ b/SyaiKit @@ -1 +1 @@ -Subproject commit 042924be26da3403cb8dc4a84de9c6dd4b9e2ebb +Subproject commit 67dad3d6ae03176283b9456a89eb7683308ab4b2 From 0df3c74d94af24b9b9f7f5c09afff40dc38cc743 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 23 Oct 2026 21:28:17 +0200 Subject: [PATCH 27/41] chore: update syaikit submodule --- SyaiKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SyaiKit b/SyaiKit index 67dad3d6ae..14236d5d72 160000 --- a/SyaiKit +++ b/SyaiKit @@ -1 +1 @@ -Subproject commit 67dad3d6ae03176283b9456a89eb7683308ab4b2 +Subproject commit 14236d5d725920368f9cfc8610c6c640c36d3db9 From f3818647335c52f75a0712fc5dc4c53ff43121f6 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 23 Oct 2026 21:34:19 +0200 Subject: [PATCH 28/41] chore: update syaikit submodule --- SyaiKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SyaiKit b/SyaiKit index 14236d5d72..c4b553c5cd 160000 --- a/SyaiKit +++ b/SyaiKit @@ -1 +1 @@ -Subproject commit 14236d5d725920368f9cfc8610c6c640c36d3db9 +Subproject commit c4b553c5cd9e219bd041586ff49d48c7d2b8efae From b661083972e9eb0507d548d5d5f38cabde1334db Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 23 Oct 2026 21:41:42 +0200 Subject: [PATCH 29/41] chore: update syaikit submodule --- SyaiKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SyaiKit b/SyaiKit index c4b553c5cd..8161089806 160000 --- a/SyaiKit +++ b/SyaiKit @@ -1 +1 @@ -Subproject commit c4b553c5cd9e219bd041586ff49d48c7d2b8efae +Subproject commit 816108980650863b637934367dc5e35212001956 From d166b09a1e6a6963c41e38e7f06dcc3402fa6d4d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Oct 2026 21:34:18 +0000 Subject: [PATCH 30/41] CI: Bump APP_DEV_VERSION to 1.0.2.19 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index e2db565337..af0b0e0215 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.18 +APP_DEV_VERSION = 1.0.2.19 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From db974e1fc5bd25e57e833d23067d2b2139fac432 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Oct 2026 13:32:11 +0000 Subject: [PATCH 31/41] CI: Bump APP_DEV_VERSION to 1.0.2.20 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index af0b0e0215..5ff2494e6a 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.19 +APP_DEV_VERSION = 1.0.2.20 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From 02fa0cfb665c19c12bc104f625205ac5f72b94f0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Oct 2026 13:36:08 +0000 Subject: [PATCH 32/41] CI: Bump APP_DEV_VERSION to 1.0.2.21 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 5ff2494e6a..37788cbdb3 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.20 +APP_DEV_VERSION = 1.0.2.21 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From 979419f0bc717ea9f32b59af2c03e719d52cfba5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Oct 2026 13:41:25 +0000 Subject: [PATCH 33/41] CI: Bump APP_DEV_VERSION to 1.0.2.22 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 37788cbdb3..ef81c2b2a1 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.21 +APP_DEV_VERSION = 1.0.2.22 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From 3c8cf877e3dcb19dc9e8762462759b03d7c45088 Mon Sep 17 00:00:00 2001 From: dnzxy <48965855+dnzxy@users.noreply.github.com> Date: Sat, 24 Oct 2026 17:34:02 +0200 Subject: [PATCH 34/41] Bump RoundWhiteDiscKit for the SwiftFormat parse fix Unblocks local builds: the format phase aborted on this package and then reformatted excluded submodule sources. --- RoundWhiteDiscKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RoundWhiteDiscKit b/RoundWhiteDiscKit index e66da6cc34..7dd6396f04 160000 --- a/RoundWhiteDiscKit +++ b/RoundWhiteDiscKit @@ -1 +1 @@ -Subproject commit e66da6cc34680fecbbb87812279163dcc1a842b4 +Subproject commit 7dd6396f04371330d35799c88b9cba105a200180 From 4b425101228e15aa2b7ed83f3870338a4395bf13 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Oct 2026 15:34:14 +0000 Subject: [PATCH 35/41] CI: Bump APP_DEV_VERSION to 1.0.2.23 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index ef81c2b2a1..882e0adbba 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.22 +APP_DEV_VERSION = 1.0.2.23 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From 2b8d4aee9cfcac1079c2ecdeff809bf5933afa68 Mon Sep 17 00:00:00 2001 From: Lamercho <33007090+Lamercho@users.noreply.github.com> Date: Sat, 24 Oct 2026 20:26:20 +0300 Subject: [PATCH 36/41] Rebuild glucose target profiles when the chart window passes their end --- .../Home/HomeStateModel+Setup/StartEndMarkerSetup.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Trio/Sources/Modules/Home/HomeStateModel+Setup/StartEndMarkerSetup.swift b/Trio/Sources/Modules/Home/HomeStateModel+Setup/StartEndMarkerSetup.swift index cdc8417f42..a70ce97fc2 100644 --- a/Trio/Sources/Modules/Home/HomeStateModel+Setup/StartEndMarkerSetup.swift +++ b/Trio/Sources/Modules/Home/HomeStateModel+Setup/StartEndMarkerSetup.swift @@ -20,5 +20,14 @@ extension Home.StateModel { endMarker = forecastDisplayType == .lines ? threeHourSinceNow : dynamicFutureDateForCone <= threeHourSinceNow ? dynamicFutureDateForCone.addingTimeInterval(TimeInterval(minutes: 30)) : threeHourSinceNow + + // Target profiles are built at setup and end at a midnight; + // rebuild them when the chart window moves past the last one + // cf. https://github.com/nightscout/Trio/issues/1581 + if let lastEnd = targetProfiles.last?.endTime, + lastEnd < endMarker.timeIntervalSinceReferenceDate + { + targetProfiles = processFetchedTargets(bgTargets, startMarker: startMarker) + } } } From 25936ebc8e7beb26ab0d67fe7615427c1d9bbb5c Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 24 Oct 2026 18:51:13 +0000 Subject: [PATCH 37/41] Upload pump-programmed bolus flag to Nightscout Boluses programmed on the pump itself are stored as BolusStored.isProgrammedByPumpUI but were not included in the Nightscout treatment payload. Send it as isProgrammedByPumpUI on bolus treatments (omitted when false), re-upload an uploaded row when the flag changes on finalization, and include it in the upload-stamp check. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012tnAW2LeHupxFWSc9HjqUg --- .../APS/Storage/PumpHistoryStorage.swift | 9 ++- Trio/Sources/Models/NightscoutTreatment.swift | 2 + .../Nightscout/NightscoutManager.swift | 1 + .../PumpEventFinalizationTests.swift | 67 ++++++++++++++++++- 4 files changed, 75 insertions(+), 4 deletions(-) diff --git a/Trio/Sources/APS/Storage/PumpHistoryStorage.swift b/Trio/Sources/APS/Storage/PumpHistoryStorage.swift index cacb57ba97..bf759f4fd7 100644 --- a/Trio/Sources/APS/Storage/PumpHistoryStorage.swift +++ b/Trio/Sources/APS/Storage/PumpHistoryStorage.swift @@ -250,6 +250,7 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable { case PumpEventStored.EventType.bolus.rawValue: guard let bolus = event.bolus else { return } let previousAmount = bolus.amount + let previousProgrammedByPumpUI = bolus.isProgrammedByPumpUI let finalAmount = dose.deliveredUnits.map { self.roundDose($0, toIncrement: Double(settings.preferences.bolusIncrement)) } @@ -259,7 +260,9 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable { bolus.isSMB = dose.automatic ?? true bolus.isProgrammedByPumpUI = dose.wasProgrammedByPumpUI event.isMutable = dose.isMutable - if event.isUploadedToNS, bolus.amount != previousAmount { + if event.isUploadedToNS, + bolus.amount != previousAmount || bolus.isProgrammedByPumpUI != previousProgrammedByPumpUI + { event.isUploadedToNS = false } if !dose.isMutable { @@ -442,7 +445,9 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable { protein: nil, targetTop: nil, targetBottom: nil, - id: event.id + id: event.id, + // omitted unless set, like LoopKit's DoseEntry encoding + isProgrammedByPumpUI: event.bolus?.isProgrammedByPumpUI == true ? true : nil ) case PumpEvent.tempBasal.rawValue: return NightscoutTreatment( diff --git a/Trio/Sources/Models/NightscoutTreatment.swift b/Trio/Sources/Models/NightscoutTreatment.swift index cbd76d3fbc..81dd6e0040 100644 --- a/Trio/Sources/Models/NightscoutTreatment.swift +++ b/Trio/Sources/Models/NightscoutTreatment.swift @@ -23,6 +23,7 @@ struct NightscoutTreatment: JSON, Hashable, Equatable { var units: String? var id: String? var fpuID: String? + var isProgrammedByPumpUI: Bool? static let local = "Trio" @@ -61,5 +62,6 @@ extension NightscoutTreatment { case units case id case fpuID + case isProgrammedByPumpUI } } diff --git a/Trio/Sources/Services/Network/Nightscout/NightscoutManager.swift b/Trio/Sources/Services/Network/Nightscout/NightscoutManager.swift index d9a9589358..5faff760da 100644 --- a/Trio/Sources/Services/Network/Nightscout/NightscoutManager.swift +++ b/Trio/Sources/Services/Network/Nightscout/NightscoutManager.swift @@ -1091,6 +1091,7 @@ final class BaseNightscoutManager: NightscoutManager, Injectable { switch event.type { case PumpEventStored.EventType.bolus.rawValue: return treatment.insulin == event.bolus?.amount as Decimal? + && (treatment.isProgrammedByPumpUI ?? false) == (event.bolus?.isProgrammedByPumpUI ?? false) case PumpEventStored.EventType.tempBasal.rawValue: return treatment.rate == event.tempBasal?.rate as Decimal? && treatment.duration == Int(event.tempBasal?.duration ?? 0) diff --git a/TrioTests/CoreDataTests/PumpEventFinalizationTests.swift b/TrioTests/CoreDataTests/PumpEventFinalizationTests.swift index 9481b927c0..bd2d4e4c94 100644 --- a/TrioTests/CoreDataTests/PumpEventFinalizationTests.swift +++ b/TrioTests/CoreDataTests/PumpEventFinalizationTests.swift @@ -47,7 +47,8 @@ import Testing deliveredUnits: Double? = nil, syncIdentifier: String?, isMutable: Bool, - automatic: Bool = true + automatic: Bool = true, + wasProgrammedByPumpUI: Bool = false ) -> LoopKit.NewPumpEvent { LoopKit.NewPumpEvent( date: date, @@ -63,7 +64,8 @@ import Testing insulinType: .lyumjev, automatic: automatic, manuallyEntered: false, - isMutable: isMutable + isMutable: isMutable, + wasProgrammedByPumpUI: wasProgrammedByPumpUI ), raw: Data((syncIdentifier ?? UUID().uuidString).utf8), title: "Test Bolus", @@ -276,6 +278,67 @@ import Testing #expect(abs((tidepoolBolus?.programmedAmount ?? 0) - 5.0) < 0.0001, "Programmed units") } + @Test("Nightscout payload marks boluses programmed on the pump") func testNightscoutPayloadCarriesPumpUIFlag() async throws { + let date = Date().addingTimeInterval(-30.minutes.timeInterval) + try await storage.storePumpEvents( + [ + bolusEvent( + date: date, + units: 1.0, + syncIdentifier: "bolus-pump-ui", + isMutable: false, + automatic: false, + wasProgrammedByPumpUI: true + ), + bolusEvent( + date: date.addingTimeInterval(5.minutes.timeInterval), + units: 2.0, + syncIdentifier: "bolus-app", + isMutable: false, + automatic: false + ) + ], + replacePendingEvents: false + ) + + let treatments = try await storage.getPumpHistoryNotYetUploadedToNightscout() + // event ids are UUIDs; tell the rows apart by amount, away from rounding noise + let pumpUI = treatments.first { ($0.insulin ?? 0) < 1.5 } + let app = treatments.first { ($0.insulin ?? 0) > 1.5 } + #expect(pumpUI?.isProgrammedByPumpUI == true, "Pump-programmed bolus must say so in NS") + #expect(app?.isProgrammedByPumpUI == nil, "Unset flag is omitted from the NS document") + } + + @Test("Finalizing an uploaded bolus as pump-programmed resets the NS upload flag") func testPumpUIFinalizationResetsNSFlag( + ) async throws { + let date = Date().addingTimeInterval(-5.minutes.timeInterval) + + try await storage.storePumpEvents( + [bolusEvent(date: date, units: 1.5, syncIdentifier: "bolus-ns3", isMutable: true)], + replacePendingEvents: false + ) + try await testContext.perform { + let rows = try testContext.fetch(PumpEventStored.fetchRequest()) + rows.forEach { $0.isUploadedToNS = true } + try testContext.save() + } + // same delivery, but the final report attributes it to the pump UI + try await storage.storePumpEvents( + [bolusEvent( + date: date, + units: 1.5, + deliveredUnits: 1.5, + syncIdentifier: "bolus-ns3", + isMutable: false, + wasProgrammedByPumpUI: true + )], + replacePendingEvents: false + ) + + let events = try await fetchAllEvents() + #expect(events.first?.isUploadedToNS == false, "A changed NS-visible flag must re-upload") + } + @Test("External doses expose no insulin type to uploaders") func testExternalDoseHasNoInsulinType() async throws { await storage.storeExternalInsulinEvent(amount: 2.0, timestamp: Date().addingTimeInterval(-10.minutes.timeInterval)) From 938e5880e36a1fad3657cac24fc07153a8c8b66c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Oct 2026 23:11:11 +0000 Subject: [PATCH 38/41] CI: Bump APP_DEV_VERSION to 1.0.2.24 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 882e0adbba..608473044b 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.23 +APP_DEV_VERSION = 1.0.2.24 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From aff37ac933d9e92a2eaf6d046f4706c0e03fb6de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Oct 2026 23:11:32 +0000 Subject: [PATCH 39/41] CI: Bump APP_DEV_VERSION to 1.0.2.25 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 608473044b..10de874812 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.24 +APP_DEV_VERSION = 1.0.2.25 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From 4cc5e7b0ecfa09766f90bf93f898828eacb29b51 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Oct 2026 23:36:48 +0000 Subject: [PATCH 40/41] CI: Bump APP_DEV_VERSION to 1.0.2.26 [skip ci] --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 10de874812..8f64b33edb 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group // The developers set the version numbers, please leave them alone APP_VERSION = 1.0.2 -APP_DEV_VERSION = 1.0.2.25 +APP_DEV_VERSION = 1.0.2.26 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = From b5e9d2f2ca56d045079f216b0712850599ca813e Mon Sep 17 00:00:00 2001 From: Robert Date: Sun, 25 Oct 2026 07:03:59 +0100 Subject: [PATCH 41/41] parity: Re-record determination goldens after SMB low temp fix Upstream 75e44e2ef corrected the inverted SMB low temp rate for sub-30m zero temps (basal * (30 - d) / 30). Four autoISF-off scenarios recorded under the old formula now differ in rate/duration/reason only; the "no temp required" branch flips accordingly. No algorithm source changes. --- .../autosens-resistance+autoisf-off/determination.json | 4 +--- .../dynamic-isf-sigmoid+autoisf-off/determination.json | 4 +++- .../goldens/override-active+autoisf-off/determination.json | 4 +--- .../post-meal-cob-active+autoisf-off/determination.json | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/TrioTests/OpenAPSSwiftTests/Parity/goldens/autosens-resistance+autoisf-off/determination.json b/TrioTests/OpenAPSSwiftTests/Parity/goldens/autosens-resistance+autoisf-off/determination.json index 965eee0980..e185d25a41 100644 --- a/TrioTests/OpenAPSSwiftTests/Parity/goldens/autosens-resistance+autoisf-off/determination.json +++ b/TrioTests/OpenAPSSwiftTests/Parity/goldens/autosens-resistance+autoisf-off/determination.json @@ -16,7 +16,6 @@ "dura_ISFratio" : 1, "dura_avg" : 1, "dura_min" : 1, - "duration" : 30, "eventualBG" : 135, "expectedDelta" : -4.6, "id" : "00000000-0000-0000-0000-000000000000", @@ -165,8 +164,7 @@ 126 ] }, - "rate" : 0.275, - "reason" : "Ins.Req:, 0.55, SMB Del.Ratio:, 0.5, autosens:, 1, autoISF disabled, Standard, COB: 0, Dev: 37, BGI: -4, CR: 12, Target: 95, minPredBG 125, minGuardBG 134, IOBpredBG 108, UAMpredBG 135; Eventual BG 135 >= 95, insulinReq 0.55; setting 30m low temp of 0.27U/h. Microbolusing 0.25U. ", + "reason" : "Ins.Req:, 0.55, SMB Del.Ratio:, 0.5, autosens:, 1, autoISF disabled, Standard, COB: 0, Dev: 37, BGI: -4, CR: 12, Target: 95, minPredBG 125, minGuardBG 134, IOBpredBG 108, UAMpredBG 135; Eventual BG 135 >= 95, insulinReq 0.55; setting 30m low temp of 0.63U/h. Microbolusing 0.25U. 30m left and 0.75 ~ req 0.625U/hr: no temp required", "received" : false, "sensitivityRatio" : 1, "temp" : "absolute", diff --git a/TrioTests/OpenAPSSwiftTests/Parity/goldens/dynamic-isf-sigmoid+autoisf-off/determination.json b/TrioTests/OpenAPSSwiftTests/Parity/goldens/dynamic-isf-sigmoid+autoisf-off/determination.json index 091cbae080..740b1a8247 100644 --- a/TrioTests/OpenAPSSwiftTests/Parity/goldens/dynamic-isf-sigmoid+autoisf-off/determination.json +++ b/TrioTests/OpenAPSSwiftTests/Parity/goldens/dynamic-isf-sigmoid+autoisf-off/determination.json @@ -16,6 +16,7 @@ "dura_ISFratio" : 1, "dura_avg" : 1, "dura_min" : 1, + "duration" : 30, "eventualBG" : 125, "expectedDelta" : -3.9, "id" : "00000000-0000-0000-0000-000000000000", @@ -166,7 +167,8 @@ 98 ] }, - "reason" : "Ins.Req:, 0.4, SMB Del.Ratio:, 0.5, autosens:, 1.15, autoISF disabled, Standard, COB: 0, Dev: 56, BGI: -4, CR: 12, Target: 95, minPredBG 114, minGuardBG 125, IOBpredBG 104, UAMpredBG 125, Dynamic ISF: On, Sigmoid function, AF: 0.6, Basal ratio: 1.01; Eventual BG 125 >= 95, insulinReq 0.4; setting 30m low temp of 0.87U/h. Microbolusing 0.2U. 30m left and 0.75 ~ req 0.875U/hr: no temp required", + "rate" : 0.025, + "reason" : "Ins.Req:, 0.4, SMB Del.Ratio:, 0.5, autosens:, 1.15, autoISF disabled, Standard, COB: 0, Dev: 56, BGI: -4, CR: 12, Target: 95, minPredBG 114, minGuardBG 125, IOBpredBG 104, UAMpredBG 125, Dynamic ISF: On, Sigmoid function, AF: 0.6, Basal ratio: 1.01; Eventual BG 125 >= 95, insulinReq 0.4; setting 30m low temp of 0.03U/h. Microbolusing 0.2U. ", "received" : false, "sensitivityRatio" : 1.152552507138643740284, "temp" : "absolute", diff --git a/TrioTests/OpenAPSSwiftTests/Parity/goldens/override-active+autoisf-off/determination.json b/TrioTests/OpenAPSSwiftTests/Parity/goldens/override-active+autoisf-off/determination.json index c17e47b591..5daa65394e 100644 --- a/TrioTests/OpenAPSSwiftTests/Parity/goldens/override-active+autoisf-off/determination.json +++ b/TrioTests/OpenAPSSwiftTests/Parity/goldens/override-active+autoisf-off/determination.json @@ -16,7 +16,6 @@ "dura_ISFratio" : 1, "dura_avg" : 1, "dura_min" : 1, - "duration" : 30, "eventualBG" : 128, "expectedDelta" : -4.1, "id" : "00000000-0000-0000-0000-000000000000", @@ -168,8 +167,7 @@ 104 ] }, - "rate" : 0.375, - "reason" : "Ins.Req:, 0.7, SMB Del.Ratio:, 0.5, autosens:, 1, autoISF disabled, Standard, COB: 0, Dev: 54, BGI: -3, CR: 12→9.2, Target: 90, minPredBG 120, minGuardBG 128, IOBpredBG 112, UAMpredBG 128; Eventual BG 128 >= 90, insulinReq 0.7; setting 30m low temp of 0.38U/h. Microbolusing 0.35U. ", + "reason" : "Ins.Req:, 0.7, SMB Del.Ratio:, 0.5, autosens:, 1, autoISF disabled, Standard, COB: 0, Dev: 54, BGI: -3, CR: 12→9.2, Target: 90, minPredBG 120, minGuardBG 128, IOBpredBG 112, UAMpredBG 128; Eventual BG 128 >= 90, insulinReq 0.7; setting 30m low temp of 0.77U/h. Microbolusing 0.35U. 30m left and 0.75 ~ req 0.775U/hr: no temp required", "received" : false, "sensitivityRatio" : 1, "temp" : "absolute", diff --git a/TrioTests/OpenAPSSwiftTests/Parity/goldens/post-meal-cob-active+autoisf-off/determination.json b/TrioTests/OpenAPSSwiftTests/Parity/goldens/post-meal-cob-active+autoisf-off/determination.json index 42e6596e2a..9fbf021591 100644 --- a/TrioTests/OpenAPSSwiftTests/Parity/goldens/post-meal-cob-active+autoisf-off/determination.json +++ b/TrioTests/OpenAPSSwiftTests/Parity/goldens/post-meal-cob-active+autoisf-off/determination.json @@ -216,8 +216,8 @@ 104 ] }, - "rate" : 0.575, - "reason" : "Ins.Req:, 0.825, SMB Del.Ratio:, 0.5, autosens:, 1, autoISF disabled, Standard, COB: 26, Dev: 67, BGI: -4, CR: 12, Target: 95, minPredBG 141, minGuardBG 141, IOBpredBG 114, COBpredBG 168, UAMpredBG 105; Eventual BG 168 >= 95, insulinReq 0.825; setting 30m low temp of 0.57U/h. Microbolusing 0.4U. ", + "rate" : 0.325, + "reason" : "Ins.Req:, 0.825, SMB Del.Ratio:, 0.5, autosens:, 1, autoISF disabled, Standard, COB: 26, Dev: 67, BGI: -4, CR: 12, Target: 95, minPredBG 141, minGuardBG 141, IOBpredBG 114, COBpredBG 168, UAMpredBG 105; Eventual BG 168 >= 95, insulinReq 0.825; setting 30m low temp of 0.33U/h. Microbolusing 0.4U. ", "received" : false, "sensitivityRatio" : 1, "temp" : "absolute",