Explorar o código

Refactor chart formatting functions

polscm32 hai 1 ano
pai
achega
53c6c33f47
Modificáronse 1 ficheiros con 75 adicións e 49 borrados
  1. 75 49
      FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

+ 75 - 49
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -67,6 +67,7 @@ struct MainChartView: View {
     @State private var maxValueCobChart: Decimal = 20
     @State private var minValueIobChart: Decimal = 0
     @State private var maxValueIobChart: Decimal = 5
+    @State private var mainChartHasInitialized = false
 
     private let now = Date.now
 
@@ -159,10 +160,6 @@ struct MainChartView: View {
                             }
 
                         }.onChange(of: screenHours) { _ in
-                            updateStartEndMarkers()
-                            yAxisChartData()
-                            yAxisChartDataCobChart()
-                            yAxisChartDataIobChart()
                             scroller.scrollTo("MainChart", anchor: .trailing)
                         }
                         .onChange(of: state.glucoseFromPersistence.last?.glucose) { _ in
@@ -171,24 +168,24 @@ struct MainChartView: View {
                             scroller.scrollTo("MainChart", anchor: .trailing)
                         }
                         .onChange(of: state.enactedAndNonEnactedDeterminations.first?.deliverAt) { _ in
-                            updateStartEndMarkers()
                             yAxisChartDataCobChart()
                             yAxisChartDataIobChart()
                             scroller.scrollTo("MainChart", anchor: .trailing)
                         }
-                        .onChange(of: state.tempBasals) { _ in
-                            updateStartEndMarkers()
-                            scroller.scrollTo("MainChart", anchor: .trailing)
-                        }
                         .onChange(of: units) { _ in
                             yAxisChartData()
-                        }
-                        .onAppear {
-                            updateStartEndMarkers()
-                            yAxisChartData()
                             yAxisChartDataCobChart()
                             yAxisChartDataIobChart()
-                            scroller.scrollTo("MainChart", anchor: .trailing)
+                        }
+                        .onAppear {
+                            if !mainChartHasInitialized {
+                                updateStartEndMarkers()
+                                yAxisChartData()
+                                yAxisChartDataCobChart()
+                                yAxisChartDataIobChart()
+                                mainChartHasInitialized = true
+                                scroller.scrollTo("MainChart", anchor: .trailing)
+                            }
                         }
                     }
                 }
