Ivan Valkou 4 лет назад
Родитель
Сommit
1d1ccc91af

+ 3 - 3
FreeAPS.xcodeproj/xcuserdata/i.valkou.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -33,17 +33,17 @@
 		<key>FreeAPSWatch (Complication).xcscheme_^#shared#^_</key>
 		<dict>
 			<key>orderHint</key>
-			<integer>18</integer>
+			<integer>11</integer>
 		</dict>
 		<key>FreeAPSWatch (Notification).xcscheme_^#shared#^_</key>
 		<dict>
 			<key>orderHint</key>
-			<integer>17</integer>
+			<integer>12</integer>
 		</dict>
 		<key>FreeAPSWatch.xcscheme_^#shared#^_</key>
 		<dict>
 			<key>orderHint</key>
-			<integer>16</integer>
+			<integer>8</integer>
 		</dict>
 		<key>ReactiveSwift (Playground) 1.xcscheme</key>
 		<dict>

+ 2 - 1
FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json

@@ -17,5 +17,6 @@
     "addSourceInfoToGlucoseNotifications": false,
     "lowGlucose": 72,
     "highGlucose": 270,
-    "carbsRequiredThreshold": 10
+    "carbsRequiredThreshold": 10,
+    "useAppleHealth": false
 }

+ 2 - 1
FreeAPS/Sources/APS/FetchGlucoseManager.swift

@@ -62,7 +62,8 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
                 return Publishers.CombineLatest3(
                     Just(date),
                     Just(self.glucoseStorage.syncDate()),
-                    self.glucoseSource.fetch()
+                    self.glucoseSource.fetch().merge(with: self.healthKitManager.fetch())
+                        .eraseToAnyPublisher()
                 )
                 .eraseToAnyPublisher()
             }

+ 4 - 4
FreeAPS/Sources/APS/Storage/GlucoseStorage.swift

