Browse Source

Add extensive logging; add MigrationErrorView WIP

Deniz Cengiz 1 năm trước cách đây
mục cha
commit
1a5befc7e6

+ 19 - 19
Model/JSONImporter.swift

@@ -748,7 +748,7 @@ extension JSONImporter {
 
     func importGlucoseHistoryIfNeeded() async throws {
         debug(.coreData, "Checking for glucose history JSON file...")
-        
+
         let url = openAPSFileURL(OpenAPS.Monitor.glucose)
         let suffix = "migrated.json"
 
@@ -756,24 +756,24 @@ extension JSONImporter {
             debug(.coreData, "❌ No JSON file to import at \(url.path)")
             return
         }
-        
+
         debug(.coreData, "Glucose history JSON file found, proceeding with import of glucose history...")
-        
+
         try await importGlucoseHistory(url: url, now: Date())
 
         debug(.coreData, "Glucose history JSON file imported successfully, moving to \(suffix)")
-        
+
         try FileManager.default.moveItem(
             at: url,
             to: url.deletingPathExtension().appendingPathExtension(suffix)
         )
-        
+
         debug(.coreData, "Import of glucose history completed successfully.")
     }
 
     func importPumpHistoryIfNeeded() async throws {
         debug(.coreData, "Checking for pump history JSON file...")
-        
+
         let url = openAPSFileURL(OpenAPS.Monitor.pumpHistory)
         let suffix = "migrated.json"
 
@@ -781,24 +781,24 @@ extension JSONImporter {
             debug(.coreData, "❌ No JSON file to import at \(url.path)")
             return
         }
-        
+
         debug(.coreData, "Pump history JSON file found, proceeding with import of glucose history...")
-        
+
         try await importPumpHistory(url: url, now: Date())
 
         debug(.coreData, "Pump history JSON file imported successfully, moving to \(suffix)")
-        
+
         try FileManager.default.moveItem(
             at: url,
             to: url.deletingPathExtension().appendingPathExtension(suffix)
         )
-        
+
         debug(.coreData, "Import of pump history completed successfully.")
     }
 
     func importCarbHistoryIfNeeded() async throws {
         debug(.coreData, "Checking for carb history JSON file...")
-        
+
         let url = openAPSFileURL(OpenAPS.Monitor.pumpHistory)
         let suffix = "migrated.json"
 
@@ -806,24 +806,24 @@ extension JSONImporter {
             debug(.coreData, "❌ No JSON file to import at \(url.path)")
             return
         }
-        
+
         debug(.coreData, "Carb history JSON file found, proceeding with import of glucose history...")
-        
+
         try await importCarbHistory(url: url, now: Date())
 
         debug(.coreData, "Carb history JSON file imported successfully, moving to \(suffix)")
-        
+
         try FileManager.default.moveItem(
             at: url,
             to: url.deletingPathExtension().appendingPathExtension(suffix)
         )
-        
+
         debug(.coreData, "Import of carb history completed successfully.")
     }
 
     func importDeterminationIfNeeded() async throws {
         debug(.coreData, "Checking for determination JSON files...")
-        
+
         let enactedPath = OpenAPS.Enact.enacted // "enact/enacted.json"
         let suggestedPath = OpenAPS.Enact.suggested // "enact/suggested.json"
         let suffix = "migrated.json"
@@ -837,11 +837,11 @@ extension JSONImporter {
             debug(.coreData, "❌ No JSON file to import at \(enactedURL.path) and/or \(suggestedURL.path)")
             return
         }
-        
+
         debug(.coreData, "Determination JSON files found, proceeding with import...")
 
         try await importOrefDetermination(enactedUrl: enactedURL, suggestedUrl: suggestedURL, now: Date())
-        
+
         debug(.coreData, "Determination JSON file(s) imported successfully, moving to \(suffix)")
 
         try FileManager.default.moveItem(at: enactedURL, to: enactedURL.deletingPathExtension().appendingPathExtension(suffix))
@@ -849,7 +849,7 @@ extension JSONImporter {
             at: suggestedURL,
             to: suggestedURL.deletingPathExtension().appendingPathExtension(suffix)
         )
-        
+
         debug(.coreData, "Import of determination data completed successfully.")
     }
 }

