Browse Source

Merge 'Small-fixes' branch and revert not working iob chart fix

polscm32 aka Marvout 1 year ago
parent
commit
ca6b8b98d4

+ 0 - 31
FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift

@@ -86,37 +86,6 @@ final class OpenAPS {
 
         // First save the current Determination to Core Data
         await attemptToSaveContext()
-
-        // After that check for changes in iob and cob and if there are any post a custom Notification
-        /// this is currently used to update Live Activity so that it stays up to date and not one loop cycle behind
-        await checkForCobIobUpdate(determination)
-    }
-
-    func checkForCobIobUpdate(_ determination: Determination) async {
-        let results = await CoreDataStack.shared.fetchEntitiesAsync(
-            ofType: OrefDetermination.self,
-            onContext: context,
-            predicate: NSPredicate.predicateFor30MinAgoForDetermination,
-            key: "deliverAt",
-            ascending: false,
-            fetchLimit: 2
-        )
-
-        await context.perform {
-            guard let previousDeterminations = results as? [OrefDetermination] else {
-                return
-            }
-
-            // We need to get the second last Determination for this comparison because we have saved the current Determination already to Core Data
-            if let previousDetermination = previousDeterminations.dropFirst().first {
-                let iobChanged = previousDetermination.iob != self.decimalToNSDecimalNumber(determination.iob)
-                let cobChanged = previousDetermination.cob != Int16(Int(determination.cob ?? 0))
-
-                if iobChanged || cobChanged {
-                    Foundation.NotificationCenter.default.post(name: .didUpdateCobIob, object: nil)
-                }
-            }
-        }
     }
 
     func attemptToSaveContext() async {

+ 4 - 4
FreeAPS/Sources/Modules/Home/View/Chart/BasalChart.swift

@@ -25,17 +25,17 @@ extension MainChartView {
                 drawTempBasals(dummy: false)
                 drawBasalProfile()
                 drawSuspensions()
-            }.onChange(of: state.tempBasals) { _ in
+            }.onChange(of: state.tempBasals) {
                 calculateBasals()
                 calculateTempBasalsInBackground()
             }
-            .onChange(of: state.maxBasal) { _ in
+            .onChange(of: state.maxBasal) {
                 calculateBasals()
             }
-            .onChange(of: state.autotunedBasalProfile) { _ in
+            .onChange(of: state.autotunedBasalProfile) {
                 calculateBasals()
             }
-            .onChange(of: state.basalProfile) { _ in
+            .onChange(of: state.basalProfile) {
                 calculateBasals()
             }
             .frame(minHeight: geo.size.height * 0.05)

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

@@ -97,17 +97,17 @@ struct MainChartView: View {
                                 iobChart
                             }
 
-                        }.onChange(of: screenHours) { _ in
+                        }.onChange(of: screenHours) {
                             scroller.scrollTo("MainChart", anchor: .trailing)
                         }
-                        .onChange(of: state.glucoseFromPersistence.last?.glucose) { _ in
+                        .onChange(of: state.glucoseFromPersistence.last?.glucose) {
                             scroller.scrollTo("MainChart", anchor: .trailing)
                             updateStartEndMarkers()
                         }
-                        .onChange(of: state.enactedAndNonEnactedDeterminations.first?.deliverAt) { _ in
+                        .onChange(of: state.enactedAndNonEnactedDeterminations.first?.deliverAt) {
                             scroller.scrollTo("MainChart", anchor: .trailing)
                         }
-                        .onChange(of: units) { _ in
+                        .onChange(of: units) {
                             // TODO: - Refactor this to only update the Y Axis Scale
                             state.setupGlucoseArray()
                         }
@@ -218,10 +218,10 @@ extension MainChartView {
                 }
             }
             .id("MainChart")
-            .onChange(of: state.insulinFromPersistence) { _ in
+            .onChange(of: state.insulinFromPersistence) {
                 state.roundedTotalBolus = state.calculateTINS()
             }
-            .onChange(of: tempTargets) { _ in
+            .onChange(of: tempTargets) {
                 Task {
                     await calculateTempTargets()
                 }

+ 6 - 5
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -429,8 +429,9 @@ extension Home {
                         .foregroundColor(.loopYellow)
                     Text(
                         (
-                            numberFormatter
-                                .string(from: (state.enactedAndNonEnactedDeterminations.first?.cob ?? 0) as NSNumber) ?? "0"
+                            numberFormatter.string(
+                                from: NSNumber(value: state.enactedAndNonEnactedDeterminations.first?.cob ?? 0)
+                            ) ?? "0"
                         ) +
                             NSLocalizedString(" g", comment: "gram of carbs")
                     )
@@ -477,7 +478,7 @@ extension Home {
                                 NSLocalizedString(" U", comment: "Unit in number of units delivered (keep the space character!)")
                         )
                         .font(.system(size: 16, weight: .bold, design: .rounded))
-                        .onChange(of: state.hours) { _ in
+                        .onChange(of: state.hours) {
                             state.roundedTotalBolus = state.calculateTINS()
                         }
                         .onAppear {
@@ -719,7 +720,7 @@ extension Home {
                 }
                 .background(color)
             }
-            .onChange(of: state.hours) { _ in
+            .onChange(of: state.hours) {
                 highlightButtons()
             }
             .onAppear {
@@ -889,7 +890,7 @@ extension Home {
                     }
                 )
             }.ignoresSafeArea(.keyboard, edges: .bottom).blur(radius: state.waitForSuggestion ? 8 : 0)
-                .onChange(of: selectedTab) { _ in
+                .onChange(of: selectedTab) {
                     print("current path is empty: \(settingsPath.isEmpty)")
                     settingsPath = NavigationPath()
                 }

+ 32 - 59
FreeAPS/Sources/Services/HealthKit/HealthKitManager.swift

@@ -361,94 +361,67 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
             batchSize: 50
         )
 
-        // Initialize an array to hold the HealthKit samples to be uploaded
-        var insulinSamples: [HKQuantitySample] = []
-
         // Perform the data processing on the background context
         await backgroundContext.perform {
-            // Ensure that the fetched results are of the expected type
             guard let existingTempBasalEntries = results as? [PumpEventStored] else { return }
 
-            // Create a mapping from timestamps to indices for quick access to existing entries
-            let existingEntriesByTimestamp = Dictionary(
-                uniqueKeysWithValues: existingTempBasalEntries.enumerated()
-                    .map { ($0.element.timestamp, $0.offset) }
-            )
+            let insulinSamples: [HKQuantitySample] = insulin.reduce([]) { result, event in
+                var result = result
 
-            for event in insulin {
                 switch event.type {
                 case .bolus:
                     // For bolus events, create a HealthKit sample directly
                     if let sample = self.createSample(for: event, sampleType: sampleType) {
                         debug(.service, "Created HealthKit sample for bolus entry: \(sample)")
-                        insulinSamples.append(sample)
+                        result.append(sample)
                     }
 
                 case .tempBasal:
                     // For temp basal events, process them and adjust overlapping durations if necessary
-                    guard let duration = event.duration, let amount = event.amount else { continue }
+                    guard let duration = event.duration, let amount = event.amount else { return result }
 
-                    // Calculate the total insulin delivered during the temp basal period
                     let value = (Decimal(duration) / 60.0) * amount
                     let valueRounded = self.deviceDataManager?.pumpManager?
                         .roundToSupportedBolusVolume(units: Double(value)) ?? Double(value)
 
-                    // Check if there's a matching existing temp basal entry
-                    if let matchingEntryIndex = existingEntriesByTimestamp[event.timestamp] {
-                        let predecessorIndex = matchingEntryIndex - 1
-                        if predecessorIndex >= 0 {
-                            // Get the predecessor entry to handle overlapping temp basal events
-                            let predecessorEntry = existingTempBasalEntries[predecessorIndex]
-
-                            // Adjust the predecessor entry if it overlaps with the current event
-                            if let adjustedSample = self.processPredecessorEntry(
-                                predecessorEntry,
-                                nextEventTimestamp: event.timestamp,
-                                sampleType: sampleType
-                            ) {
-                                insulinSamples.append(adjustedSample)
-                            }
-                        }
-
-                        // Create a new PumpHistoryEvent with the calculated insulin value
-                        let newEvent = PumpHistoryEvent(
-                            id: event.id,
-                            type: .tempBasal,
-                            timestamp: event.timestamp,
-                            amount: Decimal(valueRounded),
-                            duration: event.duration
-                        )
-
-                        // Create a HealthKit sample for the current temp basal event
-                        if let sample = self.createSample(for: newEvent, sampleType: sampleType) {
-                            debug(.service, "Created HealthKit sample for initial temp basal entry: \(sample)")
-                            insulinSamples.append(sample)
-                        }
+                    // Process and append temp basal event
+                    let newEvent = PumpHistoryEvent(
+                        id: event.id,
+                        type: .tempBasal,
+                        timestamp: event.timestamp,
+                        amount: Decimal(valueRounded),
+                        duration: event.duration
+                    )
+
+                    if let sample = self.createSample(for: newEvent, sampleType: sampleType) {
+                        debug(.service, "Created HealthKit sample for temp basal entry: \(sample)")
+                        result.append(sample)
                     }
 
                 default:
-                    // Ignore other event types
                     break
                 }
+                return result
             }
-        }
 
-        // Save the processed insulin samples to HealthKit
-        do {
-            guard insulinSamples.isNotEmpty else {
-                debug(.service, "No insulin samples available for upload.")
-                return
-            }
+            // Save the processed insulin samples to HealthKit
+            Task {
+                do {
+                    guard insulinSamples.isNotEmpty else {
+                        debug(.service, "No insulin samples available for upload.")
+                        return
+                    }
 
-            // Attempt to save the samples to HealthKit
-            try await healthKitStore.save(insulinSamples)
-            debug(.service, "Successfully stored \(insulinSamples.count) insulin samples in HealthKit.")
+                    try await self.healthKitStore.save(insulinSamples)
+                    debug(.service, "Successfully stored \(insulinSamples.count) insulin samples in HealthKit.")
 
-            // Mark the insulin events as uploaded
-            await updateInsulinAsUploaded(insulin)
+                    // Mark the insulin events as uploaded
+                    await self.updateInsulinAsUploaded(insulin)
 
-        } catch {
-            debug(.service, "Failed to upload insulin samples to HealthKit: \(error.localizedDescription)")
+                } catch {
+                    debug(.service, "Failed to upload insulin samples to HealthKit: \(error.localizedDescription)")
+                }
+            }
         }
     }
 

+ 14 - 17
FreeAPS/Sources/Services/LiveActivity/LiveActivityBridge.swift

@@ -68,14 +68,17 @@ import UIKit
 
     private func setupNotifications() {
         let notificationCenter = Foundation.NotificationCenter.default
-        notificationCenter.addObserver(self, selector: #selector(cobOrIobDidUpdate), name: .didUpdateCobIob, object: nil)
         notificationCenter
             .addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: nil) { [weak self] _ in
-                self?.forceActivityUpdate()
+                Task { @MainActor in
+                    self?.forceActivityUpdate()
+                }
             }
         notificationCenter
             .addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: nil) { [weak self] _ in
-                self?.forceActivityUpdate()
+                Task { @MainActor in
+                    self?.forceActivityUpdate()
+                }
             }
     }
 
@@ -85,6 +88,11 @@ import UIKit
             guard let self = self else { return }
             self.overridesDidUpdate()
         }.store(in: &subscriptions)
+
+        coreDataPublisher?.filterByEntityName("OrefDetermination").sink { [weak self] _ in
+            guard let self = self else { return }
+            self.cobOrIobDidUpdate()
+        }.store(in: &subscriptions)
     }
 
     private func registerSubscribers() {
@@ -97,7 +105,7 @@ import UIKit
             .store(in: &subscriptions)
     }
 
-    @objc private func cobOrIobDidUpdate() {
+    private func cobOrIobDidUpdate() {
         Task {
             await fetchAndMapDetermination()
             if let determination = determination {
@@ -106,7 +114,7 @@ import UIKit
         }
     }
 
-    @objc private func overridesDidUpdate() {
+    private func overridesDidUpdate() {
         Task {
             await fetchAndMapOverride()
             if let determination = determination {
@@ -117,19 +125,8 @@ import UIKit
 
     private func setupGlucoseArray() {
         Task {
-            async let glucoseTask: () = fetchAndMapGlucose()
-            async let determinationTask: () = fetchAndMapDetermination()
-            async let overrideTask: () = fetchAndMapOverride()
-            
             // Fetch and map glucose to GlucoseData struct
-            await glucoseTask
-
-            // Fetch and map Determination to DeterminationData struct
-            await determinationTask
-
-            // Fetch and map Override to OverrideData struct
-            /// shows if there is an active Override
-            await overrideTask
+            await fetchAndMapGlucose()
 
             // Push the update to the Live Activity
             await glucoseDidUpdate(glucoseFromPersistence ?? [])

+ 6 - 2
FreeAPS/Sources/Views/TextFieldWithToolBar.swift

@@ -225,10 +225,14 @@ extension TextFieldWithToolBar.Coordinator: UITextFieldDelegate {
                 let hasTrailingZeros = (hasDecimalSeparator && proposedText[lastCharIndex] == "0") || isDecimalSeparator
                 if !hasTrailingZeros
                 {
-                    parent.text = number.decimalValue
+                    DispatchQueue.main.async {
+                        self.parent.text = number.decimalValue
+                    }
                 }
             } else {
-                parent.text = 0
+                DispatchQueue.main.async {
+                    self.parent.text = 0
+                }
             }
         }
 

+ 0 - 1
Model/Helper/CustomNotification.swift

@@ -4,7 +4,6 @@ import Foundation
 extension Notification.Name {
     static let willUpdateOverrideConfiguration = Notification.Name("willUpdateOverrideConfiguration")
     static let didUpdateOverrideConfiguration = Notification.Name("didUpdateOverrideConfiguration")
-    static let didUpdateCobIob = Notification.Name("didUpdateCobIob")
 }
 
 func awaitNotification(_ name: Notification.Name) async {