Parcourir la source

Remove icloud backups (#491)

Daniel Mini Johansson il y a 7 mois
Parent
commit
5bdb9a060b

+ 0 - 13
LoopFollow/Loop Follow.entitlements

@@ -6,19 +6,6 @@
 	<string>development</string>
 	<key>com.apple.developer.aps-environment</key>
 	<string>development</string>
-	<key>com.apple.developer.icloud-container-identifiers</key>
-	<array>
-		<string>iCloud.$(CFBundleIdentifier)</string>
-	</array>
-	<key>com.apple.developer.icloud-services</key>
-	<array>
-		<string>CloudDocuments</string>
-		<string>CloudKit</string>
-	</array>
-	<key>com.apple.developer.ubiquity-container-identifiers</key>
-	<array>
-		<string>iCloud.$(CFBundleIdentifier)</string>
-	</array>
 	<key>com.apple.security.app-sandbox</key>
 	<true/>
 	<key>com.apple.security.device.bluetooth</key>

+ 1 - 1
LoopFollow/Nightscout/NightscoutSettingsView.swift

@@ -62,7 +62,7 @@ struct NightscoutSettingsView: View {
                 HStack {
                     Image(systemName: "square.and.arrow.down")
                         .foregroundColor(.blue)
-                    Text("Import Settings from QR Code or iCloud")
+                    Text("Import Settings from QR Code")
                 }
             }
         }

+ 1 - 1
LoopFollow/Settings/DexcomSettingsView.swift

@@ -47,7 +47,7 @@ struct DexcomSettingsView: View {
                 HStack {
                     Image(systemName: "square.and.arrow.down")
                         .foregroundColor(.blue)
-                    Text("Import Settings from QR Code or iCloud")
+                    Text("Import Settings from QR Code")
                 }
             }
         }

+ 0 - 190
LoopFollow/Settings/ImportExport/ImportExportSettingsView.swift

@@ -54,34 +54,6 @@ struct ImportExportSettingsView: View {
                     }
                 }
 