+ 4 - 0
Trio.xcodeproj/project.pbxproj

@@ -557,6 +557,7 @@
 		DD3A3CE72D29C93F00AE478E /* Helper+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3A3CE62D29C93F00AE478E /* Helper+Extensions.swift */; };
 		DD3A3CE92D29C97800AE478E /* Helper+ButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3A3CE82D29C97800AE478E /* Helper+ButtonStyles.swift */; };
 		DD3C47B32DC5608A003DD20D /* newerSuggested.json in Resources */ = {isa = PBXBuildFile; fileRef = DD3C47B22DC5608A003DD20D /* newerSuggested.json */; };
+		DD3C47B52DC57E06003DD20D /* MainMigrationErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3C47B42DC57E06003DD20D /* MainMigrationErrorView.swift */; };
 		DD3F1F832D9DC78800DCE7B3 /* UnitSelectionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3F1F822D9DC78300DCE7B3 /* UnitSelectionStepView.swift */; };
 		DD3F1F852D9DD84000DCE7B3 /* DeliveryLimitsStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3F1F842D9DD83B00DCE7B3 /* DeliveryLimitsStepView.swift */; };
 		DD3F1F892D9E078D00DCE7B3 /* TherapySettingEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3F1F882D9E078300DCE7B3 /* TherapySettingEditorView.swift */; };
