diff --git a/LoopFollow/Storage/Storage.swift b/LoopFollow/Storage/Storage.swift index 5dea5ebb1..0e32a48f0 100644 --- a/LoopFollow/Storage/Storage.swift +++ b/LoopFollow/Storage/Storage.swift @@ -33,7 +33,7 @@ class Storage { 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 hasSeenFatProteinOrderChange = StorageValue(key: "hasSeenFatProteinOrderChange", defaultValue: true) var backgroundRefreshType = StorageValue(key: "backgroundRefreshType", defaultValue: .silentTune) @@ -194,7 +194,10 @@ class Storage { var nsWriteAuth = StorageValue(key: "nsWriteAuth", defaultValue: false) var nsAdminAuth = StorageValue(key: "nsAdminAuth", defaultValue: false) - var migrationStep = StorageValue(key: "migrationStep", defaultValue: 0) + // When adding a new migration step in `runMigrationsIfNeeded()`, bump this default + // to the new latest step number so fresh installs skip all migrations. Other defaults + // in this file must reflect the post-migration final state for a fresh install. + var migrationStep = StorageValue(key: "migrationStep", defaultValue: 7) var persistentNotification = StorageValue(key: "persistentNotification", defaultValue: false) var persistentNotificationLastBGTime = StorageValue(key: "persistentNotificationLastBGTime", defaultValue: .distantPast) @@ -206,9 +209,9 @@ class Storage { // Tab positions - which position each item is in (positions 1-4 are customizable, 5 is always Menu) var homePosition = StorageValue(key: "homePosition", defaultValue: .position1) var alarmsPosition = StorageValue(key: "alarmsPosition", defaultValue: .position2) - var snoozerPosition = StorageValue(key: "snoozerPosition", defaultValue: .menu) - var nightscoutPosition = StorageValue(key: "nightscoutPosition", defaultValue: .position3) - var remotePosition = StorageValue(key: "remotePosition", defaultValue: .position4) + var snoozerPosition = StorageValue(key: "snoozerPosition", defaultValue: .position3) + var nightscoutPosition = StorageValue(key: "nightscoutPosition", defaultValue: .position4) + var remotePosition = StorageValue(key: "remotePosition", defaultValue: .menu) var statisticsPosition = StorageValue(key: "statisticsPosition", defaultValue: .menu) var treatmentsPosition = StorageValue(key: "treatmentsPosition", defaultValue: .menu) @@ -233,8 +236,8 @@ class Storage { /// launch, where Storage was initialized while UserDefaults was encrypted and all values were /// cached as their defaults. /// - /// `migrationStep` is intentionally excluded: viewDidLoad writes it to 6 during the BFU - /// launch; if we reloaded it and the flush had somehow not landed yet, migrations would re-run. + /// `migrationStep` is intentionally excluded: viewDidLoad writes it to the latest step during + /// the BFU launch; if we reloaded it and the flush had somehow not landed yet, migrations would re-run. /// /// SecureStorageValue properties (maxBolus, maxCarbs, maxProtein, maxFat, bolusIncrement) are /// not covered here — SecureStorageValue does not implement reload() and Keychain has the same diff --git a/LoopFollow/ViewControllers/MainViewController.swift b/LoopFollow/ViewControllers/MainViewController.swift index ddfb2f3f0..3f37f3d66 100644 --- a/LoopFollow/ViewControllers/MainViewController.swift +++ b/LoopFollow/ViewControllers/MainViewController.swift @@ -1015,6 +1015,12 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele // Capture before migrations run: true for existing users, false for fresh installs. let isExistingUser = Storage.shared.migrationStep.exists + // When adding a new migration step below: + // 1. Bump the `migrationStep` defaultValue in Storage.swift to the new latest step + // number so fresh installs skip every migration. + // 2. Update any other StorageValue defaults in Storage.swift that this new step + // mutates, so a fresh install ends up in the same state as a migrated user. + // Step 1: Released in v3.0.0 (2025-07-07). Can be removed after 2026-07-07. if Storage.shared.migrationStep.value < 1 { Storage.shared.migrateStep1()