@@ -1110,52 +1107,81 @@ extension MainChartView {
     // MARK: - Chart formatting
 
     private func yAxisChartData() {
-        let glucoseMapped = state.glucoseFromPersistence.map { Decimal($0.glucose) }
-        let forecastValues = state.preprocessedData.map { Decimal($0.forecastValue.value) }
-
-        guard let minGlucose = glucoseMapped.min(), let maxGlucose = glucoseMapped.max(),
-              let minForecast = forecastValues.min(), let maxForecast = forecastValues.max()
-        else {
-            // default values
-            minValue = 45 - 20
-            maxValue = 270 + 50
-            return
-        }
+        Task {
+            let (minGlucose, maxGlucose, minForecast, maxForecast) = await Task
+                .detached { () -> (Decimal?, Decimal?, Decimal?, Decimal?) in
+                    let glucoseMapped = await state.glucoseFromPersistence.map { Decimal($0.glucose) }
+                    let forecastValues = await state.preprocessedData.map { Decimal($0.forecastValue.value) }
+
+                    // Calculate min and max values for glucose and forecast
+                    return (glucoseMapped.min(), glucoseMapped.max(), forecastValues.min(), forecastValues.max())
+                }.value
+
+            // Ensure all values exist, otherwise set default values
+            guard let minGlucose = minGlucose, let maxGlucose = maxGlucose,
+                  let minForecast = minForecast, let maxForecast = maxForecast
+            else {
+                await updateChartBounds(minValue: 45 - 20, maxValue: 270 + 50)
+                return
+            }
 
-        // Ensure maxForecast is not more than 100 over maxGlucose
-        let adjustedMaxForecast = min(maxForecast, maxGlucose + 100)
+            // Adjust max forecast to be no more than 100 over max glucose
+            let adjustedMaxForecast = min(maxForecast, maxGlucose + 100)
+            let minOverall = min(minGlucose, minForecast)
+            let maxOverall = max(maxGlucose, adjustedMaxForecast)
 
-        let minOverall = min(minGlucose, minForecast)
-        let maxOverall = max(maxGlucose, adjustedMaxForecast)
+            // Update the chart bounds on the main thread
+            await updateChartBounds(minValue: minOverall - 50, maxValue: maxOverall + 80)
+        }
+    }
 
-        minValue = minOverall - 50
-        maxValue = maxOverall + 80
+    @MainActor private func updateChartBounds(minValue: Decimal, maxValue: Decimal) async {
+        self.minValue = minValue
+        self.maxValue = maxValue
     }
 
     private func yAxisChartDataCobChart() {
-        let cobMapped = state.enactedAndNonEnactedDeterminations.map { Decimal($0.cob) }
-        guard let maxCob = cobMapped.max() else {
-            // default values
-            minValueCobChart = 0
-            maxValueCobChart = 20
-            return
+        Task {
+            let maxCob = await Task.detached { () -> Decimal? in
+                let cobMapped = await state.enactedAndNonEnactedDeterminations.map { Decimal($0.cob) }
+                return cobMapped.max()
+            }.value
+
+            // Ensure the result exists or set default values
+            if let maxCob = maxCob {
+                let calculatedMax = maxCob == 0 ? 20 : maxCob + 20
+                await updateCobChartBounds(minValue: 0, maxValue: calculatedMax)
+            } else {
+                await updateCobChartBounds(minValue: 0, maxValue: 20)
+            }
         }
-        maxValueCobChart = maxCob == 0 ? 20 : maxCob +
-            20 // 2 is added to the max of iob and to keep the 1:10 ratio we add 20 here
+    }
+
+    @MainActor private func updateCobChartBounds(minValue: Decimal, maxValue: Decimal) async {
+        minValueCobChart = minValue
+        maxValueCobChart = maxValue
     }
 
     private func yAxisChartDataIobChart() {
-        let iobMapped = state.enactedAndNonEnactedDeterminations.compactMap { $0.iob?.decimalValue }
-        guard let minIob = iobMapped.min(), let maxIob = iobMapped.max() else {
-            // default values
-            minValueIobChart = 0
-            maxValueIobChart = 5
-            return
+        Task {
+            let (minIob, maxIob) = await Task.detached { () -> (Decimal?, Decimal?) in
+                let iobMapped = await state.enactedAndNonEnactedDeterminations.compactMap { $0.iob?.decimalValue }
+                return (iobMapped.min(), iobMapped.max())
+            }.value
+
+            // Ensure min and max IOB values exist, or set defaults
+            if let minIob = minIob, let maxIob = maxIob {
+                let adjustedMin = minIob < 0 ? minIob - 2 : 0
+                await updateIobChartBounds(minValue: adjustedMin, maxValue: maxIob + 2)
+            } else {
+                await updateIobChartBounds(minValue: 0, maxValue: 5)
+            }
         }
-        minValueIobChart = minIob // we need to set this here because IOB can also be negative
-        minValueCobChart = minIob < 0 ? minIob - 2 :
-            0 // if there is negative IOB the COB-X-Axis should still align with the IOB-X-Axis; 2 is only subtracted to make the charts align
-        maxValueIobChart = maxIob + 2
+    }
+
+    @MainActor private func updateIobChartBounds(minValue: Decimal, maxValue: Decimal) async {
+        minValueIobChart = minValue
+        maxValueIobChart = maxValue
     }
 
     private func basalChartPlotStyle(_ plotContent: ChartPlotContent) -> some View {