@@ -1369,6 +1370,7 @@
 		DD3A3CE62D29C93F00AE478E /* Helper+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Helper+Extensions.swift"; sourceTree = "<group>"; };
 		DD3A3CE82D29C97800AE478E /* Helper+ButtonStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Helper+ButtonStyles.swift"; sourceTree = "<group>"; };
 		DD3C47B22DC5608A003DD20D /* newerSuggested.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = newerSuggested.json; sourceTree = "<group>"; };
+		DD3C47B42DC57E06003DD20D /* MainMigrationErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMigrationErrorView.swift; sourceTree = "<group>"; };
 		DD3F1F822D9DC78300DCE7B3 /* UnitSelectionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitSelectionStepView.swift; sourceTree = "<group>"; };
 		DD3F1F842D9DD83B00DCE7B3 /* DeliveryLimitsStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeliveryLimitsStepView.swift; sourceTree = "<group>"; };
 		DD3F1F882D9E078300DCE7B3 /* TherapySettingEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TherapySettingEditorView.swift; sourceTree = "<group>"; };
@@ -1938,6 +1940,7 @@
 		3811DE1F25C9D48300A708ED /* View */ = {
 			isa = PBXGroup;
 			children = (
+				DD3C47B42DC57E06003DD20D /* MainMigrationErrorView.swift */,
 				3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */,
 				3811DE2025C9D48300A708ED /* MainRootView.swift */,
 			);
@@ -4594,6 +4597,7 @@
 				CE7CA3502A064973004BE681 /* CancelTempPresetIntent.swift in Sources */,
 				6B1F539F9FF75646D1606066 /* SnoozeDataFlow.swift in Sources */,
 				6FFAE524D1D9C262F2407CAE /* SnoozeProvider.swift in Sources */,
+				DD3C47B52DC57E06003DD20D /* MainMigrationErrorView.swift in Sources */,
 				BD4ED4FD2CF9D5E8000EDC9C /* AppState.swift in Sources */,
 				DDF847DD2C5C28720049BB3B /* LiveActivitySettingsDataFlow.swift in Sources */,
 				8194B80890CDD6A3C13B0FEE /* SnoozeStateModel.swift in Sources */,

+ 17 - 17
Trio/Sources/Application/TrioApp.swift

@@ -37,7 +37,7 @@ extension Notification.Name {
     @State private var showLoadingError = false
     @State private var showOnboardingCompletedSplash = false
     @State private var migrationErrors: [String] = []
-    @State private var showMigrationErrorAlert: Bool = false
+    @State private var showMigrationError: Bool = false
 
     // Dependencies Assembler
     // contain all dependencies Assemblies
@@ -170,7 +170,7 @@ extension Notification.Name {
         }
     }
 
-    private func performJsonToCoreDataMigrationIfNeeded() async throws {
+    @MainActor  private func performJsonToCoreDataMigrationIfNeeded() async throws {
         let importer = JSONImporter(context: coreDataStack.newTaskContext(), coreDataStack: coreDataStack)
         var importErrors: [String] = []
 
@@ -178,21 +178,21 @@ extension Notification.Name {
             try await importer.importGlucoseHistoryIfNeeded()
         } catch {
             importErrors
-                .append(String(localized: "Migration of JSON-based Glucose History failed: \(error.localizedDescription)"))
+                .append(String(localized: "Failed to import glucose history."))
             debug(.coreData, "❌ Failed to import JSON-based Glucose History: \(error)")
         }
 
         do {
             try await importer.importPumpHistoryIfNeeded()
         } catch {
-            importErrors.append(String(localized: "Migration of JSON-based Pump History failed: \(error.localizedDescription)"))
+            importErrors.append(String(localized: "Failed to import pump history."))
             debug(.coreData, "❌ Failed to import JSON-based Pump History: \(error)")
         }
 
         do {
             try await importer.importCarbHistoryIfNeeded()
         } catch {
-            importErrors.append(String(localized: "Migration of JSON-based Carb History failed: \(error.localizedDescription)"))
+            importErrors.append(String(localized: "Failed to import algorithm data."))
             debug(.coreData, "❌ Failed to import JSON-based Carb History: \(error)")
         }
 
@@ -206,8 +206,11 @@ extension Notification.Name {
             debug(.coreData, "❌ Failed to import JSON-based OpenAPS Determination Data: \(error)")
         }
 
-        await MainActor.run {
-            self.migrationErrors = importErrors
+        if importErrors.isNotEmpty {
+            await MainActor.run {
+                self.showMigrationError = true
+                self.migrationErrors = importErrors
+            }
         }
     }
 
@@ -274,6 +277,13 @@ extension Notification.Name {
                         .onReceive(Foundation.NotificationCenter.default.publisher(for: .initializationError)) { _ in
                             self.showLoadingError = true
                         }
+                } else if showMigrationError { // FIXME: display of this is not yet working, despite migration errors
+                    Main.MainMigrationErrorView(migrationErrors: self.migrationErrors, onConfirm: {
+                        Task { @MainActor in
+                            showMigrationError = false
+                            migrationErrors = []
+                        }
+                    })
                 } else if showOnboardingCompletedSplash {
                     LogoBurstSplash(isActive: $showOnboardingCompletedSplash) {
                         Main.RootView(resolver: resolver)
@@ -300,16 +310,6 @@ extension Notification.Name {
                         .onOpenURL(perform: handleURL)
                 }
             }
-            // TODO: this is just for testing...
-            .sheet(isPresented: $showMigrationErrorAlert) {
-                if migrationErrors.isNotEmpty {
-                    ForEach(migrationErrors, id: \.self) { message in
-                        Text(message)
-                            .foregroundColor(.red)
-                            .font(.footnote)
-                    }
-                }
-            }
             .onReceive(Foundation.NotificationCenter.default.publisher(for: .onboardingCompleted)) { _ in
                 Task { @MainActor in
                     self.showOnboardingCompletedSplash = true

+ 33 - 9
Trio/Sources/Localizations/Main/Localizable.xcstrings

@@ -98681,6 +98681,15 @@
         }
       }
     },
+    "Failed to import algorithm data." : {
+
+    },
+    "Failed to import glucose history." : {
+
+    },
+    "Failed to import pump history." : {
+
+    },
     "Failed to Suspend Insulin Delivery" : {
       "comment" : "Alert title for suspend error",
       "extractionState" : "manual",
@@ -115704,6 +115713,9 @@
         }
       }
     },
+    "I understand! Proceed" : {
+
+    },
     "Identify and fix bugs and crashes" : {
       "localizations" : {
         "bg" : {
@@ -136289,6 +136301,9 @@
         }
       }
     },
+    "Manually backdate some recent carbs or insulin you’ve entered in the last 6 to 8 hours." : {
+
+    },
     "Manually entered blood glucose, such as a fingerstick test." : {
       "localizations" : {
         "bg" : {
@@ -142817,18 +142832,9 @@
         }
       }
     },
-    "Migration of JSON-based Carb History failed: %@" : {
-
-    },
-    "Migration of JSON-based Glucose History failed: %@" : {
-
-    },
     "Migration of JSON-based OpenAPS Determination Data failed: %@" : {
 
     },
-    "Migration of JSON-based Pump History failed: %@" : {
-
-    },
     "min" : {
       "comment" : "Minutes abbreviation\nShort form for minutes",
       "localizations" : {
@@ -157315,6 +157321,9 @@
         }
       }
     },