-                // MARK: - iCloud Section
-
-                Section("iCloud Import") {
-                    Button(action: {
-                        viewModel.importFromiCloud()
-                    }) {
-                        HStack {
-                            Image(systemName: "icloud.and.arrow.down")
-                                .foregroundColor(.green)
-                            Text("Import Settings from iCloud")
-                        }
-                    }
-                    .buttonStyle(.plain)
-                }
-
-                Section("iCloud Export") {
-                    Button(action: {
-                        viewModel.exportToiCloud()
-                    }) {
-                        HStack {
-                            Image(systemName: "icloud.and.arrow.up")
-                                .foregroundColor(.blue)
-                            Text("Export All Settings to iCloud")
-                        }
-                    }
-                    .buttonStyle(.plain)
-                }
-
                 // MARK: - Status Message
 
                 if !viewModel.qrCodeErrorMessage.isEmpty {
@@ -148,168 +120,6 @@ struct ImportExportSettingsView: View {
         .sheet(isPresented: $viewModel.showImportConfirmation) {
             ImportConfirmationView(viewModel: viewModel)
         }
-        .sheet(isPresented: $viewModel.showExportSuccessAlert) {
-            ExportSuccessView(viewModel: viewModel)
-        }
-        .sheet(isPresented: $viewModel.showImportNotFoundAlert) {
-            ImportNotFoundView(viewModel: viewModel)
-        }
-    }
-}
-
-struct ImportNotFoundView: View {
-    @ObservedObject var viewModel: ImportExportSettingsViewModel
-
-    var body: some View {
-        NavigationView {
-            VStack(spacing: 20) {
-                // Header
-                VStack(spacing: 12) {
-                    Image(systemName: "icloud.slash")
-                        .font(.system(size: 60))
-                        .foregroundColor(.orange)
-
-                    Text("No Settings Found")
-                        .font(.title2)
-                        .fontWeight(.semibold)
-
-                    Text(viewModel.importNotFoundMessage)
-                        .font(.subheadline)
-                        .foregroundColor(.secondary)
-                        .multilineTextAlignment(.center)
-                        .padding(.horizontal)
-                }
-                .padding(.top, 30)
-
-                Spacer()
-
-                // Done Button
-                Button(action: {
-                    viewModel.showImportNotFoundAlert = false
-                }) {
-                    HStack {
-                        Image(systemName: "xmark")
-                        Text("OK")
-                    }
-                    .font(.headline)
-                    .foregroundColor(.white)
-                    .frame(maxWidth: .infinity)
-                    .padding()
-                    .background(Color.blue)
-                    .cornerRadius(12)
-                }
-                .padding(.horizontal)
-                .padding(.bottom, 20)
-            }
-            .navigationBarHidden(true)
-        }
-    }
-}
-
-struct ExportSuccessView: View {
-    @ObservedObject var viewModel: ImportExportSettingsViewModel
-
-    var body: some View {
-        NavigationView {
-            VStack(spacing: 20) {
-                // Header
-                VStack(spacing: 12) {
-                    Image(systemName: "checkmark.icloud.fill")
-                        .font(.system(size: 60))
-                        .foregroundColor(.green)
-
-                    Text("Export Successful")
-                        .font(.title2)
-                        .fontWeight(.semibold)
-
-                    Text(viewModel.exportSuccessMessage)
-                        .font(.subheadline)
-                        .foregroundColor(.secondary)
-                        .multilineTextAlignment(.center)
-                }
-                .padding(.top, 30)
-
-                // Exported Settings Details
-                if !viewModel.exportSuccessDetails.isEmpty {
-                    VStack(alignment: .leading, spacing: 16) {
-                        Text("Exported Settings")
-                            .font(.headline)
-                            .padding(.horizontal)
-
-                        VStack(spacing: 12) {
-                            ForEach(viewModel.exportSuccessDetails, id: \.self) { detail in
-                                HStack(spacing: 12) {
-                                    Image(systemName: iconForDetail(detail))
-                                        .font(.title2)
-                                        .foregroundColor(colorForDetail(detail))
-                                        .frame(width: 30)
-
-                                    Text(detail)
-                                        .font(.subheadline)
-                                        .lineLimit(2)
-
-                                    Spacer()
-
-                                    Image(systemName: "checkmark.circle.fill")
-                                        .foregroundColor(.green)
-                                }
-                                .padding()
-                                .background(Color(.systemGray6))
-                                .cornerRadius(10)
-                            }
-                        }
-                        .padding(.horizontal)
-                    }
-                }
-
-                Spacer()
-
-                // Done Button
-                Button(action: {
-                    viewModel.showExportSuccessAlert = false
-                }) {
-                    HStack {
-                        Image(systemName: "checkmark")
-                        Text("Done")
-                    }
-                    .font(.headline)
-                    .foregroundColor(.white)
-                    .frame(maxWidth: .infinity)
-                    .padding()
-                    .background(Color.blue)
-                    .cornerRadius(12)
-                }
-                .padding(.horizontal)
-                .padding(.bottom, 20)
-            }
-            .navigationBarHidden(true)
-        }
-    }
-
-    private func iconForDetail(_ detail: String) -> String {
-        if detail.lowercased().contains("nightscout") {
-            return "network"
-        } else if detail.lowercased().contains("dexcom") {
-            return "person.circle"
-        } else if detail.lowercased().contains("remote") {
-            return "antenna.radiowaves.left.and.right"
-        } else if detail.lowercased().contains("alarm") {
-            return "bell"
-        }
-        return "gear"
-    }
-
-    private func colorForDetail(_ detail: String) -> Color {
-        if detail.lowercased().contains("nightscout") {
-            return .blue
-        } else if detail.lowercased().contains("dexcom") {
-            return .green
-        } else if detail.lowercased().contains("remote") {
-            return .orange
-        } else if detail.lowercased().contains("alarm") {
-            return .red
-        }
-        return .gray
     }
 }
 

