فهرست منبع

Replace legend with sheet view with definitions

Deniz Cengiz 1 سال پیش
والد
کامیت
866e4c9bda

+ 2 - 1
FreeAPS/Sources/Application/FreeAPSApp.swift

@@ -134,7 +134,8 @@ import Swinject
             days: 2,
             relationshipKey: "forecast"
         )
-        async let overrideDeletion: () = coreDataStack.batchDeleteOlderThan(OverrideStored.self, dateKey: "date", days: 3, isPresetKey: "isPreset")
+        async let overrideDeletion: () = coreDataStack
+            .batchDeleteOlderThan(OverrideStored.self, dateKey: "date", days: 3, isPresetKey: "isPreset")
         async let overrideRunDeletion: () = coreDataStack
             .batchDeleteOlderThan(OverrideRunStored.self, dateKey: "startDate", days: 3)
 

+ 2 - 0
FreeAPS/Sources/Modules/Home/HomeStateModel.swift

@@ -56,6 +56,8 @@ extension Home {
         @Published var totalBolus: Decimal = 0
 
         @Published var isStatusPopupPresented: Bool = false
+        @Published var isLegendPresented: Bool = false
+        @Published var legendSheetDetent = PresentationDetent.large
         @Published var tins: Bool = false
         @Published var isTempTargetActive: Bool = false
 

+ 0 - 17
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -153,7 +153,6 @@ struct MainChartView: View {
                     }
                 }
             }
-            legendPanel.padding(.top, 8)
         }
     }
 }
@@ -318,22 +317,6 @@ extension MainChartView {
             .chartYAxis(.hidden)
         }
     }
-
-    var legendPanel: some View {
-        HStack(spacing: 10) {
-            Spacer()
-
-            LegendItem(color: .loopGreen, label: "BG")
-            LegendItem(color: .insulin, label: "IOB")
-            LegendItem(color: .zt, label: "ZT")
-            LegendItem(color: .loopYellow, label: "COB")
-            LegendItem(color: .uam, label: "UAM")
-
-            Spacer()
-        }
-        .padding(.horizontal, 10)
-        .frame(maxWidth: .infinity)
-    }
 }
 
 // MARK: - Calculations

+ 76 - 0
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -34,6 +34,25 @@ extension Home {
 
         let buttonFont = Font.custom("TimeButtonFont", size: 14)
 
+        struct DefinitionRow: View {
+            var term: String
+            var definition: String
+            var color: Color
+
+            var body: some View {
+                VStack(alignment: .leading) {
+                    HStack {
+                        Image(systemName: "circle.fill").foregroundStyle(color)
+                        Text(term).font(.subheadline).fontWeight(.semibold)
+                    }
+                    Text(definition)
+                        .font(.subheadline)
+                        .foregroundColor(.secondary)
+                }
+                .padding(.vertical, 5)
+            }
+        }
+
         @Environment(\.managedObjectContext) var moc
         @Environment(\.colorScheme) var colorScheme
 
@@ -321,6 +340,19 @@ extension Home {
                     )
                     .cornerRadius(20)
                 }
+                Button(action: {
+                    state.isLegendPresented.toggle()
+                }) {
+                    Image(systemName: "info")
+                        .foregroundColor(colorScheme == .dark ? Color.white : Color.black).opacity(0.9)
+                        .frame(width: 20, height: 20)
+                        .background(
+                            colorScheme == .dark ? Color(red: 0.1176470588, green: 0.2352941176, blue: 0.3725490196) :
+                                Color.white
+                        )
+                        .clipShape(Circle())
+                }
+                .padding([.top, .bottom])
             }
             .shadow(
                 color: Color.black.opacity(colorScheme == .dark ? 0.75 : 0.33),
@@ -764,6 +796,50 @@ extension Home {
                             }
                     )
             }
+            .sheet(isPresented: $state.isLegendPresented) {
+                NavigationStack {
+                    Text(
+                        "The oref algorithm determines insulin dosing based on a number of scenarios that it estimates with different types of forecasts."
+                    )
+                    .font(.subheadline)
+                    .foregroundColor(.secondary)
+
+                    List {
+                        DefinitionRow(
+                            term: "IOB (Insulin on Board)",
+                            definition: "Forecasts BG based on the amount of insulin still active in the body.",
+                            color: .insulin
+                        )
+                        DefinitionRow(
+                            term: "ZT (Zero-Temp)",
+                            definition: "Forecasts the worst-case blood glucose (BG) scenario if no carbs are absorbed and insulin delivery is stopped until BG starts rising.",
+                            color: .zt
+                        )
+                        DefinitionRow(
+                            term: "COB (Carbs on Board)",
+                            definition: "Forecasts BG changes by considering the amount of carbohydrates still being absorbed in the body.",
+                            color: .loopYellow
+                        )
+                        DefinitionRow(
+                            term: "UAM (Unannounced Meal)",
+                            definition: "Forecasts BG levels and insulin dosing needs for unexpected meals or other causes of BG rises without prior notice.",
+                            color: .uam
+                        )
+                    }
+                    .padding(.trailing, 10)
+                    .navigationBarTitle("Legend", displayMode: .inline)
+
+                    Button { state.isLegendPresented.toggle() }
+                    label: { Text("Got it!").frame(maxWidth: .infinity, alignment: .center) }
+                        .buttonStyle(.bordered)
+                        .padding(.top)
+                }
+                .padding()
+                .presentationDetents(
+                    [.fraction(0.9), .large],
+                    selection: $state.legendSheetDetent
+                )
+            }
         }
 
         @State var settingsPath = NavigationPath()

+ 7 - 2
Model/CoreDataStack.swift

@@ -178,7 +178,12 @@ extension CoreDataStack {
 
     /// Asynchronously deletes records for entities
     ///  - Tag: batchDelete
-    func batchDeleteOlderThan<T: NSManagedObject>(_ objectType: T.Type, dateKey: String, days: Int, isPresetKey: String? = nil) async throws {
+    func batchDeleteOlderThan<T: NSManagedObject>(
+        _ objectType: T.Type,
+        dateKey: String,
+        days: Int,
+        isPresetKey: String? = nil
+    ) async throws {
         let taskContext = newTaskContext()
         taskContext.name = "deleteContext"
         taskContext.transactionAuthor = "batchDelete"
@@ -188,7 +193,7 @@ extension CoreDataStack {
 
         // Fetch all the objects that are older than the specified days
         let fetchRequest = NSFetchRequest<NSManagedObjectID>(entityName: String(describing: objectType))
-        
+
         // Construct the predicate
         var predicates: [NSPredicate] = [NSPredicate(format: "%K < %@", dateKey, targetDate as NSDate)]
         if let isPresetKey = isPresetKey {