SettingsMigrationManager.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // LoopFollow
  2. // SettingsMigrationManager.swift
  3. import Foundation
  4. class SettingsMigrationManager {
  5. // MARK: - Current Version
  6. static let currentVersion = "1.0"
  7. // MARK: - Migration Methods
  8. static func migrateSettings(_ data: Data) -> CombinedSettingsExport? {
  9. // Try to decode with the current version
  10. do {
  11. let currentSettings = try JSONDecoder().decode(CombinedSettingsExport.self, from: data)
  12. LogManager.shared.log(category: .general, message: "Successfully decoded CombinedSettingsExport", isDebug: true)
  13. return currentSettings
  14. } catch {
  15. LogManager.shared.log(category: .general, message: "Failed to decode CombinedSettingsExport: \(String(describing: type(of: error)))", isDebug: true)
  16. // Try to decode as individual components
  17. return tryDecodeIndividualComponents(data)
  18. }
  19. }
  20. private static func tryDecodeIndividualComponents(_ data: Data) -> CombinedSettingsExport? {
  21. // Try to decode as AlarmSettingsExport
  22. if let alarmSettings = try? JSONDecoder().decode(AlarmSettingsExport.self, from: data) {
  23. LogManager.shared.log(category: .general, message: "Successfully decoded as AlarmSettingsExport", isDebug: true)
  24. return CombinedSettingsExport(
  25. alarms: alarmSettings,
  26. exportType: "Alarm Settings"
  27. )
  28. }
  29. // Try to decode as NightscoutSettingsExport
  30. if let nightscoutSettings = try? JSONDecoder().decode(NightscoutSettingsExport.self, from: data) {
  31. LogManager.shared.log(category: .general, message: "Successfully decoded as NightscoutSettingsExport", isDebug: true)
  32. return CombinedSettingsExport(
  33. nightscout: nightscoutSettings,
  34. exportType: "Nightscout Settings"
  35. )
  36. }
  37. // Try to decode as DexcomSettingsExport
  38. if let dexcomSettings = try? JSONDecoder().decode(DexcomSettingsExport.self, from: data) {
  39. LogManager.shared.log(category: .general, message: "Successfully decoded as DexcomSettingsExport", isDebug: true)
  40. return CombinedSettingsExport(
  41. dexcom: dexcomSettings,
  42. exportType: "Dexcom Settings"
  43. )
  44. }
  45. // Try to decode as RemoteSettingsExport
  46. if let remoteSettings = try? JSONDecoder().decode(RemoteSettingsExport.self, from: data) {
  47. LogManager.shared.log(category: .general, message: "Successfully decoded as RemoteSettingsExport", isDebug: true)
  48. return CombinedSettingsExport(
  49. remote: remoteSettings,
  50. exportType: "Remote Settings"
  51. )
  52. }
  53. // Try to decode as APNSSettingsExport
  54. if let apnsSettings = try? JSONDecoder().decode(APNSSettingsExport.self, from: data) {
  55. LogManager.shared.log(category: .general, message: "Successfully decoded as APNSSettingsExport", isDebug: true)
  56. return CombinedSettingsExport(
  57. apns: apnsSettings,
  58. exportType: "APNS Settings"
  59. )
  60. }
  61. LogManager.shared.log(category: .general, message: "Failed to decode as any known component", isDebug: true)
  62. return nil
  63. }
  64. // MARK: - Version Compatibility
  65. static func isCompatibleVersion(_ version: String) -> Bool {
  66. let currentVersionComponents = currentVersion.split(separator: ".").compactMap { Int($0) }
  67. let importVersionComponents = version.split(separator: ".").compactMap { Int($0) }
  68. // For now, accept any version (can be made more strict later)
  69. return true
  70. }
  71. static func getCompatibilityMessage(for version: String) -> String {
  72. return String(localized: "Settings from version \(version) may not be fully compatible with current version \(currentVersion). Some features may not work as expected.")
  73. }
  74. // MARK: - Error Handling
  75. enum SettingsImportError: Error {
  76. case unsupportedVersion(String)
  77. case migrationFailed(String)
  78. case corruptedData
  79. case incompatibleAlarmFormat
  80. case unknownError
  81. }
  82. }