+    "Oops! Some data didn’t make it over." : {
+
+    },
     "Open %@" : {
       "localizations" : {
         "bg" : {
@@ -192855,6 +192864,9 @@
         }
       }
     },
+    "Stay in open loop (no automated dosing) for a bit to help Trio catch up to keep you safe" : {
+
+    },
     "Steps" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -209713,6 +209725,9 @@
         }
       }
     },
+    "This means Trio may not have complete information about how much active insulin or carbs were still on board when you switched over." : {
+
+    },
     "This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor" : {
       "comment" : "This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor",
       "extractionState" : "manual",
@@ -216072,6 +216087,9 @@
         }
       }
     },
+    "To stay safe, we recommend:" : {
+
+    },
     "Today" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -221139,6 +221157,9 @@
         }
       }
     },
+    "Trio is still fully functional and will adapt quickly — but your awareness right now helps it keep you safer." : {
+
+    },
     "Trio lets you create automations using iOS Shortcuts. Go to the Shortcuts app to create new automations." : {
       "localizations" : {
         "bg" : {
@@ -236375,6 +236396,9 @@
         }
       }
     },
+    "While upgrading Trio to the new version, we ran into an issue transferring some of your historical data." : {
+
+    },
     "Why does Trio collect this data?" : {
       "localizations" : {
         "bg" : {

+ 133 - 0
Trio/Sources/Modules/Main/View/MainMigrationErrorView.swift

@@ -0,0 +1,133 @@
+//
+//  MainMigrationErrorView.swift
+//  Trio
+//
+//  Created by Cengiz Deniz on 21.04.25.
+//
+import SwiftUI
+
+extension Main {
+    struct MainMigrationErrorView: View {
+        let migrationErrors: [String]
+        let onConfirm: () -> Void
+
+        private let versionNumber = Bundle.main.releaseVersionNumber ?? String(localized: "Unknown")
+
+        var body: some View {
+            ZStack(alignment: .bottom) {
+                LinearGradient(
+                    gradient: Gradient(colors: [Color.bgDarkBlue, Color.bgDarkerDarkBlue]),
+                    startPoint: .top,
+                    endPoint: .bottom
+                )
+                .ignoresSafeArea()
+
+                ScrollView {
+                    VStack {
+                        Spacer().frame(maxHeight: 20)
+
+                        Image(.trioCircledNoBackground)
+                            .resizable()
+                            .scaledToFit()
+                            .frame(width: 80, height: 80)
+                            .shadow(color: Color.white.opacity(0.1), radius: 5, x: 0, y: 0)
+
+                        Text("Trio v\(versionNumber)")
+                            .fontWeight(.heavy)
+                            .foregroundStyle(Color(red: 148 / 255, green: 102 / 255, blue: 234 / 255))
+                            .padding(.vertical)
+
+                        Spacer().frame(maxHeight: 20)
+
+                        VStack(alignment: .leading, spacing: 20) {
+                            Text("Oops! Some data didn’t make it over.").font(.title3).bold()
+
+                            Text(
+                                "While upgrading Trio to the new version, we ran into an issue transferring some of your historical data."
+                            )
+                            .multilineTextAlignment(.leading)
+
+                            VStack(alignment: .leading, spacing: 10) {
+                                ForEach(migrationErrors, id: \.self) { message in
+                                    BulletPoint(message)
+                                }
+                            }
+
+                            Text(
+                                "This means Trio may not have complete information about how much active insulin or carbs were still on board when you switched over."
+                            )
+                            .bold()
+
+                            VStack(alignment: .leading, spacing: 10) {
+                                HStack(alignment: .top, spacing: 10) {
+                                    Image(systemName: "exclamationmark.triangle.fill")
+                                        .foregroundStyle(Color.bgDarkBlue, Color.orange)
+                                        .symbolRenderingMode(.palette)
+                                    Text("To stay safe, we recommend:").foregroundStyle(Color.orange)
+                                }.bold()
+
+                                VStack(alignment: .leading, spacing: 10) {
+                                    BulletPoint(
+                                        String(
+                                            localized: "Manually backdate some recent carbs or insulin you’ve entered in the last 6 to 8 hours."
+                                        )
+                                    )
+                                    BulletPoint(
+                                        String(
+                                            localized: "Stay in open loop (no automated dosing) for a bit to help Trio catch up to keep you safe"
+                                        )
+                                    )
+                                }
+                            }
+                            .frame(maxWidth: .infinity)
+                            .padding()
+                            .background(Color.clear)
+                            .overlay(
+                                RoundedRectangle(cornerRadius: 10)
+                                    .stroke(Color.orange, lineWidth: 2)
+                            )
+                            .cornerRadius(10)
+
+                            Text(
+                                "Trio is still fully functional and will adapt quickly — but your awareness right now helps it keep you safer."
+                            )
+                            .multilineTextAlignment(.leading)
+                            .padding(.bottom)
+                        }
+                        .padding(.horizontal, 24)
+                        .foregroundStyle(.white)
+                    }
+                }
+                .padding(.bottom, 80)
+
+                Button(action: onConfirm) {
+                    Text("I understand! Proceed")
+                        .frame(width: UIScreen.main.bounds.width - 60, height: 50)
+                        .font(.title3).bold()
+                        .background(
+                            Capsule()
+                                .fill(Color.tabBar)
+                        )
+                        .foregroundColor(.white)
+                        .shadow(color: Color.black.opacity(0.1), radius: 5, x: 0, y: 2)
+                }.padding(.bottom)
+            }
+        }
+    }
+}
+
+struct MainMigrationErrorView_Previews: PreviewProvider {
+    static var previews: some View {
+        Group {
+            Main.MainMigrationErrorView(
+                migrationErrors: [
+                    "Failed to import glucose history.",
+                    "Failed to import pump history.",
+                    "Failed to import carb history.",
+                    "Failed to import algorithm data."
+                ],
+                onConfirm: { print("Proceed") }
+            )
+        }
+    }
+}

+ 1 - 1
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/CompletedStepView.swift

@@ -29,7 +29,7 @@ struct CompletedStepView: View {
                     completedItemsView(
                         stepIndex: index + 1,
                         title: chapter.title,
-                        description: chapter.completedDescription,
+                        description: isChapterCompleted(chapter) ? chapter.completedDescription : chapter.overviewDescription,
                         isCompleted: isChapterCompleted(chapter)
                     )