Storage+Migrate.swift 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // LoopFollow
  2. // Storage+Migrate.swift
  3. // Created by Jonas Björkert on 2025-05-26.
  4. import Foundation
  5. extension Storage {
  6. func migrate() {
  7. // Helper: 1-to-1 type -----------------------------------------------------------------
  8. func move<T: AnyConvertible & Equatable>(
  9. _ legacy: @autoclosure () -> UserDefaultsValue<T>,
  10. into newValue: StorageValue<T>
  11. ) {
  12. let item = legacy()
  13. guard item.exists else { return }
  14. newValue.value = item.value
  15. item.setNil(key: item.key)
  16. }
  17. // Helper: Float → Double ------------------------------------------------------------
  18. func moveFloatToDouble(
  19. _ legacy: @autoclosure () -> UserDefaultsValue<Float>,
  20. into newValue: StorageValue<Double>
  21. ) {
  22. let item = legacy()
  23. guard item.exists else { return }
  24. newValue.value = Double(item.value)
  25. item.setNil(key: item.key)
  26. }
  27. if !UserDefaultsRepository.backgroundRefresh.value {
  28. Storage.shared.backgroundRefreshType.value = .none
  29. UserDefaultsRepository.backgroundRefresh.value = true
  30. }
  31. // Remove this in a year later than the release of the new Alarms [BEGIN]
  32. let legacyColorBGText = UserDefaultsValue<Bool>(key: "colorBGText", default: true)
  33. if legacyColorBGText.exists {
  34. Storage.shared.colorBGText.value = legacyColorBGText.value
  35. legacyColorBGText.setNil(key: "colorBGText")
  36. }
  37. let legacyAppBadge = UserDefaultsValue<Bool>(key: "appBadge", default: true)
  38. if legacyAppBadge.exists {
  39. Storage.shared.appBadge.value = legacyAppBadge.value
  40. legacyAppBadge.setNil(key: "appBadge")
  41. }
  42. let legacyForceDarkMode = UserDefaultsValue<Bool>(key: "forceDarkMode", default: true)
  43. if legacyForceDarkMode.exists {
  44. Storage.shared.forceDarkMode.value = legacyForceDarkMode.value
  45. legacyForceDarkMode.setNil(key: "forceDarkMode")
  46. }
  47. let legacyShowStats = UserDefaultsValue<Bool>(key: "showStats", default: true)
  48. if legacyShowStats.exists {
  49. Storage.shared.showStats.value = legacyShowStats.value
  50. legacyShowStats.setNil(key: "showStats")
  51. }
  52. let legacyUseIFCC = UserDefaultsValue<Bool>(key: "useIFCC", default: false)
  53. if legacyUseIFCC.exists {
  54. Storage.shared.useIFCC.value = legacyUseIFCC.value
  55. legacyUseIFCC.setNil(key: "useIFCC")
  56. }
  57. let legacyShowSmallGraph = UserDefaultsValue<Bool>(key: "showSmallGraph", default: true)
  58. if legacyShowSmallGraph.exists {
  59. Storage.shared.showSmallGraph.value = legacyShowSmallGraph.value
  60. legacyShowSmallGraph.setNil(key: "showSmallGraph")
  61. }
  62. let legacyScreenlockSwitchState = UserDefaultsValue<Bool>(key: "screenlockSwitchState", default: true)
  63. if legacyScreenlockSwitchState.exists {
  64. Storage.shared.screenlockSwitchState.value = legacyScreenlockSwitchState.value
  65. legacyScreenlockSwitchState.setNil(key: "screenlockSwitchState")
  66. }
  67. let legacyShowDisplayName = UserDefaultsValue<Bool>(key: "showDisplayName", default: false)
  68. if legacyShowDisplayName.exists {
  69. Storage.shared.showDisplayName.value = legacyShowDisplayName.value
  70. legacyShowDisplayName.setNil(key: "showDisplayName")
  71. }
  72. let legacySpeakBG = UserDefaultsValue<Bool>(key: "speakBG", default: false)
  73. if legacySpeakBG.exists {
  74. Storage.shared.speakBG.value = legacySpeakBG.value
  75. legacySpeakBG.setNil(key: "speakBG")
  76. }
  77. let legacySpeakBGAlways = UserDefaultsValue<Bool>(key: "speakBGAlways", default: true)
  78. if legacySpeakBGAlways.exists {
  79. Storage.shared.speakBGAlways.value = legacySpeakBGAlways.value
  80. legacySpeakBGAlways.setNil(key: "speakBGAlways")
  81. }
  82. let legacySpeakLowBG = UserDefaultsValue<Bool>(key: "speakLowBG", default: false)
  83. if legacySpeakLowBG.exists {
  84. Storage.shared.speakLowBG.value = legacySpeakLowBG.value
  85. legacySpeakLowBG.setNil(key: "speakLowBG")
  86. }
  87. let legacySpeakProactiveLowBG = UserDefaultsValue<Bool>(key: "speakProactiveLowBG", default: false)
  88. if legacySpeakProactiveLowBG.exists {
  89. Storage.shared.speakProactiveLowBG.value = legacySpeakProactiveLowBG.value
  90. legacySpeakProactiveLowBG.setNil(key: "speakProactiveLowBG")
  91. }
  92. let legacySpeakFastDropDelta = UserDefaultsValue<Float>(key: "speakFastDropDelta", default: 10.0)
  93. if legacySpeakFastDropDelta.exists {
  94. Storage.shared.speakFastDropDelta.value = Double(legacySpeakFastDropDelta.value)
  95. legacySpeakFastDropDelta.setNil(key: "speakFastDropDelta")
  96. }
  97. let legacySpeakLowBGLimit = UserDefaultsValue<Float>(key: "speakLowBGLimit", default: 72.0)
  98. if legacySpeakLowBGLimit.exists {
  99. Storage.shared.speakLowBGLimit.value = Double(legacySpeakLowBGLimit.value)
  100. legacySpeakLowBGLimit.setNil(key: "speakLowBGLimit")
  101. }
  102. let legacySpeakHighBGLimit = UserDefaultsValue<Float>(key: "speakHighBGLimit", default: 180.0)
  103. if legacySpeakHighBGLimit.exists {
  104. Storage.shared.speakHighBGLimit.value = Double(legacySpeakHighBGLimit.value)
  105. legacySpeakHighBGLimit.setNil(key: "speakHighBGLimit")
  106. }
  107. let legacySpeakHighBG = UserDefaultsValue<Bool>(key: "speakHighBG", default: false)
  108. if legacySpeakHighBG.exists {
  109. Storage.shared.speakHighBG.value = legacySpeakHighBG.value
  110. legacySpeakHighBG.setNil(key: "speakHighBG")
  111. }
  112. let legacySpeakLanguage = UserDefaultsValue<String>(key: "speakLanguage", default: "en")
  113. if legacySpeakLanguage.exists {
  114. Storage.shared.speakLanguage.value = legacySpeakLanguage.value
  115. legacySpeakLanguage.setNil(key: "speakLanguage")
  116. }
  117. // ── General (done earlier, but safe to repeat) ──
  118. move(UserDefaultsValue<Bool>(key: "colorBGText", default: true), into: Storage.shared.colorBGText)
  119. move(UserDefaultsValue<Bool>(key: "appBadge", default: true), into: appBadge)
  120. move(UserDefaultsValue<Bool>(key: "forceDarkMode", default: false), into: forceDarkMode)
  121. move(UserDefaultsValue<Bool>(key: "showStats", default: true), into: showStats)
  122. move(UserDefaultsValue<Bool>(key: "useIFCC", default: false), into: useIFCC)
  123. move(UserDefaultsValue<Bool>(key: "showSmallGraph", default: true), into: showSmallGraph)
  124. move(UserDefaultsValue<Bool>(key: "screenlockSwitchState", default: false), into: screenlockSwitchState)
  125. move(UserDefaultsValue<Bool>(key: "showDisplayName", default: false), into: showDisplayName)
  126. // ── Speak-BG ──
  127. move(UserDefaultsValue<Bool>(key: "speakBG", default: false), into: speakBG)
  128. move(UserDefaultsValue<Bool>(key: "speakBGAlways", default: true), into: speakBGAlways)
  129. move(UserDefaultsValue<Bool>(key: "speakLowBG", default: false), into: speakLowBG)
  130. move(UserDefaultsValue<Bool>(key: "speakProactiveLowBG", default: false), into: speakProactiveLowBG)
  131. move(UserDefaultsValue<Bool>(key: "speakHighBG", default: false), into: speakHighBG)
  132. moveFloatToDouble(UserDefaultsValue<Float>(key: "speakLowBGLimit", default: 72.0), into: speakLowBGLimit)
  133. moveFloatToDouble(UserDefaultsValue<Float>(key: "speakHighBGLimit", default: 180.0), into: speakHighBGLimit)
  134. moveFloatToDouble(UserDefaultsValue<Float>(key: "speakFastDropDelta", default: 10.0), into: speakFastDropDelta)
  135. move(UserDefaultsValue<String>(key: "speakLanguage", default: "en"), into: speakLanguage)
  136. // ── Graph ──
  137. move(UserDefaultsValue<Bool>(key: "showDots", default: true), into: showDots)
  138. move(UserDefaultsValue<Bool>(key: "showLines", default: true), into: showLines)
  139. move(UserDefaultsValue<Bool>(key: "showValues", default: true), into: showValues)
  140. move(UserDefaultsValue<Bool>(key: "showAbsorption", default: true), into: showAbsorption)
  141. move(UserDefaultsValue<Bool>(key: "showDIAMarkers", default: true), into: showDIALines)
  142. move(UserDefaultsValue<Bool>(key: "show30MinLine", default: false), into: show30MinLine)
  143. move(UserDefaultsValue<Bool>(key: "show90MinLine", default: false), into: show90MinLine)
  144. move(UserDefaultsValue<Bool>(key: "showMidnightMarkers", default: false), into: showMidnightLines)
  145. move(UserDefaultsValue<Bool>(key: "smallGraphTreatments", default: true), into: smallGraphTreatments)
  146. move(UserDefaultsValue<Int>(key: "smallGraphHeight", default: 40), into: smallGraphHeight)
  147. move(UserDefaultsValue<Double>(key: "predictionToLoad", default: 1.0), into: predictionToLoad)
  148. move(UserDefaultsValue<Double>(key: "minBasalScale", default: 5.0), into: minBasalScale)
  149. moveFloatToDouble(UserDefaultsValue<Float>(key: "minBGScale", default: 250.0), into: minBGScale)
  150. moveFloatToDouble(UserDefaultsValue<Float>(key: "lowLine", default: 70.0), into: lowLine)
  151. moveFloatToDouble(UserDefaultsValue<Float>(key: "highLine", default: 180.0), into: highLine)
  152. move(UserDefaultsValue<Int>(key: "downloadDays", default: 1), into: downloadDays)
  153. // Remove this in a year later than the release of the new Alarms [END]
  154. // ── Watch / Calendar ────────────────────────────────────────────────
  155. move(UserDefaultsValue<Bool>(key: "writeCalendarEvent", default: false), into: writeCalendarEvent)
  156. move(UserDefaultsValue<String>(key: "calendarIdentifier", default: ""), into: calendarIdentifier)
  157. move(UserDefaultsValue<String>(key: "watchLine1", default: "%BG% %DIRECTION% %DELTA% %MINAGO%"), into: watchLine1)
  158. move(UserDefaultsValue<String>(key: "watchLine2", default: "C:%COB% I:%IOB% B:%BASAL%"), into: watchLine2)
  159. }
  160. }