+ 12 - 136
LoopFollow/Settings/ImportExport/ImportExportSettingsViewModel.swift

@@ -36,12 +36,14 @@ class ImportExportSettingsViewModel: ObservableObject {
 
     enum ExportType: String, CaseIterable {
         case nightscout = "Nightscout Settings"
+        case dexcom = "Dexcom Share Settings"
         case remote = "Remote Settings"
         case alarms = "Alarm Settings"
 
         var icon: String {
             switch self {
             case .nightscout: return "network"
+            case .dexcom: return "network"
             case .remote: return "antenna.radiowaves.left.and.right"
             case .alarms: return "bell"
             }
@@ -207,6 +209,16 @@ class ImportExportSettingsViewModel: ObservableObject {
                 alarms: alarmSettings,
                 exportType: exportType.rawValue
             )
+        case .dexcom:
+            let dexcomSettings = DexcomSettingsExport.fromCurrentStorage()
+            if !dexcomSettings.hasValidSettings() {
+                qrCodeErrorMessage = "Please configure your Dexcom Share settings first (username and password)"
+                return nil
+            }
+            settings = CombinedSettingsExport(
+                dexcom: dexcomSettings,
+                exportType: exportType.rawValue
+            )
         }
 
         return settings?.encodeToJSON()
@@ -238,142 +250,6 @@ class ImportExportSettingsViewModel: ObservableObject {
         exportedAlarmIds.removeAll()
     }
 
-    // MARK: - iCloud Methods
-
-    /// Returns the iCloud container URL for persistent storage (survives app deletion)
-    /// Falls back to local Documents if iCloud is not available
-    private func getICloudContainerURL() -> URL? {
-        if let iCloudURL = FileManager.default.url(forUbiquityContainerIdentifier: nil) {
-            let documentsURL = iCloudURL.appendingPathComponent("Documents")
-            if !FileManager.default.fileExists(atPath: documentsURL.path) {
-                try? FileManager.default.createDirectory(at: documentsURL, withIntermediateDirectories: true)
-            }
-            return documentsURL
-        }
-        return nil
-    }
-
-    func exportToiCloud() {
-        // Create a comprehensive settings export for iCloud
-        let nightscoutSettings = NightscoutSettingsExport.fromCurrentStorage()
-        let dexcomSettings = DexcomSettingsExport.fromCurrentStorage()
-        let remoteSettings = RemoteSettingsExport.fromCurrentStorage()
-        let alarmSettings = AlarmSettingsExport.fromCurrentStorage()
-
-        let allSettings = CombinedSettingsExport(
-            nightscout: nightscoutSettings,
-            dexcom: dexcomSettings,
-            remote: remoteSettings,
-            alarms: alarmSettings,
-            exportType: "All Settings"
-        )
-
-        guard let jsonData = allSettings.encodeToJSON()?.data(using: .utf8) else {
-            qrCodeErrorMessage = "Failed to prepare settings for iCloud export"
-            return
-        }
-
-        guard let iCloudDocumentsPath = getICloudContainerURL() else {
-            qrCodeErrorMessage = "iCloud is not available. Please sign in to iCloud in Settings and enable iCloud Drive."
-            LogManager.shared.log(category: .general, message: "iCloud ubiquity container not available")
-            return
-        }
-
-        let fileName = "\(AppConstants.appInstanceId)Settings.json"
-        let iCloudPath = iCloudDocumentsPath.appendingPathComponent(fileName)
-
-        LogManager.shared.log(category: .general, message: "Attempting to export settings to iCloud")
-        LogManager.shared.log(category: .general, message: "iCloud ubiquity container path: \(iCloudDocumentsPath.path)")
-        LogManager.shared.log(category: .general, message: "Saving settings file to: \(iCloudPath.path)")
-
-        do {
-            try jsonData.write(to: iCloudPath)
-
-            // Build export details for the success alert - show what's being exported
-            var details: [String] = []
-
-            // Nightscout - show if URL is configured
-            if !nightscoutSettings.url.isEmpty {
-                details.append("Nightscout: \(nightscoutSettings.url)")
-            }
-
-            // Dexcom - show if username is configured
-            if !dexcomSettings.userName.isEmpty {
-                details.append("Dexcom: \(dexcomSettings.userName)")
-            }
-
-            // Remote - only show if a remote type is actually configured (not "none")
-            if remoteSettings.remoteType != .none {
-                details.append("Remote: \(remoteSettings.remoteType.rawValue)")
-            }
-
-            // Alarms - show if any alarms exist
-            if !alarmSettings.alarms.isEmpty {
-                details.append("Alarms: \(alarmSettings.alarms.count) alarm(s)")
-            }
-
-            exportSuccessDetails = details
-            exportSuccessMessage = "Settings saved to iCloud"
-            showExportSuccessAlert = true
-            qrCodeErrorMessage = "" // Clear any previous error
-
-            LogManager.shared.log(category: .general, message: "All settings exported to iCloud successfully")
-        } catch {
-            qrCodeErrorMessage = "Failed to export to iCloud: \(error.localizedDescription)"
-        }
-    }
-
-    func importFromiCloud() {
-        // Try to read from iCloud ubiquity container (persists after app deletion)
-        guard let iCloudDocumentsPath = getICloudContainerURL() else {
-            importNotFoundMessage = "iCloud is not available.\n\nPlease sign in to iCloud in Settings and enable iCloud Drive."
-            showImportNotFoundAlert = true
-            LogManager.shared.log(category: .general, message: "iCloud ubiquity container not available for import")
-            return
-        }
-
-        let fileName = "\(AppConstants.appInstanceId)Settings.json"
-        let iCloudPath = iCloudDocumentsPath.appendingPathComponent(fileName)
-
-        LogManager.shared.log(category: .general, message: "Attempting to import settings from iCloud")
-        LogManager.shared.log(category: .general, message: "iCloud ubiquity container path: \(iCloudDocumentsPath.path)")
-        LogManager.shared.log(category: .general, message: "Looking for settings file: \(iCloudPath.path)")
-
-        guard FileManager.default.fileExists(atPath: iCloudPath.path) else {
-            LogManager.shared.log(category: .general, message: "Settings file not found at: \(iCloudPath.path)")
-            importNotFoundMessage = "No settings file found in iCloud.\n\nMake sure you have previously exported settings to iCloud from this app."
-            showImportNotFoundAlert = true
-            return
-        }
-
-        do {
-            LogManager.shared.log(category: .general, message: "Settings file found, attempting to read data")
-
-            let data = try Data(contentsOf: iCloudPath)
-            guard let settings = SettingsMigrationManager.migrateSettings(data) else {
-                qrCodeErrorMessage = "Failed to decode settings from iCloud"
-                return
-            }
-
-            // Check version compatibility
-            let currentVersion = AppVersionManager().version()
-            if !SettingsMigrationManager.isCompatibleVersion(settings.appVersion) {
-                qrCodeErrorMessage = SettingsMigrationManager.getCompatibilityMessage(for: settings.appVersion)
-                // Still try to apply settings, but warn user
-            }
-
-            // Store settings and create preview for confirmation
-            pendingImportSettings = settings
-            pendingImportSource = "iCloud"
-            createImportPreview(from: settings)
-
-        } catch {
-            let currentVersion = AppVersionManager().version()
-            qrCodeErrorMessage = "iCloud import failed. This might be due to a version change (current: \(currentVersion)). Please try exporting settings to iCloud again."
-            LogManager.shared.log(category: .general, message: "iCloud import failed: \(error.localizedDescription)")
-        }
-    }
-
     private func createImportPreview(from settings: CombinedSettingsExport) {
         let nightscoutURL = settings.nightscout?.url.isEmpty == false ? settings.nightscout?.url : nil
         let dexcomUsername = settings.dexcom?.userName.isEmpty == false ? settings.dexcom?.userName : nil