Просмотр исходного кода

replace @FetchRequest for glucose in stats with background fetching

polscm32 1 год назад
Родитель
Сommit
eb9cc17061

+ 42 - 27
FreeAPS/Sources/Modules/Stat/StatStateModel.swift

@@ -13,12 +13,23 @@ extension Stat {
         @Published var units: GlucoseUnits = .mmolL
         @Published var glucoseFromPersistence: [GlucoseStored] = []
 
+        @Published var selectedDuration: Duration = .Today
+
         private let context = CoreDataStack.shared.newTaskContext()
         private let viewContext = CoreDataStack.shared.persistentContainer.viewContext
 
+        enum Duration: String, CaseIterable, Identifiable {
+            case Today
+            case Day
+            case Week
+            case Month
+            case Total
+            var id: Self { self }
+        }
+
         override func subscribe() {
-            setupNotifications()
-            setupGlucoseArray()
+            /// Default is today
+            setupGlucoseArray(for: .Today)
             highLimit = settingsManager.settings.high
             lowLimit = settingsManager.settings.low
             units = settingsManager.settings.units
@@ -26,36 +37,40 @@ extension Stat {
             layingChart = settingsManager.settings.oneDimensionalGraph
         }
 
-        private func setupNotifications() {
-            /// custom notification that is sent when a batch insert of glucose objects is done
-            Foundation.NotificationCenter.default.addObserver(
-                self,
-                selector: #selector(handleBatchInsert),
-                name: .didPerformBatchInsert,
-                object: nil
-            )
-        }
-
-        @objc private func handleBatchInsert() {
-            setupGlucoseArray()
-        }
-
-        private func setupGlucoseArray() {
+        func setupGlucoseArray(for duration: Duration) {
             Task {
-                let ids = await self.fetchGlucose()
+                let ids = await self.fetchGlucose(for: duration)
                 await updateGlucoseArray(with: ids)
             }
         }
 
-        private func fetchGlucose() async -> [NSManagedObjectID] {
-            CoreDataStack.shared.fetchEntities(
-                ofType: GlucoseStored.self,
-                onContext: context,
-                predicate: NSPredicate.glucose,
-                key: "date",
-                ascending: false,
-                fetchLimit: 288
-            ).map(\.objectID)
+        private func fetchGlucose(for duration: Duration) async -> [NSManagedObjectID] {
+            await context.perform {
+                let predicate: NSPredicate
+
+                switch duration {
+                case .Day:
+                    predicate = NSPredicate.glucoseForStatsDay
+                case .Week:
+                    predicate = NSPredicate.glucoseForStatsWeek
+                case .Today:
+                    predicate = NSPredicate.glucoseForStatsToday
+                case .Month:
+                    predicate = NSPredicate.glucoseForStatsMonth
+                case .Total:
+                    predicate = NSPredicate.glucoseForStatsTotal
+                }
+
+                return CoreDataStack.shared.fetchEntities(
+                    ofType: GlucoseStored.self,
+                    onContext: self.context,
+                    predicate: predicate,
+                    key: "date",
+                    ascending: false,
+                    batchSize: 100,
+                    propertiesToFetch: ["glucose", "date"]
+                ).map(\.objectID)
+            }
         }
 
         @MainActor private func updateGlucoseArray(with IDs: [NSManagedObjectID]) {

+ 0 - 1
FreeAPS/Sources/Modules/Stat/View/ChartsView.swift

@@ -34,7 +34,6 @@ struct ChartsView: View {
     }
 
     init(
-        filter _: NSDate,
         _ highLimit: Binding<Decimal>,
         _ lowLimit: Binding<Decimal>,
         _ units: Binding<GlucoseUnits>,

+ 6 - 20
FreeAPS/Sources/Modules/Stat/View/StatRootView.swift

@@ -21,16 +21,6 @@ extension Stat {
 
         @Environment(\.colorScheme) var colorScheme
 
-        enum Duration: String, CaseIterable, Identifiable {
-            case Today
-            case Day
-            case Week
-            case Month
-            case Total
-            var id: Self { self }
-        }
-
-        @State private var selectedDuration: Duration = .Today
         @State var paddingAmount: CGFloat? = 10
         @State var headline: Color = .secondary
         @State var days: Double = 0
@@ -58,7 +48,7 @@ extension Stat {
             ZStack {
                 Color.gray.opacity(0.05).ignoresSafeArea(.all)
                 let filter = DateFilter()
-                switch selectedDuration {
+                switch state.selectedDuration {
                 case .Today:
                     StatsView(
                         filter: filter.today,
@@ -104,11 +94,9 @@ extension Stat {
         }
 
         @ViewBuilder func chart() -> some View {
-            let filter = DateFilter()
-            switch selectedDuration {
+            switch state.selectedDuration {
             case .Today:
                 ChartsView(
-                    filter: filter.today,
                     $state.highLimit,
                     $state.lowLimit,
                     $state.units,
@@ -118,7 +106,6 @@ extension Stat {
                 )
             case .Day:
                 ChartsView(
-                    filter: filter.day,
                     $state.highLimit,
                     $state.lowLimit,
                     $state.units,
@@ -128,7 +115,6 @@ extension Stat {
                 )
             case .Week:
                 ChartsView(
-                    filter: filter.week,
                     $state.highLimit,
                     $state.lowLimit,
                     $state.units,
@@ -138,7 +124,6 @@ extension Stat {
                 )
             case .Month:
                 ChartsView(
-                    filter: filter.month,
                     $state.highLimit,
                     $state.lowLimit,
                     $state.units,
@@ -148,7 +133,6 @@ extension Stat {
                 )
             case .Total:
                 ChartsView(
-                    filter: filter.total,
                     $state.highLimit,
                     $state.lowLimit,
                     $state.units,
@@ -162,10 +146,12 @@ extension Stat {
         var body: some View {
             VStack(alignment: .center) {
                 chart().padding(.top, 20)
-                Picker("Duration", selection: $selectedDuration) {
-                    ForEach(Duration.allCases) { duration in
+                Picker("Duration", selection: $state.selectedDuration) {
+                    ForEach(Stat.StateModel.Duration.allCases) { duration in
                         Text(NSLocalizedString(duration.rawValue, comment: "")).tag(Optional(duration))
                     }
+                }.onChange(of: state.selectedDuration) { newValue in
+                    state.setupGlucoseArray(for: newValue)
                 }
                 .pickerStyle(.segmented).background(.cyan.opacity(0.2))
                 stats()

+ 25 - 0
Model/Helper/GlucoseStored+helper.swift

@@ -40,6 +40,31 @@ extension NSPredicate {
         let date = Date.oneDayAgo
         return NSPredicate(format: "isManual == %@ AND date >= %@", true as NSNumber, date as NSDate)
     }
+
+    static var glucoseForStatsDay: NSPredicate {
+        let date = Date.oneDayAgo
+        return NSPredicate(format: "date >= %@", date as NSDate)
+    }
+
+    static var glucoseForStatsToday: NSPredicate {
+        let date = Date.startOfToday
+        return NSPredicate(format: "date >= %@", date as NSDate)
+    }
+
+    static var glucoseForStatsMonth: NSPredicate {
+        let date = Date.oneMonthAgo
+        return NSPredicate(format: "date >= %@", date as NSDate)
+    }
+
+    static var glucoseForStatsTotal: NSPredicate {
+        let date = Date.threeMonthsAgo
+        return NSPredicate(format: "date >= %@", date as NSDate)
+    }
+
+    static var glucoseForStatsWeek: NSPredicate {
+        let date = Date.oneWeekAgo
+        return NSPredicate(format: "date >= %@", date as NSDate)
+    }
 }
 
 extension GlucoseStored: Encodable {

+ 4 - 0
Model/Helper/NSPredicates.swift

@@ -2,6 +2,10 @@ import CoreData
 import Foundation
 
 extension Date {
+    static var startOfToday: Date {
+        Calendar.current.startOfDay(for: Date())
+    }
+
     static var oneDayAgo: Date {
         Calendar.current.date(byAdding: .day, value: -1, to: Date())!
     }