@@ -5,17 +5,31 @@ import Foundation
55
66extension Storage {
77 func migrateStep5( ) {
8- let isLegacyDefaultTabBarOrder = homePosition. value. normalized == . position1
9- && alarmsPosition. value. normalized == . position2
10- && remotePosition. value. normalized == . position3
11- && nightscoutPosition. value. normalized == . position4
12- && snoozerPosition. value. normalized == . menu
13-
14- guard isLegacyDefaultTabBarOrder else { return }
8+ // Users upgrading from main had snoozer hardcoded at position 3, but that
9+ // key never existed in UserDefaults. On dev the default for snoozerPosition
10+ // is .menu, so an unstored value silently becomes .menu and snoozer
11+ // disappears from the tab bar.
12+ //
13+ // Detect this by checking .exists: if snoozerPosition was never stored,
14+ // the user expects snoozer at position 3 (where it always was on main).
15+ guard !snoozerPosition. exists else { return }
16+
17+ LogManager . shared. log ( category: . general, message: " migrateStep5: snoozerPosition not stored, restoring snoozer to position 3 " )
18+
19+ // If position 3 is occupied by another item whose position also wasn't
20+ // stored (e.g. nightscout landing there from a changed default), move
21+ // that item out first.
22+ for item in TabItem . allCases where item != . snoozer {
23+ if position ( for: item) . normalized == . position3,
24+ !migratePositionExists( for: item)
25+ {
26+ setPosition ( . menu, for: item)
27+ }
28+ }
1529
16- LogManager . shared . log ( category : . general , message : " migrateStep5: Reordering default tabs to Home, Alarms, Nightscout, Remote " )
17- nightscoutPosition . value = . position3
18- remotePosition . value = . position4
30+ if tabItem ( at : . position3 ) == nil {
31+ snoozerPosition . value = . position3
32+ }
1933 }
2034
2135 func migrateStep3( ) {
@@ -32,7 +46,19 @@ extension Storage {
3246 }
3347
3448 if !TabPosition. customizablePositions. contains ( snoozerPosition. value. normalized) {
35- snoozerPosition. value = . position3
49+ // Move any unstored occupant at position 3 to menu before placing snoozer,
50+ // to avoid a collision when dev defaults differ from main.
51+ for item in TabItem . allCases where item != . snoozer {
52+ if position ( for: item) . normalized == . position3,
53+ !migratePositionExists( for: item)
54+ {
55+ setPosition ( . menu, for: item)
56+ }
57+ }
58+
59+ if tabItem ( at: . position3) == nil {
60+ snoozerPosition. value = . position3
61+ }
3662 }
3763
3864 if alarmsPosition. value == . more {
@@ -1719,4 +1745,20 @@ extension Storage {
17191745
17201746 Storage . shared. alarms. value. append ( alarm)
17211747 }
1748+
1749+ // MARK: - Migration helpers (can be removed when step 5 is removed)
1750+
1751+ /// Check whether a tab item's position was explicitly stored in UserDefaults
1752+ /// (as opposed to using the StorageValue default).
1753+ private func migratePositionExists( for item: TabItem ) -> Bool {
1754+ switch item {
1755+ case . home: return homePosition. exists
1756+ case . alarms: return alarmsPosition. exists
1757+ case . remote: return remotePosition. exists
1758+ case . nightscout: return nightscoutPosition. exists
1759+ case . snoozer: return snoozerPosition. exists
1760+ case . stats: return statisticsPosition. exists
1761+ case . treatments: return treatmentsPosition. exists
1762+ }
1763+ }
17221764}
0 commit comments