@@ -54,8 +54,8 @@ final class BaseGlucoseStorage: GlucoseStorage, Injectable {
         processQueue.sync {
             let file = OpenAPS.Monitor.glucose
             self.storage.transaction { storage in
-                let BGInStorage = storage.retrieve(file, as: [BloodGlucose].self)
-                let filteredBG = BGInStorage?.filter { !ids.contains($0.id) } ?? []
+                let bgInStorage = storage.retrieve(file, as: [BloodGlucose].self)
+                let filteredBG = bgInStorage?.filter { !ids.contains($0.id) } ?? []
                 storage.save(filteredBG, as: file)
 
                 DispatchQueue.main.async {
@@ -71,8 +71,8 @@ final class BaseGlucoseStorage: GlucoseStorage, Injectable {
         processQueue.sync {
             let file = OpenAPS.Monitor.glucose
             self.storage.transaction { storage in
-                let BGInStorage = storage.retrieve(file, as: [BloodGlucose].self)
-                let filteredBG = BGInStorage?.filter { $0.id != id } ?? []
+                let bgInStorage = storage.retrieve(file, as: [BloodGlucose].self)
+                let filteredBG = bgInStorage?.filter { $0.id != id } ?? []
                 storage.save(filteredBG, as: file)
 
                 DispatchQueue.main.async {

+ 0 - 10
FreeAPS/Sources/Models/FreeAPSSettings.swift

@@ -14,10 +14,7 @@ struct FreeAPSSettings: JSON, Equatable {
     var cgm: CGMType = .nightscout
     var uploadGlucose: Bool = false
     var useCalendar: Bool = false
-    // Apple Health Integration
     var useAppleHealth: Bool = false
-    var needShowInformationTextForSetPermissions: Bool = false
-    // ---
     var glucoseBadge: Bool = false
     var glucoseNotificationsAlways: Bool = false
     var useAlarmSound: Bool = false
@@ -89,13 +86,6 @@ extension FreeAPSSettings: Decodable {
             settings.useAppleHealth = useAppleHealth
         }
 
-        if let needShowInformationTextForSetPermissions = try? container.decode(
-            Bool.self,
-            forKey: .needShowInformationTextForSetPermissions
-        ) {
-            settings.needShowInformationTextForSetPermissions = needShowInformationTextForSetPermissions
-        }
-
         if let glucoseBadge = try? container.decode(Bool.self, forKey: .glucoseBadge) {
             settings.glucoseBadge = glucoseBadge
         }

+ 18 - 22
FreeAPS/Sources/Modules/HealthKit/HealthKitStateModel.swift

@@ -10,35 +10,31 @@ extension AppleHealthKit {
 
         override func subscribe() {
             useAppleHealth = settingsManager.settings.useAppleHealth
-            needShowInformationTextForSetPermissions = settingsManager.settings.needShowInformationTextForSetPermissions
 
-            subscribeSetting(\.needShowInformationTextForSetPermissions, on: $needShowInformationTextForSetPermissions) { _ in }
+            needShowInformationTextForSetPermissions = healthKitManager.areAllowAllPermissions
 
-            $useAppleHealth
-                .removeDuplicates()
-                .sink { [weak self] value in
-                    guard let self = self else { return }
-                    guard value else {
-                        self.settingsManager.settings.useAppleHealth = false
-                        self.needShowInformationTextForSetPermissions = false
+            subscribeSetting(\.useAppleHealth, on: $useAppleHealth) {
+                useAppleHealth = $0
+            } didSet: { [weak self] value in
+                guard let self = self else { return }
+
+                guard value else {
+                    self.needShowInformationTextForSetPermissions = false
+                    return
+                }
+
+                self.healthKitManager.requestPermission { status, error in
+                    guard error == nil else {
                         return
                     }
 
-                    self.healthKitManager.requestPermission { status, error in
-                        guard error == nil else {
-                            return
-                        }
-                        self.settingsManager.settings.useAppleHealth = status
-                        self.healthKitManager.enableBackgroundDelivery()
-                        self.healthKitManager.createObserver()
-                        DispatchQueue.main.async {
-                            if !self.healthKitManager.areAllowAllPermissions {
-                                self.needShowInformationTextForSetPermissions = true
-                            }
-                        }
+                    self.healthKitManager.enableBackgroundDelivery()
+                    self.healthKitManager.createObserver()
+                    DispatchQueue.main.async {
+                        self.needShowInformationTextForSetPermissions = !self.healthKitManager.areAllowAllPermissions
                     }
                 }
-                .store(in: &lifetime)
+            }
         }
     }
 }

+ 36 - 21
FreeAPS/Sources/Services/HealthKit/HealthKitManager.swift

@@ -1,8 +1,9 @@
+import Combine
 import Foundation
 import HealthKit
 import Swinject
 
-protocol HealthKitManager {
+protocol HealthKitManager: GlucoseSource {
     /// Check availability HealthKit on current device and user's permissions
     var isAvailableOnCurrentDevice: Bool { get }
     /// Check all needed permissions
@@ -24,6 +25,7 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
     @Injected() private var fileStorage: FileStorage!
     @Injected() private var glucoseStorage: GlucoseStorage!
     @Injected() private var healthKitStore: HKHealthStore!
+    @Injected() private var settingsManager: SettingsManager!
 
     private enum Config {
         // unwraped HKObjects
@@ -42,6 +44,8 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
         static let frequencyBackgroundDeliveryBloodGlucoseFromHealth = HKUpdateFrequency(rawValue: 10)!
     }
 
+    private var newGlucose: [BloodGlucose] = []
+
     var isAvailableOnCurrentDevice: Bool {
         HKHealthStore.isHealthDataAvailable()
     }
@@ -98,6 +102,8 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
     }
 
     func save(bloodGlucoses: [BloodGlucose], completion: ((Result<Bool, Error>) -> Void)? = nil) {
+        guard settingsManager.settings.useAppleHealth else { return }
+
         for bgItem in bloodGlucoses {
             let bgQuantity = HKQuantity(
                 unit: .milligramsPerDeciliter,
@@ -128,6 +134,8 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
     }
 
     func createObserver() {
+        guard settingsManager.settings.useAppleHealth else { return }
+
         guard let bgType = Config.healthBGObject else {
             warning(
                 .service,
@@ -158,6 +166,8 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
     }
 
     func enableBackgroundDelivery() {
+        guard settingsManager.settings.useAppleHealth else { return }
+
         guard let bgType = Config.healthBGObject else {
             warning(
                 .service,
@@ -192,13 +202,8 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
             }
 
             DispatchQueue.global(qos: .utility).async {
-                var removingBGID = [String]()
-                samples.forEach {
-                    if let idString = $0.metadata?["HKMetadataKeySyncIdentifier"] as? String {
-                        removingBGID.append(idString)
-                    } else {
-                        removingBGID.append($0.uuid.uuidString)
-                    }
+                let removingBGID = samples.map {
+                    $0.metadata?["HKMetadataKeySyncIdentifier"] as? String ?? $0.uuid.uuidString
                 }
                 glucoseStorage.removeGlucose(byIDCollection: removingBGID)
             }
@@ -214,29 +219,29 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
             sortDescriptors: nil
         ) { [unowned self] _, results, _ in
 
-            guard let samples = results as? [HKQuantitySample] else {
+            guard let samples = results as? [HKQuantitySample], samples.isNotEmpty else {
                 return
             }
 
             let oldSamples: [HealthKitSample] = fileStorage
                 .retrieve(OpenAPS.HealthKit.downloadedGlucose, as: [HealthKitSample].self) ?? []
 
-            var newSamples = [HealthKitSample]()
-            for sample in samples {
-                if sample.wasUserEntered {
-                    newSamples.append(HealthKitSample(
+            let newSamples = samples
+                .compactMap { sample -> HealthKitSample? in
+                    let fromFAX = sample.metadata?["fromFreeAPSX"] as? Bool ?? false
+                    guard !fromFAX else { return nil }
+                    return HealthKitSample(
                         healthKitId: sample.uuid.uuidString,
                         date: sample.startDate,
                         glucose: Int(round(sample.quantity.doubleValue(for: .milligramsPerDeciliter)))
-                    ))
+                    )
                 }
-            }
-
-            newSamples = newSamples
                 .filter { !oldSamples.contains($0) }
 
-            newSamples.forEach({ sample in
-                let glucose = BloodGlucose(
+            guard newSamples.isNotEmpty else { return }
+
+            let newGlucose = newSamples.map { sample in
+                BloodGlucose(
                     _id: sample.healthKitId,
                     sgv: sample.glucose,
                     direction: nil,
@@ -248,8 +253,9 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
                     glucose: sample.glucose,
                     type: "sgv"
                 )
-                glucoseStorage.storeGlucose([glucose])
-            })
+            }
+
+            self.newGlucose = newGlucose
 
             let savingSamples = (newSamples + oldSamples)
                 .removeDublicates()
@@ -259,6 +265,15 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
         }
         return query
     }
+
+    func fetch() -> AnyPublisher<[BloodGlucose], Never> {
+        guard settingsManager.settings.useAppleHealth else { return Just([]).eraseToAnyPublisher() }
+
+        let copy = newGlucose
+        newGlucose = []
+
+        return Just(copy).eraseToAnyPublisher()
+    }
 }
 
 enum HealthKitPermissionRequestStatus {

+ 1 - 1
FreeAPS/Sources/Services/UserNotifiactions/UserNotificationsManager.swift

@@ -240,7 +240,7 @@ final class BaseUserNotificationsManager: NSObject, UserNotificationsManager, In
                     "\n"
                         + String(
                             format: NSLocalizedString("Transmitter: %@%%", comment: "Transmitter: %@%%"),
-                            transmitterBattery
+                            "\(transmitterBattery)"
                         )
                 )
             }