diff --git a/LoopFollow/Remote/Settings/RemoteSettingsView.swift b/LoopFollow/Remote/Settings/RemoteSettingsView.swift index 1c1066197..3df7acf2d 100644 --- a/LoopFollow/Remote/Settings/RemoteSettingsView.swift +++ b/LoopFollow/Remote/Settings/RemoteSettingsView.swift @@ -450,10 +450,10 @@ struct RemoteSettingsView: View { if device.value == "Trio" { HStack { - Text("Max Protein") + Text("Max Fat") Spacer() TextFieldWithToolBar( - quantity: $viewModel.maxProtein, + quantity: $viewModel.maxFat, maxLength: 4, unit: HKUnit.gram(), allowDecimalSeparator: true, @@ -469,10 +469,10 @@ struct RemoteSettingsView: View { } HStack { - Text("Max Fat") + Text("Max Protein") Spacer() TextFieldWithToolBar( - quantity: $viewModel.maxFat, + quantity: $viewModel.maxProtein, maxLength: 4, unit: HKUnit.gram(), allowDecimalSeparator: true, diff --git a/LoopFollow/Remote/TRC/MealView.swift b/LoopFollow/Remote/TRC/MealView.swift index 4c5e27df6..55dd704e6 100644 --- a/LoopFollow/Remote/TRC/MealView.swift +++ b/LoopFollow/Remote/TRC/MealView.swift @@ -33,6 +33,7 @@ struct MealView: View { @State private var statusMessage: String? = nil @State private var selectedTime: Date? = nil @State private var isScheduling: Bool = false + @State private var showFatProteinOrderBanner = false enum AlertType { case confirmMeal @@ -46,6 +47,24 @@ struct MealView: View { VStack { Form { Section(header: Text("Meal Data")) { + // TODO: This banner can be deleted in March 2027. Check the commit for other places to cleanup. + if showFatProteinOrderBanner { + HStack { + Image(systemName: "arrow.left.arrow.right") + Text("The order of Fat and Protein inputs has changed.").font(.callout) + Spacer() + Button { + Storage.shared.hasSeenFatProteinOrderChange.value = true + withAnimation { showFatProteinOrderBanner = false } + } label: { + Image(systemName: "xmark.circle.fill") + } + .buttonStyle(.plain) + } + .listRowBackground(Color.orange.opacity(0.75)) + .transition(.opacity) + } + HKQuantityInputView( label: "Carbs", quantity: $carbs, @@ -61,26 +80,26 @@ struct MealView: View { if mealWithFatProtein.value { HKQuantityInputView( - label: "Protein", - quantity: $protein, + label: "Fat", + quantity: $fat, unit: .gram(), maxLength: 4, minValue: HKQuantity(unit: .gram(), doubleValue: 0), - maxValue: maxProtein.value, - isFocused: $proteinFieldIsFocused, + maxValue: maxFat.value, + isFocused: $fatFieldIsFocused, onValidationError: { message in handleValidationError(message) } ) HKQuantityInputView( - label: "Fat", - quantity: $fat, + label: "Protein", + quantity: $protein, unit: .gram(), maxLength: 4, minValue: HKQuantity(unit: .gram(), doubleValue: 0), - maxValue: maxFat.value, - isFocused: $fatFieldIsFocused, + maxValue: maxProtein.value, + isFocused: $proteinFieldIsFocused, onValidationError: { message in handleValidationError(message) } @@ -153,6 +172,10 @@ struct MealView: View { .onAppear { selectedTime = nil isScheduling = false + + if !Storage.shared.hasSeenFatProteinOrderChange.value && Storage.shared.mealWithFatProtein.value { + showFatProteinOrderBanner = true + } } .alert(isPresented: $showAlert) { switch alertType { diff --git a/LoopFollow/Storage/Storage.swift b/LoopFollow/Storage/Storage.swift index 06bec90fb..8a90727a6 100644 --- a/LoopFollow/Storage/Storage.swift +++ b/LoopFollow/Storage/Storage.swift @@ -29,6 +29,9 @@ class Storage { var mealWithBolus = StorageValue(key: "mealWithBolus", defaultValue: false) var mealWithFatProtein = StorageValue(key: "mealWithFatProtein", defaultValue: false) + // TODO: This flag can be deleted in March 2027. Check the commit for other places to cleanup. + var hasSeenFatProteinOrderChange = StorageValue(key: "hasSeenFatProteinOrderChange", defaultValue: false) + var cachedJWT = StorageValue(key: "cachedJWT", defaultValue: nil) var jwtExpirationDate = StorageValue(key: "jwtExpirationDate", defaultValue: nil) diff --git a/LoopFollow/ViewControllers/MainViewController.swift b/LoopFollow/ViewControllers/MainViewController.swift index ab1df5766..1077ae62c 100644 --- a/LoopFollow/ViewControllers/MainViewController.swift +++ b/LoopFollow/ViewControllers/MainViewController.swift @@ -137,6 +137,9 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele loadDebugData() + // Capture before migrations run: true for existing users, false for fresh installs. + let isExistingUser = Storage.shared.migrationStep.exists + if Storage.shared.migrationStep.value < 1 { Storage.shared.migrateStep1() Storage.shared.migrationStep.value = 1 @@ -152,6 +155,14 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele Storage.shared.migrationStep.value = 3 } + // TODO: This migration step can be deleted in March 2027. Check the commit for other places to cleanup. + if Storage.shared.migrationStep.value < 4 { + // Existing users need to see the fat/protein order change banner. + // New users never saw the old order, so mark it as already seen. + Storage.shared.hasSeenFatProteinOrderChange.value = !isExistingUser + Storage.shared.migrationStep.value = 4 + } + // Synchronize info types to ensure arrays are the correct size synchronizeInfoTypes()