|
|
@@ -1,29 +1,23 @@
|
|
|
+import Combine
|
|
|
import CoreData
|
|
|
import Foundation
|
|
|
import SwiftDate
|
|
|
import Swinject
|
|
|
|
|
|
-protocol CarbsStoredDelegate: AnyObject {
|
|
|
- /*
|
|
|
- Informs the delegate that the Carbs Storage has updated Carbs
|
|
|
- */
|
|
|
- func carbsStorageHasUpdatedCarbs(_ carbsStorage: BaseCarbsStorage)
|
|
|
-}
|
|
|
-
|
|
|
protocol CarbsObserver {
|
|
|
func carbsDidUpdate(_ carbs: [CarbsEntry])
|
|
|
}
|
|
|
|
|
|
protocol CarbsStorage {
|
|
|
- var delegate: CarbsStoredDelegate? { get set }
|
|
|
+ var updatePublisher: AnyPublisher<Void, Never> { get }
|
|
|
func storeCarbs(_ carbs: [CarbsEntry], areFetchedFromRemote: Bool) async
|
|
|
+ func deleteCarbs(_ treatmentObjectID: NSManagedObjectID) async
|
|
|
func syncDate() -> Date
|
|
|
func recent() -> [CarbsEntry]
|
|
|
func getCarbsNotYetUploadedToNightscout() async -> [NightscoutTreatment]
|
|
|
func getFPUsNotYetUploadedToNightscout() async -> [NightscoutTreatment]
|
|
|
func deleteCarbs(at uniqueID: String, fpuID: String, complex: Bool)
|
|
|
func getCarbsNotYetUploadedToHealth() async -> [CarbsEntry]
|
|
|
- func deleteCarbs(_ treatmentObjectID: NSManagedObjectID) async
|
|
|
}
|
|
|
|
|
|
final class BaseCarbsStorage: CarbsStorage, Injectable {
|
|
|
@@ -34,7 +28,11 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
|
|
|
|
|
|
let coredataContext = CoreDataStack.shared.newTaskContext()
|
|
|
|
|
|
- public weak var delegate: CarbsStoredDelegate?
|
|
|
+ private let updateSubject = PassthroughSubject<Void, Never>()
|
|
|
+
|
|
|
+ var updatePublisher: AnyPublisher<Void, Never> {
|
|
|
+ updateSubject.eraseToAnyPublisher()
|
|
|
+ }
|
|
|
|
|
|
init(resolver: Resolver) {
|
|
|
injectServices(resolver)
|
|
|
@@ -50,10 +48,6 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
|
|
|
await saveCarbsToCoreData(entries: entriesToStore, areFetchedFromRemote: areFetchedFromRemote)
|
|
|
|
|
|
await saveCarbEquivalents(entries: entriesToStore, areFetchedFromRemote: areFetchedFromRemote)
|
|
|
-
|
|
|
- // TODO: - Should we really use a delegate here? If yes, should we also use this for NS/TP?
|
|
|
-
|
|
|
- delegate?.carbsStorageHasUpdatedCarbs(self)
|
|
|
}
|
|
|
|
|
|
private func filterRemoteEntries(entries: [CarbsEntry]) async -> [CarbsEntry] {
|
|
|
@@ -253,8 +247,8 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
|
|
|
try self.coredataContext.execute(batchInsert)
|
|
|
debugPrint("Carbs Storage: \(DebuggingIdentifiers.succeeded) saved fpus to core data")
|
|
|
|
|
|
- // Send notification for triggering a fetch in Home State Model to update the FPU Array
|
|
|
- Foundation.NotificationCenter.default.post(name: .didPerformBatchInsert, object: nil)
|
|
|
+ // Notify subscriber in Home State Model to update the FPU Array
|
|
|
+ self.updateSubject.send(())
|
|
|
} catch {
|
|
|
debugPrint("Carbs Storage: \(DebuggingIdentifiers.failed) error while saving fpus to core data")
|
|
|
}
|
|
|
@@ -269,36 +263,6 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
|
|
|
storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self)?.reversed() ?? []
|
|
|
}
|
|
|
|
|
|
- func deleteCarbs(at uniqueID: String, fpuID: String, complex: Bool) {
|
|
|
- processQueue.sync {
|
|
|
- var allValues = storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self) ?? []
|
|
|
-
|
|
|
- if fpuID != "" {
|
|
|
- if allValues.firstIndex(where: { $0.fpuID == fpuID }) == nil {
|
|
|
- debug(.default, "Didn't find any carb equivalents to delete. ID to search for: " + fpuID.description)
|
|
|
- } else {
|
|
|
- allValues.removeAll(where: { $0.fpuID == fpuID })
|
|
|
- storage.save(allValues, as: OpenAPS.Monitor.carbHistory)
|
|
|
- broadcaster.notify(CarbsObserver.self, on: processQueue) {
|
|
|
- $0.carbsDidUpdate(allValues)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if fpuID == "" || complex {
|
|
|
- if allValues.firstIndex(where: { $0.id == uniqueID }) == nil {
|
|
|
- debug(.default, "Didn't find any carb entries to delete. ID to search for: " + uniqueID.description)
|
|
|
- } else {
|
|
|
- allValues.removeAll(where: { $0.id == uniqueID })
|
|
|
- storage.save(allValues, as: OpenAPS.Monitor.carbHistory)
|
|
|
- broadcaster.notify(CarbsObserver.self, on: processQueue) {
|
|
|
- $0.carbsDidUpdate(allValues)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
func deleteCarbs(_ treatmentObjectID: NSManagedObjectID) async {
|
|
|
let taskContext = CoreDataStack.shared.newTaskContext()
|
|
|
taskContext.name = "deleteContext"
|
|
|
@@ -317,7 +281,7 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
|
|
|
if carbEntry.isFPU, let fpuID = carbEntry.fpuID {
|
|
|
// fetch request for all carb entries with the same id
|
|
|
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = CarbEntryStored.fetchRequest()
|
|
|
- fetchRequest.predicate = NSPredicate(format: "isFPU == true AND fpuID == %@", fpuID as CVarArg)
|
|
|
+ fetchRequest.predicate = NSPredicate(format: "fpuID == %@", fpuID as CVarArg)
|
|
|
|
|
|
// NSBatchDeleteRequest
|
|
|
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
|
|
|
@@ -327,7 +291,8 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
|
|
|
let result = try taskContext.execute(deleteRequest) as? NSBatchDeleteResult
|
|
|
debugPrint("\(DebuggingIdentifiers.succeeded) Deleted \(result?.result ?? 0) items with FpuID \(fpuID)")
|
|
|
|
|
|
- Foundation.NotificationCenter.default.post(name: .didPerformBatchDelete, object: nil)
|
|
|
+ // Notifiy subscribers of the batch delete
|
|
|
+ self.updateSubject.send(())
|
|
|
} else {
|
|
|
taskContext.delete(carbEntry)
|
|
|
|
|
|
@@ -345,6 +310,36 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ func deleteCarbs(at uniqueID: String, fpuID: String, complex: Bool) {
|
|
|
+ processQueue.sync {
|
|
|
+ var allValues = storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self) ?? []
|
|
|
+
|
|
|
+ if fpuID != "" {
|
|
|
+ if allValues.firstIndex(where: { $0.fpuID == fpuID }) == nil {
|
|
|
+ debug(.default, "Didn't find any carb equivalents to delete. ID to search for: " + fpuID.description)
|
|
|
+ } else {
|
|
|
+ allValues.removeAll(where: { $0.fpuID == fpuID })
|
|
|
+ storage.save(allValues, as: OpenAPS.Monitor.carbHistory)
|
|
|
+ broadcaster.notify(CarbsObserver.self, on: processQueue) {
|
|
|
+ $0.carbsDidUpdate(allValues)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if fpuID == "" || complex {
|
|
|
+ if allValues.firstIndex(where: { $0.id == uniqueID }) == nil {
|
|
|
+ debug(.default, "Didn't find any carb entries to delete. ID to search for: " + uniqueID.description)
|
|
|
+ } else {
|
|
|
+ allValues.removeAll(where: { $0.id == uniqueID })
|
|
|
+ storage.save(allValues, as: OpenAPS.Monitor.carbHistory)
|
|
|
+ broadcaster.notify(CarbsObserver.self, on: processQueue) {
|
|
|
+ $0.carbsDidUpdate(allValues)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
func getCarbsNotYetUploadedToNightscout() async -> [NightscoutTreatment] {
|
|
|
let results = await CoreDataStack.shared.fetchEntitiesAsync(
|
|
|
ofType: CarbEntryStored.self,
|