diff --git a/Common/Extensions/GlucoseRangeSchedule.swift b/Common/Extensions/GlucoseRangeSchedule.swift index 9b092d6ad3..a7bfef414f 100644 --- a/Common/Extensions/GlucoseRangeSchedule.swift +++ b/Common/Extensions/GlucoseRangeSchedule.swift @@ -6,14 +6,14 @@ // import LoopKit -import HealthKit +import LoopAlgorithm extension GlucoseRangeSchedule { - func minQuantity(at date: Date) -> HKQuantity { - return HKQuantity(unit: unit, doubleValue: value(at: date).minValue) + func minQuantity(at date: Date) -> LoopQuantity { + return LoopQuantity(unit: unit, doubleValue: value(at: date).minValue) } - func maxQuantity(at date: Date) -> HKQuantity { - return HKQuantity(unit: unit, doubleValue: value(at: date).maxValue) + func maxQuantity(at date: Date) -> LoopQuantity { + return LoopQuantity(unit: unit, doubleValue: value(at: date).maxValue) } } diff --git a/Common/Extensions/HKUnit.swift b/Common/Extensions/HKUnit.swift index 36f7576d80..69cf8fb40c 100644 --- a/Common/Extensions/HKUnit.swift +++ b/Common/Extensions/HKUnit.swift @@ -6,13 +6,13 @@ // Copyright © 2016 LoopKit Authors. All rights reserved. // -import HealthKit +import LoopAlgorithm import LoopCore // Code in this extension is duplicated from: // https://github.com/LoopKit/LoopKit/blob/master/LoopKit/HKUnit.swift // to avoid pulling in the LoopKit extension since it's not extension-API safe. -extension HKUnit { +extension LoopUnit { // A formatting helper for determining the preferred decimal style for a given unit var preferredFractionDigits: Int { if self == .milligramsPerDeciliter { @@ -22,20 +22,6 @@ extension HKUnit { } } - var localizedShortUnitString: String { - if self == HKUnit.millimolesPerLiter { - return NSLocalizedString("mmol/L", comment: "The short unit display string for millimoles of glucose per liter") - } else if self == .milligramsPerDeciliter { - return NSLocalizedString("mg/dL", comment: "The short unit display string for milligrams of glucose per decilter") - } else if self == .internationalUnit() { - return NSLocalizedString("U", comment: "The short unit display string for international units of insulin") - } else if self == .gram() { - return NSLocalizedString("g", comment: "The short unit display string for grams") - } else { - return String(describing: self) - } - } - /// The smallest value expected to be visible on a chart var chartableIncrement: Double { if self == .milligramsPerDeciliter { diff --git a/Common/Extensions/NumberFormatter.swift b/Common/Extensions/NumberFormatter.swift index 51f411ae7d..c0f8c3addb 100644 --- a/Common/Extensions/NumberFormatter.swift +++ b/Common/Extensions/NumberFormatter.swift @@ -7,11 +7,11 @@ // import Foundation -import HealthKit +import LoopAlgorithm extension NumberFormatter { - static func glucoseFormatter(for unit: HKUnit) -> NumberFormatter { + static func glucoseFormatter(for unit: LoopUnit) -> NumberFormatter { let numberFormatter = NumberFormatter() numberFormatter.numberStyle = .decimal @@ -24,11 +24,11 @@ extension NumberFormatter { return string(from: NSNumber(value: number)) } - func string(from quantity: HKQuantity, unit: HKUnit) -> String? { + func string(from quantity: LoopQuantity, unit: LoopUnit) -> String? { return string(from: quantity.doubleValue(for: unit), unit: unit) } - func string(from number: Double, unit: HKUnit) -> String? { + func string(from number: Double, unit: LoopUnit) -> String? { return string(from: number, unit: unit.localizedShortUnitString) } diff --git a/Common/Extensions/SampleValue.swift b/Common/Extensions/SampleValue.swift index dd9c901ecf..b85fec0145 100644 --- a/Common/Extensions/SampleValue.swift +++ b/Common/Extensions/SampleValue.swift @@ -5,15 +5,14 @@ // Copyright © 2018 LoopKit Authors. All rights reserved. // -import HealthKit import LoopKit import LoopAlgorithm extension Collection where Element == SampleValue { /// O(n) - var quantityRange: ClosedRange? { - var lowest: HKQuantity? - var highest: HKQuantity? + var quantityRange: ClosedRange? { + var lowest: LoopQuantity? + var highest: LoopQuantity? for sample in self { if let l = lowest { diff --git a/Common/Models/StatusExtensionContext.swift b/Common/Models/StatusExtensionContext.swift index cf486fd1a8..114f2a416f 100644 --- a/Common/Models/StatusExtensionContext.swift +++ b/Common/Models/StatusExtensionContext.swift @@ -8,7 +8,7 @@ // This class allows Loop to pass context data to the Loop Status Extension. import Foundation -import HealthKit +import LoopAlgorithm import LoopKit import LoopKitUI import LoopAlgorithm @@ -25,24 +25,24 @@ struct GlucoseDisplayableContext: GlucoseDisplayable { let isStateValid: Bool let stateDescription: String let trendType: GlucoseTrend? - let trendRate: HKQuantity? + let trendRate: LoopQuantity? let isLocal: Bool let glucoseRangeCategory: GlucoseRangeCategory? } struct GlucoseContext: GlucoseValue { let value: Double - let unit: HKUnit + let unit: LoopUnit let startDate: Date - var quantity: HKQuantity { - return HKQuantity(unit: unit, doubleValue: value) + var quantity: LoopQuantity { + return LoopQuantity(unit: unit, doubleValue: value) } } struct PredictedGlucoseContext { let values: [Double] - let unit: HKUnit + let unit: LoopUnit let startDate: Date let interval: TimeInterval @@ -162,7 +162,7 @@ extension GlucoseDisplayableContext: RawRepresentable { } if let trendRateValue = rawValue["trendRateValue"] as? Double { - trendRate = HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: trendRateValue) + trendRate = LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: trendRateValue) } else { trendRate = nil } @@ -182,7 +182,7 @@ extension GlucoseDisplayableContext: RawRepresentable { ] raw["trendType"] = trendType?.rawValue if let trendRate = trendRate { - raw["trendRateValue"] = trendRate.doubleValue(for: HKUnit.milligramsPerDeciliterPerMinute) + raw["trendRateValue"] = trendRate.doubleValue(for: LoopUnit.milligramsPerDeciliterPerMinute) } raw["glucoseRangeCategory"] = glucoseRangeCategory?.rawValue @@ -204,7 +204,7 @@ extension PredictedGlucoseContext: RawRepresentable { } self.values = values - self.unit = HKUnit(from: unitString) + self.unit = LoopUnit(from: unitString) self.startDate = startDate self.interval = interval } diff --git a/Common/Models/WatchContext.swift b/Common/Models/WatchContext.swift index 6d4e7a23a0..c35694390e 100644 --- a/Common/Models/WatchContext.swift +++ b/Common/Models/WatchContext.swift @@ -7,7 +7,6 @@ // import Foundation -import HealthKit import LoopKit import LoopAlgorithm @@ -19,19 +18,19 @@ final class WatchContext: RawRepresentable { var creationDate = Date() - var displayGlucoseUnit: HKUnit? + var displayGlucoseUnit: LoopUnit? - var glucose: HKQuantity? + var glucose: LoopQuantity? var glucoseCondition: GlucoseCondition? var glucoseTrend: GlucoseTrend? - var glucoseTrendRate: HKQuantity? + var glucoseTrendRate: LoopQuantity? var glucoseDate: Date? var glucoseIsDisplayOnly: Bool? var glucoseWasUserEntered: Bool? var glucoseSyncIdentifier: String? var predictedGlucose: WatchPredictedGlucose? - var eventualGlucose: HKQuantity? { + var eventualGlucose: LoopQuantity? { return predictedGlucose?.values.last?.quantity } @@ -63,11 +62,11 @@ final class WatchContext: RawRepresentable { isClosedLoop = rawValue["cl"] as? Bool if let unitString = rawValue["gu"] as? String { - displayGlucoseUnit = HKUnit(from: unitString) + displayGlucoseUnit = LoopUnit(from: unitString) } let unit = displayGlucoseUnit ?? .milligramsPerDeciliter if let glucoseValue = rawValue["gv"] as? Double { - glucose = HKQuantity(unit: unit, doubleValue: glucoseValue) + glucose = LoopQuantity(unit: unit, doubleValue: glucoseValue) } if let rawGlucoseCondition = rawValue["gc"] as? GlucoseCondition.RawValue { @@ -77,7 +76,7 @@ final class WatchContext: RawRepresentable { glucoseTrend = GlucoseTrend(rawValue: rawGlucoseTrend) } if let glucoseTrendRateValue = rawValue["gtrv"] as? Double { - glucoseTrendRate = HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: glucoseTrendRateValue) + glucoseTrendRate = LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: glucoseTrendRateValue) } glucoseDate = rawValue["gd"] as? Date glucoseIsDisplayOnly = rawValue["gdo"] as? Bool @@ -126,7 +125,7 @@ final class WatchContext: RawRepresentable { raw["gc"] = glucoseCondition?.rawValue raw["gt"] = glucoseTrend?.rawValue if let glucoseTrendRate = glucoseTrendRate { - let unitPerMinute = unit.unitDivided(by: .minute()) + let unitPerMinute = unit.glucose(per: .minutes) raw["gtru"] = unitPerMinute.unitString raw["gtrv"] = glucoseTrendRate.doubleValue(for: unitPerMinute) } diff --git a/Common/Models/WatchHistoricalGlucose.swift b/Common/Models/WatchHistoricalGlucose.swift index 3b166170a9..71209d428d 100644 --- a/Common/Models/WatchHistoricalGlucose.swift +++ b/Common/Models/WatchHistoricalGlucose.swift @@ -73,10 +73,10 @@ extension WatchHistoricalGlucose: RawRepresentable { syncIdentifier: syncIdentifiers[$0], syncVersion: syncVersions[$0], startDate: startDates[$0], - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: quantities[$0]), + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: quantities[$0]), condition: conditions[$0], trend: trends[$0], - trendRate: trendRates[$0].flatMap { HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: $0) }, + trendRate: trendRates[$0].flatMap { LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: $0) }, isDisplayOnly: isDisplayOnlys[$0], wasUserEntered: wasUserEntereds[$0], device: devices[$0].flatMap { try? HKDevice(from: $0) }, diff --git a/Common/Models/WatchPredictedGlucose.swift b/Common/Models/WatchPredictedGlucose.swift index d5978eb6ed..d697418e43 100644 --- a/Common/Models/WatchPredictedGlucose.swift +++ b/Common/Models/WatchPredictedGlucose.swift @@ -8,7 +8,6 @@ import Foundation import LoopKit -import HealthKit import LoopAlgorithm @@ -47,7 +46,7 @@ extension WatchPredictedGlucose: RawRepresentable { self.values = values.enumerated().map { tuple in PredictedGlucoseValue(startDate: firstDate + Double(tuple.0) * interval, - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: Double(tuple.1))) + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: Double(tuple.1))) } } } diff --git a/Learn/Configuration/QuantityRangeEntry.swift b/Learn/Configuration/QuantityRangeEntry.swift index abb7ac344e..a549730af9 100644 --- a/Learn/Configuration/QuantityRangeEntry.swift +++ b/Learn/Configuration/QuantityRangeEntry.swift @@ -5,7 +5,6 @@ // Copyright © 2019 LoopKit Authors. All rights reserved. // -import HealthKit import LoopKit import UIKit diff --git a/Learn/Lessons/ModalDayLesson.swift b/Learn/Lessons/ModalDayLesson.swift index 612e55e41a..0b40c283d0 100644 --- a/Learn/Lessons/ModalDayLesson.swift +++ b/Learn/Lessons/ModalDayLesson.swift @@ -6,7 +6,6 @@ // import Foundation -import HealthKit import LoopCore import LoopKit import os.log diff --git a/Learn/Lessons/TimeInRangeLesson.swift b/Learn/Lessons/TimeInRangeLesson.swift index f01b3967cb..6f02fb8720 100644 --- a/Learn/Lessons/TimeInRangeLesson.swift +++ b/Learn/Lessons/TimeInRangeLesson.swift @@ -10,7 +10,6 @@ import LoopCore import LoopKit import LoopKitUI import LoopUI -import HealthKit import os.log diff --git a/Learn/Managers/DataManager.swift b/Learn/Managers/DataManager.swift index 3929c42bac..15e3220f1b 100644 --- a/Learn/Managers/DataManager.swift +++ b/Learn/Managers/DataManager.swift @@ -6,7 +6,6 @@ // import Foundation -import HealthKit import LoopKit import LoopCore diff --git a/Loop Widget Extension/Components/GlucoseView.swift b/Loop Widget Extension/Components/GlucoseView.swift index 332d4afee4..b865ce0e02 100644 --- a/Loop Widget Extension/Components/GlucoseView.swift +++ b/Loop Widget Extension/Components/GlucoseView.swift @@ -8,7 +8,6 @@ import SwiftUI import LoopKit -import HealthKit import LoopCore struct GlucoseView: View { diff --git a/Loop Widget Extension/Timeline/StatusWidgetTimelimeEntry.swift b/Loop Widget Extension/Timeline/StatusWidgetTimelimeEntry.swift index 78cec95b08..4fe09ba12f 100644 --- a/Loop Widget Extension/Timeline/StatusWidgetTimelimeEntry.swift +++ b/Loop Widget Extension/Timeline/StatusWidgetTimelimeEntry.swift @@ -6,7 +6,6 @@ // Copyright © 2023 LoopKit Authors. All rights reserved. // -import HealthKit import LoopCore import LoopKit import WidgetKit @@ -25,8 +24,8 @@ struct StatusWidgetTimelimeEntry: TimelineEntry { let currentGlucose: GlucoseValue? let glucoseFetchedAt: Date? - let delta: HKQuantity? - let unit: HKUnit? + let delta: LoopQuantity? + let unit: LoopUnit? let sensor: GlucoseDisplayableContext? let pumpHighlight: DeviceStatusHighlightContext? diff --git a/Loop Widget Extension/Timeline/StatusWidgetTimelineProvider.swift b/Loop Widget Extension/Timeline/StatusWidgetTimelineProvider.swift index b48bb1f7bf..04939d6761 100644 --- a/Loop Widget Extension/Timeline/StatusWidgetTimelineProvider.swift +++ b/Loop Widget Extension/Timeline/StatusWidgetTimelineProvider.swift @@ -112,14 +112,15 @@ class StatusWidgetTimelineProvider: TimelineProvider { let finalGlucose = glucose - guard let defaults = self.defaults, + guard let hkUnit = await healthStore.cachedPreferredUnits(for: .bloodGlucose), + let defaults = self.defaults, let context = defaults.statusExtensionContext, - let contextUpdatedAt = context.createdAt, - let unit = await healthStore.cachedPreferredUnits(for: .bloodGlucose) + let contextUpdatedAt = context.createdAt else { return } + let unit = LoopUnit(from: hkUnit) let lastCompleted = context.lastLoopCompleted let closeLoop = context.isClosedLoop ?? false @@ -137,7 +138,7 @@ class StatusWidgetTimelineProvider: TimelineProvider { previousGlucose = finalGlucose[finalGlucose.count - 2] } - var delta: HKQuantity? + var delta: LoopQuantity? // Making sure that previous glucose is within 6 mins of last glucose to avoid large deltas on sensor changes, missed readings, etc. if let prevGlucose = previousGlucose, @@ -145,7 +146,7 @@ class StatusWidgetTimelineProvider: TimelineProvider { currGlucose.startDate.timeIntervalSince(prevGlucose.startDate).minutes < 6 { let deltaMGDL = currGlucose.quantity.doubleValue(for: .milligramsPerDeciliter) - prevGlucose.quantity.doubleValue(for: .milligramsPerDeciliter) - delta = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: deltaMGDL) + delta = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: deltaMGDL) } let predictedGlucose = context.predictedGlucose?.samples diff --git a/Loop/Extensions/CarbStore+SimulatedCoreData.swift b/Loop/Extensions/CarbStore+SimulatedCoreData.swift index 3ddcc23c83..81530e1233 100644 --- a/Loop/Extensions/CarbStore+SimulatedCoreData.swift +++ b/Loop/Extensions/CarbStore+SimulatedCoreData.swift @@ -7,7 +7,7 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit // MARK: - Simulated Core Data @@ -63,7 +63,7 @@ extension CarbStore { fileprivate extension NewCarbEntry { static func simulated(startDate: Date, grams: Double, absorptionTime: TimeInterval) -> NewCarbEntry { return NewCarbEntry(date: startDate, - quantity: HKQuantity(unit: .gram(), doubleValue: grams), + quantity: LoopQuantity(unit: .gram, doubleValue: grams), startDate: startDate, foodType: "Simulated", absorptionTime: absorptionTime) diff --git a/Loop/Extensions/DoseStore+SimulatedCoreData.swift b/Loop/Extensions/DoseStore+SimulatedCoreData.swift index 066e1306a0..7f95ea82ba 100644 --- a/Loop/Extensions/DoseStore+SimulatedCoreData.swift +++ b/Loop/Extensions/DoseStore+SimulatedCoreData.swift @@ -7,7 +7,7 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit // MARK: - Simulated Core Data @@ -144,7 +144,7 @@ fileprivate extension PersistedPumpEvent { value: rate, unit: .unitsPerHour, deliveredUnits: rate * duration / .hours(1), - scheduledBasalRate: HKQuantity(unit: .internationalUnitsPerHour, doubleValue: scheduledRate))) + scheduledBasalRate: LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: scheduledRate))) } private static func simulated(date: Date, type: PumpEventType, alarmType: PumpAlarmType? = nil) -> PersistedPumpEvent { diff --git a/Loop/Extensions/DosingDecisionStore+SimulatedCoreData.swift b/Loop/Extensions/DosingDecisionStore+SimulatedCoreData.swift index ae4b0c05bc..e4a007d4a6 100644 --- a/Loop/Extensions/DosingDecisionStore+SimulatedCoreData.swift +++ b/Loop/Extensions/DosingDecisionStore+SimulatedCoreData.swift @@ -102,10 +102,10 @@ fileprivate extension StoredDosingDecision { var historicalGlucose = [HistoricalGlucoseValue]() for minutes in stride(from: -120.0, to: 0.0, by: 5.0) { historicalGlucose.append(HistoricalGlucoseValue(startDate: date.addingTimeInterval(.minutes(minutes)), - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 125 + minutes / 5))) + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 125 + minutes / 5))) } let originalCarbEntry = StoredCarbEntry(startDate: date.addingTimeInterval(-.minutes(15)), - quantity: HKQuantity(unit: .gram(), doubleValue: 15), + quantity: LoopQuantity(unit: .gram, doubleValue: 15), uuid: UUID(uuidString: "C86DEB61-68E9-464E-9DD5-96A9CB445FD3")!, provenanceIdentifier: Bundle.main.bundleIdentifier!, syncIdentifier: "2B03D96C-6F5D-4140-99CD-80C3E64D6010", @@ -116,7 +116,7 @@ fileprivate extension StoredDosingDecision { userCreatedDate: date.addingTimeInterval(-.minutes(15)), userUpdatedDate: date.addingTimeInterval(-.minutes(1))) let carbEntry = StoredCarbEntry(startDate: date.addingTimeInterval(-.minutes(1)), - quantity: HKQuantity(unit: .gram(), doubleValue: 25), + quantity: LoopQuantity(unit: .gram, doubleValue: 25), uuid: UUID(uuidString: "71B699D7-0E8F-4B13-B7A1-E7751EB78E74")!, provenanceIdentifier: Bundle.main.bundleIdentifier!, syncIdentifier: "2B03D96C-6F5D-4140-99CD-80C3E64D6010", @@ -131,10 +131,10 @@ fileprivate extension StoredDosingDecision { syncIdentifier: "2A67A303-1234-4CB8-8263-79498265368E", syncVersion: 1, startDate: date.addingTimeInterval(-.minutes(1)), - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 123.45), + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 123.45), condition: nil, trend: .up, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: 3.4), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: 3.4), isDisplayOnly: false, wasUserEntered: true, device: HKDevice(name: "Device Name", @@ -163,14 +163,14 @@ fileprivate extension StoredDosingDecision { var predictedGlucose = [PredictedGlucoseValue]() for minutes in stride(from: 5.0, to: 360.0, by: 5.0) { predictedGlucose.append(PredictedGlucoseValue(startDate: date.addingTimeInterval(.minutes(minutes)), - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 125 + minutes / 5))) + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 125 + minutes / 5))) } let automaticDoseRecommendation = AutomaticDoseRecommendation(basalAdjustment: TempBasalRecommendation(unitsPerHour: 0.75, duration: .minutes(30)), bolusUnits: 1.25) let manualBolusRecommendation = ManualBolusRecommendationWithDate(recommendation: ManualBolusRecommendation(amount: 0.2, notice: .predictedGlucoseBelowTarget(minGlucose: SimpleGlucoseValue(startDate: date.addingTimeInterval(.minutes(30)), - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 95.0)))), + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 95.0)))), date: date.addingTimeInterval(-.minutes(1))) let manualBolusRequested = 0.5 let warnings: [Issue] = [Issue(id: "one"), diff --git a/Loop/Extensions/GlucoseStore+SimulatedCoreData.swift b/Loop/Extensions/GlucoseStore+SimulatedCoreData.swift index e30a548a4a..4e27c520b0 100644 --- a/Loop/Extensions/GlucoseStore+SimulatedCoreData.swift +++ b/Loop/Extensions/GlucoseStore+SimulatedCoreData.swift @@ -7,7 +7,7 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit // MARK: - Simulated Core Data @@ -52,9 +52,9 @@ extension GlucoseStore { } }() simulated.append(NewGlucoseSample.simulated(date: startDate, - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: new), + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: new), trend: trend, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: trendRateValue))) + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: trendRateValue))) if simulated.count >= simulatedLimit { if let error = addSimulatedHistoricalGlucoseObjects(samples: simulated) { @@ -88,7 +88,7 @@ extension GlucoseStore { } fileprivate extension NewGlucoseSample { - static func simulated(date: Date, quantity: HKQuantity, trend: GlucoseTrend?, trendRate: HKQuantity?) -> NewGlucoseSample { + static func simulated(date: Date, quantity: LoopQuantity, trend: GlucoseTrend?, trendRate: LoopQuantity?) -> NewGlucoseSample { return NewGlucoseSample(date: date, quantity: quantity, condition: nil, diff --git a/Loop/Extensions/SettingsStore+SimulatedCoreData.swift b/Loop/Extensions/SettingsStore+SimulatedCoreData.swift index e633401d0d..06633e1ddd 100644 --- a/Loop/Extensions/SettingsStore+SimulatedCoreData.swift +++ b/Loop/Extensions/SettingsStore+SimulatedCoreData.swift @@ -103,7 +103,7 @@ fileprivate extension StoredSettings { RepeatingScheduleValue(startTime: .hours(18), value: 45.0), RepeatingScheduleValue(startTime: .hours(21), value: 50.0)], timeZone: scheduleTimeZone) - let carbRatioSchedule = CarbRatioSchedule(unit: .gram(), + let carbRatioSchedule = CarbRatioSchedule(unit: .gram, dailyItems: [RepeatingScheduleValue(startTime: .hours(0), value: 10.0), RepeatingScheduleValue(startTime: .hours(8), value: 12.0), RepeatingScheduleValue(startTime: .hours(10), value: 9.0), diff --git a/Loop/Managers/AnalyticsServicesManager.swift b/Loop/Managers/AnalyticsServicesManager.swift index 8528318d6c..16e4eab670 100644 --- a/Loop/Managers/AnalyticsServicesManager.swift +++ b/Loop/Managers/AnalyticsServicesManager.swift @@ -9,7 +9,7 @@ import Foundation import LoopKit import LoopCore -import HealthKit +import LoopAlgorithm final class AnalyticsServicesManager { @@ -202,7 +202,7 @@ final class AnalyticsServicesManager { logEvent("Alert Issued", withProperties: ["identifier": identifier, "interruptionLevel": interruptionLevel.rawValue]) } - func didEnactOverride(name: String, symbol: String, duration: TemporaryScheduleOverride.Duration, insulinSensitivityMultiplier: Double = 1.0, targetRange: ClosedRange? = nil) + func didEnactOverride(name: String, symbol: String, duration: TemporaryScheduleOverride.Duration, insulinSensitivityMultiplier: Double = 1.0, targetRange: ClosedRange? = nil) { let combinedName = "\(symbol) - \(name)" @@ -213,10 +213,10 @@ final class AnalyticsServicesManager { "nameWithEmoji": combinedName ] - if let targetUpperBound = targetRange?.upperBound.doubleValue(for: HKUnit.milligramsPerDeciliter) { + if let targetUpperBound = targetRange?.upperBound.doubleValue(for: LoopUnit.milligramsPerDeciliter) { properties["targetUpperBound"] = targetUpperBound } - if let targetLowerBound = targetRange?.lowerBound.doubleValue(for: HKUnit.milligramsPerDeciliter) { + if let targetLowerBound = targetRange?.lowerBound.doubleValue(for: LoopUnit.milligramsPerDeciliter) { properties["targetLowerBound"] = targetLowerBound } diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 7d29b8f742..9ac0d5fdc5 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -763,9 +763,9 @@ extension DeviceDataManager { guard FeatureFlags.cgmManagerCategorizeManualGlucoseRangeEnabled else { // Using Dexcom default glucose thresholds to categorize a glucose range - let urgentLowGlucoseThreshold = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 55) - let lowGlucoseThreshold = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 80) - let highGlucoseThreshold = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 200) + let urgentLowGlucoseThreshold = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 55) + let lowGlucoseThreshold = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 80) + let highGlucoseThreshold = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 200) let glucoseRangeCategory: GlucoseRangeCategory switch glucose.quantity { diff --git a/Loop/Managers/ExtensionDataManager.swift b/Loop/Managers/ExtensionDataManager.swift index 37e1a21ed6..366cc5eb30 100644 --- a/Loop/Managers/ExtensionDataManager.swift +++ b/Loop/Managers/ExtensionDataManager.swift @@ -6,7 +6,7 @@ // Copyright © 2016 Nathan Racklyeft. All rights reserved. // -import HealthKit +import LoopAlgorithm import UIKit import LoopKit @@ -87,7 +87,7 @@ final class ExtensionDataManager { return info } - private func createStatusContext(glucoseUnit: HKUnit) async -> StatusExtensionContext? { + private func createStatusContext(glucoseUnit: LoopUnit) async -> StatusExtensionContext? { let basalDeliveryState = deviceManager.pumpManager?.status.basalDeliveryState @@ -112,7 +112,7 @@ final class ExtensionDataManager { ) context.predictedGlucose = PredictedGlucoseContext( values: (1...36).map { 89.123 + Double($0 * 5) }, // 3 hours of linear data - unit: HKUnit.milligramsPerDeciliter, + unit: LoopUnit.milligramsPerDeciliter, startDate: Date(), interval: TimeInterval(minutes: 5)) #endif diff --git a/Loop/Managers/LoopAppManager.swift b/Loop/Managers/LoopAppManager.swift index 935726187a..c83414ef54 100644 --- a/Loop/Managers/LoopAppManager.swift +++ b/Loop/Managers/LoopAppManager.swift @@ -298,7 +298,8 @@ class LoopAppManager: NSObject { } Task { @MainActor in - if let unit = await self.healthStore.cachedPreferredUnits(for: .bloodGlucose) { + if let hkUnit = await self.healthStore.cachedPreferredUnits(for: .bloodGlucose) { + let unit = LoopUnit(from: hkUnit) self.displayGlucosePreference.unitDidChange(to: unit) self.notifyObserversOfDisplayGlucoseUnitChange(to: unit) } @@ -764,7 +765,7 @@ extension LoopAppManager: AlertPresenter { protocol DisplayGlucoseUnitBroadcaster: AnyObject { func addDisplayGlucoseUnitObserver(_ observer: DisplayGlucoseUnitObserver) func removeDisplayGlucoseUnitObserver(_ observer: DisplayGlucoseUnitObserver) - func notifyObserversOfDisplayGlucoseUnitChange(to displayGlucoseUnit: HKUnit) + func notifyObserversOfDisplayGlucoseUnitChange(to displayGlucoseUnit: LoopUnit) } extension LoopAppManager: DisplayGlucoseUnitBroadcaster { @@ -781,7 +782,7 @@ extension LoopAppManager: DisplayGlucoseUnitBroadcaster { displayGlucoseUnitObservers.cleanupDeallocatedElements() } - func notifyObserversOfDisplayGlucoseUnitChange(to displayGlucoseUnit: HKUnit) { + func notifyObserversOfDisplayGlucoseUnitChange(to displayGlucoseUnit: LoopUnit) { self.displayGlucoseUnitObservers.forEach { $0.unitDidChange(to: displayGlucoseUnit) } @@ -852,7 +853,7 @@ extension LoopAppManager: UNUserNotificationCenterDelegate { let mealTime = userInfo[LoopNotificationUserInfoKey.missedMealTime.rawValue] as? Date, let carbAmount = userInfo[LoopNotificationUserInfoKey.missedMealCarbAmount.rawValue] as? Double { - let missedEntry = NewCarbEntry(quantity: HKQuantity(unit: .gram(), + let missedEntry = NewCarbEntry(quantity: LoopQuantity(unit: .gram, doubleValue: carbAmount), startDate: mealTime, foodType: nil, diff --git a/Loop/Managers/LoopDataManager+CarbAbsorption.swift b/Loop/Managers/LoopDataManager+CarbAbsorption.swift index 8f532a4e02..705ef75b35 100644 --- a/Loop/Managers/LoopDataManager+CarbAbsorption.swift +++ b/Loop/Managers/LoopDataManager+CarbAbsorption.swift @@ -8,7 +8,6 @@ import Foundation import LoopKit -import HealthKit import LoopAlgorithm struct CarbAbsorptionReview { diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift index d79b8c2db9..bf333358df 100644 --- a/Loop/Managers/LoopDataManager.swift +++ b/Loop/Managers/LoopDataManager.swift @@ -8,7 +8,6 @@ import Foundation import Combine -import HealthKit import LoopKit import LoopKitUI import LoopCore @@ -902,7 +901,7 @@ extension LoopDataManager { ).filterDateRange(startSuspend, endSuspend) } - func computeSimpleBolusRecommendation(at date: Date, mealCarbs: HKQuantity?, manualGlucose: HKQuantity?) -> BolusDosingDecision? { + func computeSimpleBolusRecommendation(at date: Date, mealCarbs: LoopQuantity?, manualGlucose: LoopQuantity?) -> BolusDosingDecision? { var dosingDecision = BolusDosingDecision(for: .simpleBolus) @@ -938,13 +937,13 @@ extension LoopDataManager { let bolusAmount = SimpleBolusCalculator.recommendedInsulin( mealCarbs: mealCarbs, manualGlucose: manualGlucose, - activeInsulin: HKQuantity.init(unit: .internationalUnit(), doubleValue: iob), + activeInsulin: LoopQuantity.init(unit: .internationalUnit, doubleValue: iob), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule, at: date) - dosingDecision.manualBolusRecommendation = ManualBolusRecommendationWithDate(recommendation: ManualBolusRecommendation(amount: bolusAmount.doubleValue(for: .internationalUnit()), notice: notice), + dosingDecision.manualBolusRecommendation = ManualBolusRecommendationWithDate(recommendation: ManualBolusRecommendation(amount: bolusAmount.doubleValue(for: .internationalUnit), notice: notice), date: Date()) return dosingDecision @@ -1135,7 +1134,7 @@ extension LoopDataManager: ServicesManagerDelegate { throw CarbActionError.invalidCarbs } - guard amountInGrams <= LoopConstants.maxCarbEntryQuantity.doubleValue(for: .gram()) else { + guard amountInGrams <= LoopConstants.maxCarbEntryQuantity.doubleValue(for: .gram) else { throw CarbActionError.exceedsMaxCarbs } @@ -1147,7 +1146,7 @@ extension LoopDataManager: ServicesManagerDelegate { } } - let quantity = HKQuantity(unit: .gram(), doubleValue: amountInGrams) + let quantity = LoopQuantity(unit: .gram, doubleValue: amountInGrams) let candidateCarbEntry = NewCarbEntry(quantity: quantity, startDate: startDate ?? Date(), foodType: foodType, absorptionTime: absorptionTime) let _ = try await carbStore.addCarbEntry(candidateCarbEntry) @@ -1199,7 +1198,7 @@ extension LoopDataManager: SimpleBolusViewModelDelegate { settingsProvider.settings.maximumBolus } - var suspendThreshold: HKQuantity? { + var suspendThreshold: LoopQuantity? { settingsProvider.settings.suspendThreshold?.quantity } diff --git a/Loop/Managers/Missed Meal Detection/MealDetectionManager.swift b/Loop/Managers/Missed Meal Detection/MealDetectionManager.swift index e014a4332d..979009f92b 100644 --- a/Loop/Managers/Missed Meal Detection/MealDetectionManager.swift +++ b/Loop/Managers/Missed Meal Detection/MealDetectionManager.swift @@ -7,7 +7,6 @@ // import Foundation -import HealthKit import OSLog import LoopCore import LoopKit @@ -32,7 +31,7 @@ class MealDetectionManager { private let log = OSLog(category: "MealDetectionManager") // All math for meal detection occurs in mg/dL, with settings being converted if in mmol/L - private let unit = HKUnit.milligramsPerDeciliter + private let unit = LoopUnit.milligramsPerDeciliter /// The last missed meal notification that was sent /// Internal for unit testing @@ -325,7 +324,7 @@ class MealDetectionManager { return } - let currentCarbRatio = settingsProvider.carbRatioSchedule!.quantity(at: now).doubleValue(for: .gram()) + let currentCarbRatio = settingsProvider.carbRatioSchedule!.quantity(at: now).doubleValue(for: .gram) let maxAllowedCarbAutofill = settingsProvider.maximumBolus! * currentCarbRatio let clampedCarbAmount = min(carbAmount, maxAllowedCarbAutofill) @@ -406,7 +405,7 @@ extension GlucoseEffectVelocity { return GlucoseEffect( startDate: end, - quantity: HKQuantity( + quantity: LoopQuantity( unit: .milligramsPerDeciliter, doubleValue: velocityPerSecond * duration ) diff --git a/Loop/Managers/NotificationManager.swift b/Loop/Managers/NotificationManager.swift index b91ab70614..d3ab7d44e8 100644 --- a/Loop/Managers/NotificationManager.swift +++ b/Loop/Managers/NotificationManager.swift @@ -118,7 +118,7 @@ extension NotificationManager { static func sendRemoteBolusNotification(amount: Double) { let notification = UNMutableNotificationContent() - let quantityFormatter = QuantityFormatter(for: .internationalUnit()) + let quantityFormatter = QuantityFormatter(for: .internationalUnit) guard let amountDescription = quantityFormatter.numberFormatter.string(from: amount) else { return } @@ -140,7 +140,7 @@ extension NotificationManager { static func sendRemoteBolusFailureNotification(for error: Error, amountInUnits: Double) { let notification = UNMutableNotificationContent() - let quantityFormatter = QuantityFormatter(for: .internationalUnit()) + let quantityFormatter = QuantityFormatter(for: .internationalUnit) guard let amountDescription = quantityFormatter.numberFormatter.string(from: amountInUnits) else { return } diff --git a/Loop/Managers/SettingsManager.swift b/Loop/Managers/SettingsManager.swift index ff80a6170b..13c4e0ea91 100644 --- a/Loop/Managers/SettingsManager.swift +++ b/Loop/Managers/SettingsManager.swift @@ -10,7 +10,6 @@ import Foundation import LoopKit import UserNotifications import UIKit -import HealthKit import Combine import LoopCore import LoopKitUI @@ -278,11 +277,11 @@ class SettingsManager { try await settingsStore.getCarbRatioHistory(startDate: startDate, endDate: endDate) } - func getInsulinSensitivityHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue] { + func getInsulinSensitivityHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue] { try await settingsStore.getInsulinSensitivityHistory(startDate: startDate, endDate: endDate) } - func getTargetRangeHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue>] { + func getTargetRangeHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue>] { try await settingsStore.getTargetRangeHistory(startDate: startDate, endDate: endDate) } @@ -331,8 +330,8 @@ protocol SettingsProvider { func getBasalHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue] func getCarbRatioHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue] - func getInsulinSensitivityHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue] - func getTargetRangeHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue>] + func getInsulinSensitivityHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue] + func getTargetRangeHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue>] func getDosingLimits(at date: Date) async throws -> DosingLimits func executeSettingsQuery(fromQueryAnchor queryAnchor: SettingsStore.QueryAnchor?, limit: Int, completion: @escaping (SettingsStore.SettingsQueryResult) -> Void) } diff --git a/Loop/Managers/Store Protocols/CarbStoreProtocol.swift b/Loop/Managers/Store Protocols/CarbStoreProtocol.swift index a565cb703f..b6c7d16c5e 100644 --- a/Loop/Managers/Store Protocols/CarbStoreProtocol.swift +++ b/Loop/Managers/Store Protocols/CarbStoreProtocol.swift @@ -7,7 +7,6 @@ // import LoopKit -import HealthKit protocol CarbStoreProtocol: AnyObject { diff --git a/Loop/Managers/Store Protocols/GlucoseStoreProtocol.swift b/Loop/Managers/Store Protocols/GlucoseStoreProtocol.swift index 0f15a19f56..915f0016f7 100644 --- a/Loop/Managers/Store Protocols/GlucoseStoreProtocol.swift +++ b/Loop/Managers/Store Protocols/GlucoseStoreProtocol.swift @@ -7,7 +7,6 @@ // import LoopKit -import HealthKit import LoopAlgorithm protocol GlucoseStoreProtocol: AnyObject { diff --git a/Loop/Managers/TemporaryPresetsManager.swift b/Loop/Managers/TemporaryPresetsManager.swift index 2edbdecb12..31bb4af3a1 100644 --- a/Loop/Managers/TemporaryPresetsManager.swift +++ b/Loop/Managers/TemporaryPresetsManager.swift @@ -10,7 +10,6 @@ import Foundation import LoopKit import os.log import LoopCore -import HealthKit protocol PresetActivationObserver: AnyObject { func presetActivated(context: TemporaryScheduleOverride.Context, duration: TemporaryScheduleOverride.Duration) diff --git a/Loop/Managers/WatchDataManager.swift b/Loop/Managers/WatchDataManager.swift index c73af7aeea..b7262086fe 100644 --- a/Loop/Managers/WatchDataManager.swift +++ b/Loop/Managers/WatchDataManager.swift @@ -9,6 +9,7 @@ import HealthKit import UIKit import WatchConnectivity +import LoopAlgorithm import LoopKit import LoopCore @@ -139,7 +140,7 @@ final class WatchDataManager: NSObject { private var lastComplicationContext: WatchContext? private let minTrendDrift: Double = 20 - private lazy var minTrendUnit = HKUnit.milligramsPerDeciliter + private lazy var minTrendUnit = LoopUnit.milligramsPerDeciliter private func sendSettingsIfNeeded() { let userInfo = LoopSettingsUserInfo( @@ -272,7 +273,7 @@ final class WatchDataManager: NSObject { let context = WatchContext(glucose: glucose, glucoseUnit: self.deviceManager.displayGlucosePreference.unit) context.reservoir = reservoir?.unitVolume context.loopLastRunDate = loopDataManager.lastLoopCompleted - context.cob = carbsOnBoard?.quantity.doubleValue(for: HKUnit.gram()) + context.cob = carbsOnBoard?.quantity.doubleValue(for: .gram) if let glucoseDisplay = self.deviceManager.glucoseDisplay(for: glucose) { context.glucoseTrend = glucoseDisplay.trendType @@ -388,7 +389,7 @@ final class WatchDataManager: NSObject { if let carbEntry = bolus.carbEntry { let storedCarbEntry = try await loopDataManager.addCarbEntry(carbEntry) dosingDecision.carbEntry = storedCarbEntry - self.analyticsServicesManager?.didAddCarbs(source: "Watch", amount: storedCarbEntry.quantity.doubleValue(for: .gram())) + self.analyticsServicesManager?.didAddCarbs(source: "Watch", amount: storedCarbEntry.quantity.doubleValue(for: .gram)) } else { dosingDecision.carbEntry = nil } diff --git a/Loop/Models/ApplicationFactorStrategy.swift b/Loop/Models/ApplicationFactorStrategy.swift index d3244ec1c2..57038f5cb0 100644 --- a/Loop/Models/ApplicationFactorStrategy.swift +++ b/Loop/Models/ApplicationFactorStrategy.swift @@ -7,13 +7,13 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit import LoopCore protocol ApplicationFactorStrategy { func calculateDosingFactor( - for glucose: HKQuantity, - correctionRange: ClosedRange + for glucose: LoopQuantity, + correctionRange: ClosedRange ) -> Double } diff --git a/Loop/Models/ConstantApplicationFactorStrategy.swift b/Loop/Models/ConstantApplicationFactorStrategy.swift index 82ab6ebad6..41b4b478e2 100644 --- a/Loop/Models/ConstantApplicationFactorStrategy.swift +++ b/Loop/Models/ConstantApplicationFactorStrategy.swift @@ -7,15 +7,14 @@ // import Foundation -import HealthKit import LoopKit import LoopCore import LoopAlgorithm struct ConstantApplicationFactorStrategy: ApplicationFactorStrategy { func calculateDosingFactor( - for glucose: HKQuantity, - correctionRange: ClosedRange + for glucose: LoopQuantity, + correctionRange: ClosedRange ) -> Double { // The original strategy uses a constant dosing factor. return LoopAlgorithm.defaultBolusPartialApplicationFactor diff --git a/Loop/Models/GlucoseBasedApplicationFactorStrategy.swift b/Loop/Models/GlucoseBasedApplicationFactorStrategy.swift index 7f03337011..e339d4a881 100644 --- a/Loop/Models/GlucoseBasedApplicationFactorStrategy.swift +++ b/Loop/Models/GlucoseBasedApplicationFactorStrategy.swift @@ -7,7 +7,7 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit import LoopCore @@ -20,8 +20,8 @@ struct GlucoseBasedApplicationFactorStrategy: ApplicationFactorStrategy { static let maxGlucoseSlidingScale = 200.0 // mg/dL func calculateDosingFactor( - for glucose: HKQuantity, - correctionRange: ClosedRange + for glucose: LoopQuantity, + correctionRange: ClosedRange ) -> Double { // Calculate current glucose and lower bound target let currentGlucose = glucose.doubleValue(for: .milligramsPerDeciliter) diff --git a/Loop/Models/GlucoseDisplay.swift b/Loop/Models/GlucoseDisplay.swift index 119e06d096..fe81a05b34 100644 --- a/Loop/Models/GlucoseDisplay.swift +++ b/Loop/Models/GlucoseDisplay.swift @@ -7,19 +7,19 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit struct GlucoseDisplay: GlucoseDisplayable { let isStateValid: Bool let trendType: GlucoseTrend? - let trendRate: HKQuantity? + let trendRate: LoopQuantity? let isLocal: Bool var glucoseRangeCategory: GlucoseRangeCategory? init(isStateValid: Bool, trendType: GlucoseTrend?, - trendRate: HKQuantity?, + trendRate: LoopQuantity?, isLocal: Bool, glucoseRangeCategory: GlucoseRangeCategory?) { @@ -45,7 +45,7 @@ struct GlucoseDisplay: GlucoseDisplayable { struct ManualGlucoseDisplay: GlucoseDisplayable { let isStateValid: Bool let trendType: GlucoseTrend? - let trendRate: HKQuantity? + let trendRate: LoopQuantity? let isLocal: Bool let glucoseRangeCategory: GlucoseRangeCategory? diff --git a/Loop/Models/GlucoseEffectVelocity.swift b/Loop/Models/GlucoseEffectVelocity.swift index 6680073769..4a9ab40796 100644 --- a/Loop/Models/GlucoseEffectVelocity.swift +++ b/Loop/Models/GlucoseEffectVelocity.swift @@ -5,7 +5,6 @@ // Copyright © 2017 LoopKit Authors. All rights reserved. // -import HealthKit import LoopKit import LoopAlgorithm @@ -13,7 +12,7 @@ import LoopAlgorithm extension GlucoseEffectVelocity: RawRepresentable { public typealias RawValue = [String: Any] - static let unit = HKUnit.milligramsPerDeciliter.unitDivided(by: .minute()) + static let unit = LoopUnit.milligramsPerDeciliterPerMinute public init?(rawValue: RawValue) { guard let startDate = rawValue["startDate"] as? Date, @@ -25,7 +24,7 @@ extension GlucoseEffectVelocity: RawRepresentable { self.init( startDate: startDate, endDate: rawValue["endDate"] as? Date ?? startDate, - quantity: HKQuantity(unit: type(of: self).unit, doubleValue: doubleValue) + quantity: LoopQuantity(unit: type(of: self).unit, doubleValue: doubleValue) ) } diff --git a/Loop/Models/LoopConstants.swift b/Loop/Models/LoopConstants.swift index bd1296c12f..0d7d881279 100644 --- a/Loop/Models/LoopConstants.swift +++ b/Loop/Models/LoopConstants.swift @@ -7,7 +7,7 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit import UIKit @@ -15,11 +15,11 @@ enum LoopConstants { // Input field bounds - static let maxCarbEntryQuantity = HKQuantity(unit: .gram(), doubleValue: 250) // cannot exceed this value + static let maxCarbEntryQuantity = LoopQuantity(unit: .gram, doubleValue: 250) // cannot exceed this value - static let warningCarbEntryQuantity = HKQuantity(unit: .gram(), doubleValue: 99) // user is warned above this value + static let warningCarbEntryQuantity = LoopQuantity(unit: .gram, doubleValue: 99) // user is warned above this value - static let validManualGlucoseEntryRange = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 10)...HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 600) + static let validManualGlucoseEntryRange = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 10)...LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 600) static let minCarbAbsorptionTime = TimeInterval(minutes: 30) static let maxCarbAbsorptionTime = TimeInterval(hours: 8) @@ -36,13 +36,13 @@ enum LoopConstants { static let statusChartMinimumHistoryDisplay: TimeInterval = .hours(1) static let glucoseChartDefaultDisplayBound = - HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 100)...HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 175) + LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 100)...LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 175) static let glucoseChartDefaultDisplayRangeWide = - HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 60)...HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 200) + LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 60)...LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 200) static let glucoseChartDefaultDisplayBoundClamped = - HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 80)...HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 240) + LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 80)...LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 240) // Compile time configuration @@ -66,7 +66,7 @@ enum LoopConstants { static let missedMealWarningVelocitySampleMinDuration = TimeInterval(minutes: 12) // Bolus calculator warning thresholds - static let simpleBolusCalculatorMinGlucoseBolusRecommendation = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 70) - static let simpleBolusCalculatorMinGlucoseMealBolusRecommendation = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 55) - static let simpleBolusCalculatorGlucoseWarningLimit = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 70) + static let simpleBolusCalculatorMinGlucoseBolusRecommendation = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 70) + static let simpleBolusCalculatorMinGlucoseMealBolusRecommendation = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 55) + static let simpleBolusCalculatorGlucoseWarningLimit = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 70) } diff --git a/Loop/Models/ManualBolusRecommendation.swift b/Loop/Models/ManualBolusRecommendation.swift index 1753813e2c..4594bae7f8 100644 --- a/Loop/Models/ManualBolusRecommendation.swift +++ b/Loop/Models/ManualBolusRecommendation.swift @@ -8,12 +8,11 @@ import Foundation import LoopKit -import HealthKit import LoopAlgorithm extension BolusRecommendationNotice { - public func description(using unit: HKUnit) -> String { + public func description(using unit: LoopUnit) -> String { switch self { case .glucoseBelowSuspendThreshold(minGlucose: let minGlucose): let glucoseFormatter = NumberFormatter.glucoseFormatter(for: unit) diff --git a/Loop/Models/PredictionInputEffect.swift b/Loop/Models/PredictionInputEffect.swift index 175afd3c1b..342fe23db5 100644 --- a/Loop/Models/PredictionInputEffect.swift +++ b/Loop/Models/PredictionInputEffect.swift @@ -7,7 +7,6 @@ // import Foundation -import HealthKit import LoopKit import LoopAlgorithm @@ -39,7 +38,7 @@ struct PredictionInputEffect: OptionSet { } } - func localizedDescription(forGlucoseUnit unit: HKUnit) -> String? { + func localizedDescription(forGlucoseUnit unit: LoopUnit) -> String? { switch self { case [.carbs]: return String(format: NSLocalizedString("Carbs Absorbed (g) ÷ Carb Ratio (g/U) × Insulin Sensitivity (%1$@/U)", comment: "Description of the prediction input effect for carbohydrates. (1: The glucose unit string)"), unit.localizedShortUnitString) diff --git a/Loop/Models/SimpleBolusCalculator.swift b/Loop/Models/SimpleBolusCalculator.swift index a26af98466..515aef3f5f 100644 --- a/Loop/Models/SimpleBolusCalculator.swift +++ b/Loop/Models/SimpleBolusCalculator.swift @@ -8,17 +8,17 @@ import Foundation import LoopCore -import HealthKit +import LoopAlgorithm import LoopKit struct SimpleBolusCalculator { - public static func recommendedInsulin(mealCarbs: HKQuantity?, manualGlucose: HKQuantity?, activeInsulin: HKQuantity, carbRatioSchedule: CarbRatioSchedule, correctionRangeSchedule: GlucoseRangeSchedule, sensitivitySchedule: InsulinSensitivitySchedule, at date: Date = Date()) -> HKQuantity { + public static func recommendedInsulin(mealCarbs: LoopQuantity?, manualGlucose: LoopQuantity?, activeInsulin: LoopQuantity, carbRatioSchedule: CarbRatioSchedule, correctionRangeSchedule: GlucoseRangeSchedule, sensitivitySchedule: InsulinSensitivitySchedule, at date: Date = Date()) -> LoopQuantity { var recommendedBolus: Double = 0 if let mealCarbs = mealCarbs { let carbRatio = carbRatioSchedule.quantity(at: date) - recommendedBolus += mealCarbs.doubleValue(for: .gram()) / carbRatio.doubleValue(for: .gram()) + recommendedBolus += mealCarbs.doubleValue(for: .gram) / carbRatio.doubleValue(for: .gram) } if let manualGlucose = manualGlucose { @@ -28,7 +28,7 @@ struct SimpleBolusCalculator { let correctionTarget = correctionRange.averageValue(for: .milligramsPerDeciliter) let correctionBolus = (manualGlucose.doubleValue(for: .milligramsPerDeciliter) - correctionTarget) / sensitivity if correctionBolus >= 0 { - let activeInsulin = max(0, activeInsulin.doubleValue(for: .internationalUnit())) + let activeInsulin = max(0, activeInsulin.doubleValue(for: .internationalUnit)) let correctionBolusMinusActiveInsulin = correctionBolus - activeInsulin recommendedBolus += max(0, correctionBolusMinusActiveInsulin) } else { @@ -46,6 +46,6 @@ struct SimpleBolusCalculator { // No negative recommendation recommendedBolus = max(0, recommendedBolus) - return HKQuantity(unit: .internationalUnit(), doubleValue: recommendedBolus) + return LoopQuantity(unit: .internationalUnit, doubleValue: recommendedBolus) } } diff --git a/Loop/Models/StoredDataAlgorithmInput.swift b/Loop/Models/StoredDataAlgorithmInput.swift index ae33304c3c..b5273bf2c6 100644 --- a/Loop/Models/StoredDataAlgorithmInput.swift +++ b/Loop/Models/StoredDataAlgorithmInput.swift @@ -8,7 +8,6 @@ import Foundation import LoopKit -import HealthKit import LoopAlgorithm struct StoredDataAlgorithmInput: AlgorithmInput { @@ -28,13 +27,13 @@ struct StoredDataAlgorithmInput: AlgorithmInput { var basal: [AbsoluteScheduleValue] - var sensitivity: [AbsoluteScheduleValue] + var sensitivity: [AbsoluteScheduleValue] var carbRatio: [AbsoluteScheduleValue] var target: GlucoseRangeTimeline - var suspendThreshold: HKQuantity? + var suspendThreshold: LoopQuantity? var maxBolus: Double diff --git a/Loop/Models/WatchContext+LoopKit.swift b/Loop/Models/WatchContext+LoopKit.swift index 2235ec7b92..e1374e4ed1 100644 --- a/Loop/Models/WatchContext+LoopKit.swift +++ b/Loop/Models/WatchContext+LoopKit.swift @@ -7,12 +7,11 @@ // import Foundation -import HealthKit import LoopKit import LoopAlgorithm extension WatchContext { - convenience init(glucose: GlucoseSampleValue?, glucoseUnit: HKUnit?) { + convenience init(glucose: GlucoseSampleValue?, glucoseUnit: LoopUnit?) { self.init() self.glucose = glucose?.quantity diff --git a/Loop/View Controllers/CarbAbsorptionViewController.swift b/Loop/View Controllers/CarbAbsorptionViewController.swift index be8327bba8..8e7fc59406 100644 --- a/Loop/View Controllers/CarbAbsorptionViewController.swift +++ b/Loop/View Controllers/CarbAbsorptionViewController.swift @@ -6,7 +6,6 @@ // import SwiftUI -import HealthKit import Intents import LoopCore import LoopKit @@ -235,7 +234,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif static let count = 1 } - private lazy var carbFormatter: QuantityFormatter = QuantityFormatter(for: .gram()) + private lazy var carbFormatter: QuantityFormatter = QuantityFormatter(for: .gram) private lazy var absorptionFormatter: DateComponentsFormatter = { let formatter = DateComponentsFormatter() @@ -292,7 +291,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif return cell case .entries: - let unit = HKUnit.gram() + let unit = LoopUnit.gram let cell = tableView.dequeueReusableCell(withIdentifier: CarbEntryTableViewCell.className, for: indexPath) as! CarbEntryTableViewCell // Entry value @@ -323,7 +322,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif if let absorption = status.absorption { // Absorbed value - let observedProgress = Float(absorption.observedProgress.doubleValue(for: .percent())) + let observedProgress = Float(absorption.observedProgress.doubleValue(for: .percent)) let observedCarbs = absorption.observed if let observedCarbsText = carbFormatter.string(from: observedCarbs) { @@ -342,7 +341,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif } cell.observedProgress = observedProgress - cell.clampedProgress = Float(absorption.observedProgress.doubleValue(for: .percent())) + cell.clampedProgress = Float(absorption.observedProgress.doubleValue(for: .percent)) cell.observedDateText = absorptionFormatter.string(from: absorption.estimatedDate.duration) // Absorbed time @@ -366,7 +365,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif } private func updateCell(_ cell: HeaderValuesTableViewCell) { - let unit = HKUnit.gram() + let unit = LoopUnit.gram if let carbsOnBoard = carbsOnBoard, carbsOnBoard.quantity.doubleValue(for: unit) > 0 { cell.COBDateLabel.text = String( @@ -389,7 +388,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif cell.COBDateLabel.textColor = textColor } else { cell.COBDateLabel.text = nil - cell.COBValueLabel.text = carbFormatter.string(from: HKQuantity(unit: .gram(), doubleValue: 0), includeUnit: false) + cell.COBValueLabel.text = carbFormatter.string(from: LoopQuantity(unit: .gram, doubleValue: 0), includeUnit: false) } if let carbTotal = carbTotal { @@ -400,7 +399,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif cell.totalValueLabel.text = carbFormatter.string(from: carbTotal.quantity, includeUnit: false) } else { cell.totalDateLabel.text = nil - cell.totalValueLabel.text = carbFormatter.string(from: HKQuantity(unit: .gram(), doubleValue: 0), includeUnit: false) + cell.totalValueLabel.text = carbFormatter.string(from: LoopQuantity(unit: .gram, doubleValue: 0), includeUnit: false) } } diff --git a/Loop/View Controllers/GlucoseThresholdTableViewController.swift b/Loop/View Controllers/GlucoseThresholdTableViewController.swift index 1657be2779..cb6bbb7011 100644 --- a/Loop/View Controllers/GlucoseThresholdTableViewController.swift +++ b/Loop/View Controllers/GlucoseThresholdTableViewController.swift @@ -7,16 +7,16 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit import LoopKitUI import UIKit final class GlucoseThresholdTableViewController: TextFieldTableViewController { - public let glucoseUnit: HKUnit + public let glucoseUnit: LoopUnit - init(threshold: Double?, glucoseUnit: HKUnit) { + init(threshold: Double?, glucoseUnit: LoopUnit) { self.glucoseUnit = glucoseUnit super.init(style: .grouped) diff --git a/Loop/View Controllers/LoopChartsTableViewController.swift b/Loop/View Controllers/LoopChartsTableViewController.swift index 8b1e56447b..699459f0b7 100644 --- a/Loop/View Controllers/LoopChartsTableViewController.swift +++ b/Loop/View Controllers/LoopChartsTableViewController.swift @@ -8,7 +8,6 @@ import UIKit import LoopUI import LoopKitUI -import HealthKit import os.log diff --git a/Loop/View Controllers/PredictionTableViewController.swift b/Loop/View Controllers/PredictionTableViewController.swift index 79ab21a35f..ffaffe0070 100644 --- a/Loop/View Controllers/PredictionTableViewController.swift +++ b/Loop/View Controllers/PredictionTableViewController.swift @@ -6,7 +6,6 @@ // Copyright © 2016 Nathan Racklyeft. All rights reserved. // -import HealthKit import LoopCore import LoopKit import LoopKitUI @@ -76,7 +75,7 @@ class PredictionTableViewController: LoopChartsTableViewController, Identifiable private var retrospectiveGlucoseDiscrepancies: [GlucoseChange]? - private var totalRetrospectiveCorrection: HKQuantity? + private var totalRetrospectiveCorrection: LoopQuantity? private var refreshContext = RefreshContext.all @@ -115,7 +114,7 @@ class PredictionTableViewController: LoopChartsTableViewController, Identifiable chartStartDate = calendar.nextDate(after: date, matching: components, matchingPolicy: .strict, direction: .backward) ?? date var glucoseSamples: [StoredGlucoseSample]? - var totalRetrospectiveCorrection: HKQuantity? + var totalRetrospectiveCorrection: LoopQuantity? // For now, do this every time _ = self.refreshContext.remove(.status) @@ -259,7 +258,7 @@ class PredictionTableViewController: LoopChartsTableViewController, Identifiable let currentGlucose = loopDataManager.latestGlucose { let formatter = QuantityFormatter(for: glucoseChart.glucoseUnit) - let predicted = HKQuantity(unit: glucoseChart.glucoseUnit, doubleValue: currentGlucose.quantity.doubleValue(for: glucoseChart.glucoseUnit) - lastDiscrepancy.quantity.doubleValue(for: glucoseChart.glucoseUnit)) + let predicted = LoopQuantity(unit: glucoseChart.glucoseUnit, doubleValue: currentGlucose.quantity.doubleValue(for: glucoseChart.glucoseUnit) - lastDiscrepancy.quantity.doubleValue(for: glucoseChart.glucoseUnit)) var values = [predicted, currentGlucose.quantity].map { formatter.string(from: $0) ?? "?" } formatter.numberFormatter.positivePrefix = formatter.numberFormatter.plusSign values.append(formatter.string(from: lastDiscrepancy.quantity) ?? "?") @@ -275,7 +274,7 @@ class PredictionTableViewController: LoopChartsTableViewController, Identifiable var totalEffectDisplay = "?" if let totalEffect = self.totalRetrospectiveCorrection { let integralEffectValue = totalEffect.doubleValue(for: glucoseChart.glucoseUnit) - lastDiscrepancy.quantity.doubleValue(for: glucoseChart.glucoseUnit) - let integralEffect = HKQuantity(unit: glucoseChart.glucoseUnit, doubleValue: integralEffectValue) + let integralEffect = LoopQuantity(unit: glucoseChart.glucoseUnit, doubleValue: integralEffectValue) integralEffectDisplay = formatter.string(from: integralEffect) ?? "?" totalEffectDisplay = formatter.string(from: totalEffect) ?? "?" } diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 1b075628d2..1448a6fb36 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -7,7 +7,6 @@ // import UIKit -import HealthKit import SwiftUI import Intents import LoopCore @@ -30,10 +29,10 @@ final class StatusTableViewController: LoopChartsTableViewController { private let log = OSLog(category: "StatusTableViewController") - lazy var carbFormatter: QuantityFormatter = QuantityFormatter(for: .gram()) + lazy var carbFormatter: QuantityFormatter = QuantityFormatter(for: .gram) lazy var insulinFormatter: QuantityFormatter = { - let formatter = QuantityFormatter(for: .internationalUnit()) + let formatter = QuantityFormatter(for: .internationalUnit) formatter.numberFormatter.maximumFractionDigits = 2 return formatter }() @@ -480,7 +479,7 @@ final class StatusTableViewController: LoopChartsTableViewController { var doseEntries: [BasalRelativeDose]? var totalDelivery: Double? var cobValues: [CarbValue]? - var carbsOnBoard: HKQuantity? + var carbsOnBoard: LoopQuantity? let startDate = charts.startDate let basalDeliveryState = self.basalDeliveryState let automaticDosingEnabled = automaticDosingStatus.automaticDosingEnabled diff --git a/Loop/View Controllers/TextFieldTableViewController.swift b/Loop/View Controllers/TextFieldTableViewController.swift index 07c686e0f8..5dc954e726 100644 --- a/Loop/View Controllers/TextFieldTableViewController.swift +++ b/Loop/View Controllers/TextFieldTableViewController.swift @@ -7,7 +7,6 @@ // import LoopKitUI -import HealthKit /// Convenience static constructors used to contain common configuration diff --git a/Loop/View Models/BolusEntryViewModel.swift b/Loop/View Models/BolusEntryViewModel.swift index 4b88387fd5..49f3a1e5d2 100644 --- a/Loop/View Models/BolusEntryViewModel.swift +++ b/Loop/View Models/BolusEntryViewModel.swift @@ -7,7 +7,6 @@ // import Combine -import HealthKit import LocalAuthentication import Intents import os.log @@ -66,7 +65,7 @@ final class BolusEntryViewModel: ObservableObject { enum Notice: Equatable { case predictedGlucoseInRange - case predictedGlucoseBelowSuspendThreshold(suspendThreshold: HKQuantity) + case predictedGlucoseBelowSuspendThreshold(suspendThreshold: LoopQuantity) case glucoseBelowTarget case staleGlucoseData case futureGlucoseData @@ -93,26 +92,26 @@ final class BolusEntryViewModel: ObservableObject { @Published var predictedGlucoseValues: [GlucoseValue] = [] @Published var chartDateInterval: DateInterval - @Published var activeCarbs: HKQuantity? - @Published var activeInsulin: HKQuantity? + @Published var activeCarbs: LoopQuantity? + @Published var activeInsulin: LoopQuantity? @Published var targetGlucoseSchedule: GlucoseRangeSchedule? @Published var preMealOverride: TemporaryScheduleOverride? private var savedPreMealOverride: TemporaryScheduleOverride? @Published var scheduleOverride: TemporaryScheduleOverride? - var maximumBolus: HKQuantity? + var maximumBolus: LoopQuantity? let originalCarbEntry: StoredCarbEntry? let potentialCarbEntry: NewCarbEntry? let selectedCarbAbsorptionTimeEmoji: String? - @Published var recommendedBolus: HKQuantity? + @Published var recommendedBolus: LoopQuantity? var recommendedBolusAmount: Double? { - recommendedBolus?.doubleValue(for: .internationalUnit()) + recommendedBolus?.doubleValue(for: .internationalUnit) } - @Published var enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0) + @Published var enteredBolus = LoopQuantity(unit: .internationalUnit, doubleValue: 0) var enteredBolusAmount: Double { - enteredBolus.doubleValue(for: .internationalUnit()) + enteredBolus.doubleValue(for: .internationalUnit) } private var userChangedBolusAmount = false @Published var isInitiatingSaveOrBolus = false @@ -138,7 +137,7 @@ final class BolusEntryViewModel: ObservableObject { }() @Published var isManualGlucoseEntryEnabled = false - @Published var manualGlucoseQuantity: HKQuantity? + @Published var manualGlucoseQuantity: LoopQuantity? var manualGlucoseSample: NewGlucoseSample? @@ -240,7 +239,7 @@ final class BolusEntryViewModel: ObservableObject { guard let self = self else { return } // Clear out any entered bolus whenever the glucose entry changes - self.enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0) + self.enteredBolus = LoopQuantity(unit: .internationalUnit, doubleValue: 0) Task { await self.updatePredictedGlucoseValues() @@ -324,7 +323,7 @@ final class BolusEntryViewModel: ObservableObject { return false } - guard enteredBolusAmount <= maximumBolus.doubleValue(for: .internationalUnit()) else { + guard enteredBolusAmount <= maximumBolus.doubleValue(for: .internationalUnit) else { presentAlert(.maxBolusExceeded) return false } @@ -368,7 +367,7 @@ final class BolusEntryViewModel: ObservableObject { self.dosingDecision.manualGlucoseSample = nil } - let activationType = BolusActivationType.activationTypeFor(recommendedAmount: recommendedBolus?.doubleValue(for: .internationalUnit()), bolusAmount: amountToDeliver) + let activationType = BolusActivationType.activationTypeFor(recommendedAmount: recommendedBolus?.doubleValue(for: .internationalUnit), bolusAmount: amountToDeliver) if let carbEntry = potentialCarbEntry { if originalCarbEntry == nil { @@ -382,7 +381,7 @@ final class BolusEntryViewModel: ObservableObject { } if let storedCarbEntry = await saveCarbEntry(carbEntry, replacingEntry: originalCarbEntry) { self.dosingDecision.carbEntry = storedCarbEntry - self.analyticsServicesManager?.didAddCarbs(source: "Phone", amount: storedCarbEntry.quantity.doubleValue(for: .gram()), isFavoriteFood: storedCarbEntry.favoriteFoodID != nil) + self.analyticsServicesManager?.didAddCarbs(source: "Phone", amount: storedCarbEntry.quantity.doubleValue(for: .gram), isFavoriteFood: storedCarbEntry.favoriteFoodID != nil) } else { self.presentAlert(.carbEntryPersistenceFailure) return false @@ -416,7 +415,7 @@ final class BolusEntryViewModel: ObservableObject { } private lazy var bolusAmountFormatter: NumberFormatter = { - let formatter = QuantityFormatter(for: .internationalUnit()) + let formatter = QuantityFormatter(for: .internationalUnit) formatter.numberFormatter.roundingMode = .down return formatter.numberFormatter }() @@ -436,7 +435,7 @@ final class BolusEntryViewModel: ObservableObject { } var maximumBolusAmountString: String? { - guard let maxBolusAmount = maximumBolus?.doubleValue(for: .internationalUnit()) else { + guard let maxBolusAmount = maximumBolus?.doubleValue(for: .internationalUnit) else { return nil } return formatBolusAmount(maxBolusAmount) @@ -445,7 +444,7 @@ final class BolusEntryViewModel: ObservableObject { var carbEntryAmountAndEmojiString: String? { guard let potentialCarbEntry = potentialCarbEntry, - let carbAmountString = QuantityFormatter(for: .gram()).string(from: potentialCarbEntry.quantity) + let carbAmountString = QuantityFormatter(for: .gram).string(from: potentialCarbEntry.quantity) else { return nil } @@ -501,7 +500,7 @@ final class BolusEntryViewModel: ObservableObject { var chartGlucoseValues = storedGlucoseValues if let manualGlucoseSample = manualGlucoseSample { - chartGlucoseValues.append(manualGlucoseSample.quantitySample) + chartGlucoseValues.append(LoopQuantitySample(with: manualGlucoseSample.quantitySample)) } self.glucoseValues = chartGlucoseValues @@ -523,7 +522,7 @@ final class BolusEntryViewModel: ObservableObject { deliveryType: .bolus, startDate: startDate, endDate: startDate, - volume: enteredBolus.doubleValue(for: .internationalUnit()), + volume: enteredBolus.doubleValue(for: .internationalUnit), insulinModel: insulinModel ) @@ -554,13 +553,13 @@ final class BolusEntryViewModel: ObservableObject { } var recommendation: ManualBolusRecommendation? - let recommendedBolus: HKQuantity? + let recommendedBolus: LoopQuantity? let notice: Notice? do { recommendation = try await computeBolusRecommendation() if let recommendation, deliveryDelegate != nil { - recommendedBolus = HKQuantity(unit: .internationalUnit(), doubleValue: recommendation.amount) + recommendedBolus = LoopQuantity(unit: .internationalUnit, doubleValue: recommendation.amount) switch recommendation.notice { case .glucoseBelowSuspendThreshold: @@ -577,7 +576,7 @@ final class BolusEntryViewModel: ObservableObject { notice = nil } } else { - recommendedBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0) + recommendedBolus = LoopQuantity(unit: .internationalUnit, doubleValue: 0) notice = nil } } catch { @@ -640,7 +639,7 @@ final class BolusEntryViewModel: ObservableObject { } maximumBolus = delegate.settings.maximumBolus.map { maxBolusAmount in - HKQuantity(unit: .internationalUnit(), doubleValue: maxBolusAmount) + LoopQuantity(unit: .internationalUnit, doubleValue: maxBolusAmount) } dosingDecision.scheduleOverride = scheduleOverride @@ -690,7 +689,7 @@ final class BolusEntryViewModel: ObservableObject { } func updateEnteredBolus(_ enteredBolusAmount: Double?) { - enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: enteredBolusAmount ?? 0) + enteredBolus = LoopQuantity(unit: .internationalUnit, doubleValue: enteredBolusAmount ?? 0) } } @@ -726,7 +725,7 @@ extension BolusEntryViewModel { } private var hasBolusEntryReadyToDeliver: Bool { - enteredBolus.doubleValue(for: .internationalUnit()) != 0 + enteredBolus.doubleValue(for: .internationalUnit) != 0 } private var hasDataToSave: Bool { diff --git a/Loop/View Models/CarbEntryViewModel.swift b/Loop/View Models/CarbEntryViewModel.swift index b71771b6ad..2228a289b0 100644 --- a/Loop/View Models/CarbEntryViewModel.swift +++ b/Loop/View Models/CarbEntryViewModel.swift @@ -8,7 +8,6 @@ import SwiftUI import LoopKit -import HealthKit import Combine import LoopCore import LoopAlgorithm @@ -59,7 +58,7 @@ final class CarbEntryViewModel: ObservableObject { let shouldBeginEditingQuantity: Bool @Published var carbsQuantity: Double? = nil - var preferredCarbUnit = HKUnit.gram() + var preferredCarbUnit = LoopUnit.gram var maxCarbEntryQuantity = LoopConstants.maxCarbEntryQuantity var warningCarbEntryQuantity = LoopConstants.warningCarbEntryQuantity @@ -160,7 +159,7 @@ final class CarbEntryViewModel: ObservableObject { return NewCarbEntry( date: date, - quantity: HKQuantity(unit: preferredCarbUnit, doubleValue: quantity), + quantity: LoopQuantity(unit: preferredCarbUnit, doubleValue: quantity), startDate: time, foodType: usesCustomFoodType ? foodType : selectedDefaultAbsorptionTimeEmoji, absorptionTime: absorptionTime, @@ -200,7 +199,7 @@ final class CarbEntryViewModel: ObservableObject { } guard let carbsQuantity, carbsQuantity > 0 else { return } - let quantity = HKQuantity(unit: preferredCarbUnit, doubleValue: carbsQuantity) + let quantity = LoopQuantity(unit: preferredCarbUnit, doubleValue: carbsQuantity) if quantity.compare(maxCarbEntryQuantity) == .orderedDescending { self.alert = .maxQuantityExceded return diff --git a/Loop/View Models/FavoriteFoodAddEditViewModel.swift b/Loop/View Models/FavoriteFoodAddEditViewModel.swift index 225766db4c..b3f70fe3cf 100644 --- a/Loop/View Models/FavoriteFoodAddEditViewModel.swift +++ b/Loop/View Models/FavoriteFoodAddEditViewModel.swift @@ -8,7 +8,7 @@ import SwiftUI import LoopKit -import HealthKit +import LoopAlgorithm final class FavoriteFoodAddEditViewModel: ObservableObject { enum Alert: Identifiable { @@ -23,7 +23,7 @@ final class FavoriteFoodAddEditViewModel: ObservableObject { @Published var name = "" @Published var carbsQuantity: Double? = nil - var preferredCarbUnit = HKUnit.gram() + var preferredCarbUnit = LoopUnit.gram var maxCarbEntryQuantity = LoopConstants.maxCarbEntryQuantity var warningCarbEntryQuantity = LoopConstants.warningCarbEntryQuantity @@ -76,7 +76,7 @@ final class FavoriteFoodAddEditViewModel: ObservableObject { return NewFavoriteFood( name: name, - carbsQuantity: HKQuantity(unit: preferredCarbUnit, doubleValue: quantity), + carbsQuantity: LoopQuantity(unit: preferredCarbUnit, doubleValue: quantity), foodType: foodType, absorptionTime: absorptionTime ) @@ -90,7 +90,7 @@ final class FavoriteFoodAddEditViewModel: ObservableObject { guard let updatedFavoriteFood, absorptionTime <= maxAbsorptionTime else { return } guard let carbsQuantity, carbsQuantity > 0 else { return } - let quantity = HKQuantity(unit: preferredCarbUnit, doubleValue: carbsQuantity) + let quantity = LoopQuantity(unit: preferredCarbUnit, doubleValue: carbsQuantity) if quantity.compare(maxCarbEntryQuantity) == .orderedDescending { self.alert = .maxQuantityExceded return diff --git a/Loop/View Models/FavoriteFoodInsightsViewModel.swift b/Loop/View Models/FavoriteFoodInsightsViewModel.swift index e7403c2c48..d649fe844c 100644 --- a/Loop/View Models/FavoriteFoodInsightsViewModel.swift +++ b/Loop/View Models/FavoriteFoodInsightsViewModel.swift @@ -11,7 +11,6 @@ import LoopKitUI import LoopAlgorithm import os.log import Combine -import HealthKit protocol FavoriteFoodInsightsViewModelDelegate: AnyObject { func selectedFavoriteFoodLastEaten(_ favoriteFood: StoredFavoriteFood) async throws -> Date? @@ -56,7 +55,7 @@ class FavoriteFoodInsightsViewModel: ObservableObject { } var now = Date() - var preferredCarbUnit = HKUnit.gram() + var preferredCarbUnit = LoopUnit.gram lazy var carbFormatter = QuantityFormatter(for: preferredCarbUnit) lazy var absorptionTimeFormatter: DateComponentsFormatter = { let formatter = DateComponentsFormatter() diff --git a/Loop/View Models/FavoriteFoodsViewModel.swift b/Loop/View Models/FavoriteFoodsViewModel.swift index f9055c46f2..4b425ccee7 100644 --- a/Loop/View Models/FavoriteFoodsViewModel.swift +++ b/Loop/View Models/FavoriteFoodsViewModel.swift @@ -7,7 +7,7 @@ // import SwiftUI -import HealthKit +import LoopAlgorithm import LoopKit import Combine import os.log @@ -20,7 +20,7 @@ final class FavoriteFoodsViewModel: ObservableObject { @Published var isEditViewActive = false @Published var isAddViewActive = false - var preferredCarbUnit = HKUnit.gram() + var preferredCarbUnit = LoopUnit.gram lazy var carbFormatter = QuantityFormatter(for: preferredCarbUnit) lazy var absorptionTimeFormatter: DateComponentsFormatter = { let formatter = DateComponentsFormatter() diff --git a/Loop/View Models/ManualEntryDoseViewModel.swift b/Loop/View Models/ManualEntryDoseViewModel.swift index f6d1235df6..5365595d0c 100644 --- a/Loop/View Models/ManualEntryDoseViewModel.swift +++ b/Loop/View Models/ManualEntryDoseViewModel.swift @@ -7,7 +7,6 @@ // import Combine -import HealthKit import LocalAuthentication import Intents import os.log @@ -38,18 +37,18 @@ final class ManualEntryDoseViewModel: ObservableObject { @Published var glucoseValues: [GlucoseValue] = [] // stored glucose values @Published var predictedGlucoseValues: [GlucoseValue] = [] - @Published var glucoseUnit: HKUnit = .milligramsPerDeciliter + @Published var glucoseUnit: LoopUnit = .milligramsPerDeciliter @Published var chartDateInterval: DateInterval - @Published var activeCarbs: HKQuantity? - @Published var activeInsulin: HKQuantity? + @Published var activeCarbs: LoopQuantity? + @Published var activeInsulin: LoopQuantity? @Published var targetGlucoseSchedule: GlucoseRangeSchedule? @Published var preMealOverride: TemporaryScheduleOverride? private var savedPreMealOverride: TemporaryScheduleOverride? @Published var scheduleOverride: TemporaryScheduleOverride? - @Published var enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0) + @Published var enteredBolus = LoopQuantity(unit: .internationalUnit, doubleValue: 0) private var isInitiatingSaveOrBolus = false private let log = OSLog(category: "ManualEntryDoseViewModel") @@ -171,7 +170,7 @@ final class ManualEntryDoseViewModel: ObservableObject { // MARK: - View API func saveManualDose() async throws { - guard enteredBolus.doubleValue(for: .internationalUnit()) > 0 else { + guard enteredBolus.doubleValue(for: .internationalUnit) > 0 else { return } @@ -185,7 +184,7 @@ final class ManualEntryDoseViewModel: ObservableObject { } private func continueSaving() async { - let doseVolume = enteredBolus.doubleValue(for: .internationalUnit()) + let doseVolume = enteredBolus.doubleValue(for: .internationalUnit) guard doseVolume > 0 else { return } @@ -193,7 +192,7 @@ final class ManualEntryDoseViewModel: ObservableObject { await delegate?.addManuallyEnteredDose(startDate: selectedDoseDate, units: doseVolume, insulinType: selectedInsulinType) } - private lazy var bolusVolumeFormatter = QuantityFormatter(for: .internationalUnit()) + private lazy var bolusVolumeFormatter = QuantityFormatter(for: .internationalUnit) private lazy var absorptionTimeFormatter: DateComponentsFormatter = { let formatter = DateComponentsFormatter() @@ -205,7 +204,7 @@ final class ManualEntryDoseViewModel: ObservableObject { }() var enteredBolusAmountString: String { - let bolusVolume = enteredBolus.doubleValue(for: .internationalUnit()) + let bolusVolume = enteredBolus.doubleValue(for: .internationalUnit) return bolusVolumeFormatter.numberFormatter.string(from: bolusVolume) ?? String(bolusVolume) } @@ -235,7 +234,7 @@ final class ManualEntryDoseViewModel: ObservableObject { deliveryType: .bolus, startDate: selectedDoseDate, endDate: selectedDoseDate, - volume: enteredBolus.doubleValue(for: .internationalUnit()), + volume: enteredBolus.doubleValue(for: .internationalUnit), insulinModel: insulinModel ) diff --git a/Loop/View Models/SettingsViewModel.swift b/Loop/View Models/SettingsViewModel.swift index ea93e53d7d..f907427989 100644 --- a/Loop/View Models/SettingsViewModel.swift +++ b/Loop/View Models/SettingsViewModel.swift @@ -11,7 +11,6 @@ import LoopCore import LoopKit import LoopKitUI import SwiftUI -import HealthKit public class DeviceViewModel: ObservableObject { public typealias DeleteTestingDataFunc = () -> Void diff --git a/Loop/View Models/SimpleBolusViewModel.swift b/Loop/View Models/SimpleBolusViewModel.swift index 3d90042d3e..45593378d3 100644 --- a/Loop/View Models/SimpleBolusViewModel.swift +++ b/Loop/View Models/SimpleBolusViewModel.swift @@ -7,7 +7,6 @@ // import Foundation -import HealthKit import LoopKit import LoopKitUI import os.log @@ -29,11 +28,11 @@ protocol SimpleBolusViewModelDelegate: AnyObject { func insulinOnBoard(at date: Date) async -> InsulinValue? - func computeSimpleBolusRecommendation(at date: Date, mealCarbs: HKQuantity?, manualGlucose: HKQuantity?) -> BolusDosingDecision? + func computeSimpleBolusRecommendation(at date: Date, mealCarbs: LoopQuantity?, manualGlucose: LoopQuantity?) -> BolusDosingDecision? var maximumBolus: Double? { get } - var suspendThreshold: HKQuantity? { get } + var suspendThreshold: LoopQuantity? { get } } @MainActor @@ -75,7 +74,7 @@ class SimpleBolusViewModel: ObservableObject { @Published var enteredCarbString: String = "" { didSet { if let enteredCarbs = Self.carbAmountFormatter.number(from: enteredCarbString)?.doubleValue, enteredCarbs > 0 { - carbQuantity = HKQuantity(unit: .gram(), doubleValue: enteredCarbs) + carbQuantity = LoopQuantity(unit: .gram, doubleValue: enteredCarbs) } else { carbQuantity = nil } @@ -87,7 +86,7 @@ class SimpleBolusViewModel: ObservableObject { // needed to detect change in display glucose unit when returning to the app - private var cachedDisplayGlucoseUnit: HKUnit + private var cachedDisplayGlucoseUnit: LoopUnit var manualGlucoseString: String { get { @@ -121,14 +120,14 @@ class SimpleBolusViewModel: ObservableObject { } if let bolus = bolus { - guard bolus.doubleValue(for: .internationalUnit()) <= maxBolus else { + guard bolus.doubleValue(for: .internationalUnit) <= maxBolus else { activeNotice = .maxBolusExceeded return } } let isAddingCarbs: Bool - if let carbQuantity = carbQuantity, carbQuantity.doubleValue(for: .gram()) > 0 { + if let carbQuantity = carbQuantity, carbQuantity.doubleValue(for: .gram) > 0 { isAddingCarbs = true } else { isAddingCarbs = false @@ -170,7 +169,7 @@ class SimpleBolusViewModel: ObservableObject { if manualGlucoseQuantity == nil || _manualGlucoseString != displayGlucosePreference.format(manualGlucoseQuantity!, includeUnit: false) { - manualGlucoseQuantity = HKQuantity(unit: cachedDisplayGlucoseUnit, doubleValue: manualGlucoseValue) + manualGlucoseQuantity = LoopQuantity(unit: cachedDisplayGlucoseUnit, doubleValue: manualGlucoseValue) updateNotice() } } @@ -179,7 +178,7 @@ class SimpleBolusViewModel: ObservableObject { @Published var enteredBolusString: String { didSet { if let enteredBolusAmount = Self.doseAmountFormatter.number(from: enteredBolusString)?.doubleValue, enteredBolusAmount > 0 { - bolus = HKQuantity(unit: .internationalUnit(), doubleValue: enteredBolusAmount) + bolus = LoopQuantity(unit: .internationalUnit, doubleValue: enteredBolusAmount) } else { bolus = nil } @@ -187,18 +186,18 @@ class SimpleBolusViewModel: ObservableObject { } } - private var carbQuantity: HKQuantity? = nil + private var carbQuantity: LoopQuantity? = nil - private var manualGlucoseQuantity: HKQuantity? = nil { + private var manualGlucoseQuantity: LoopQuantity? = nil { didSet { updateRecommendation() } } - private var bolus: HKQuantity? = nil + private var bolus: LoopQuantity? = nil var bolusRecommended: Bool { - if let bolus = bolus, bolus.doubleValue(for: .internationalUnit()) > 0 { + if let bolus = bolus, bolus.doubleValue(for: .internationalUnit) > 0 { return true } return false @@ -206,9 +205,9 @@ class SimpleBolusViewModel: ObservableObject { let displayGlucosePreference: DisplayGlucosePreference - var displayGlucoseUnit: HKUnit { return displayGlucosePreference.unit } + var displayGlucoseUnit: LoopUnit { return displayGlucosePreference.unit } - var suspendThreshold: HKQuantity? { return delegate.suspendThreshold } + var suspendThreshold: LoopQuantity? { return delegate.suspendThreshold } private var recommendation: Double? = nil { didSet { @@ -234,7 +233,7 @@ class SimpleBolusViewModel: ObservableObject { }() private static let carbAmountFormatter: NumberFormatter = { - let quantityFormatter = QuantityFormatter(for: .gram()) + let quantityFormatter = QuantityFormatter(for: .gram) return quantityFormatter.numberFormatter }() @@ -278,13 +277,13 @@ class SimpleBolusViewModel: ObservableObject { private let delegate: SimpleBolusViewModelDelegate private let log = OSLog(category: "SimpleBolusViewModel") - private lazy var bolusVolumeFormatter = QuantityFormatter(for: .internationalUnit()) + private lazy var bolusVolumeFormatter = QuantityFormatter(for: .internationalUnit) var maximumBolusAmountString: String { guard let maxBolus = delegate.maximumBolus else { return "" } - let maxBolusQuantity = HKQuantity(unit: .internationalUnit(), doubleValue: maxBolus) + let maxBolusQuantity = LoopQuantity(unit: .internationalUnit, doubleValue: maxBolus) return bolusVolumeFormatter.string(from: maxBolusQuantity)! } @@ -342,7 +341,7 @@ class SimpleBolusViewModel: ObservableObject { let saveDate = Date() // Authenticate if needed - if let bolus = bolus, bolus.doubleValue(for: .internationalUnit()) > 0 { + if let bolus = bolus, bolus.doubleValue(for: .internationalUnit) > 0 { let message = String(format: NSLocalizedString("Authenticate to Bolus %@ Units", comment: "The message displayed during a device authentication prompt for bolus specification"), enteredBolusString) let authenticated = await withCheckedContinuation { continuation in authenticate(message) { @@ -396,7 +395,7 @@ class SimpleBolusViewModel: ObservableObject { } } - if let bolusVolume = bolus?.doubleValue(for: .internationalUnit()), bolusVolume > 0 { + if let bolusVolume = bolus?.doubleValue(for: .internationalUnit), bolusVolume > 0 { do { try await delegate.enactBolus(units: bolusVolume, activationType: .activationTypeFor(recommendedAmount: recommendation, bolusAmount: bolusVolume)) dosingDecision?.manualBolusRequested = bolusVolume diff --git a/Loop/Views/BolusEntryView.swift b/Loop/Views/BolusEntryView.swift index 7e01c87a8e..7aa7bc0f9f 100644 --- a/Loop/Views/BolusEntryView.swift +++ b/Loop/Views/BolusEntryView.swift @@ -7,7 +7,7 @@ // import Combine -import HealthKit +import LoopAlgorithm import SwiftUI import LoopKit import LoopKitUI @@ -58,7 +58,7 @@ struct BolusEntryView: View { .alert(item: self.$viewModel.activeAlert, content: self.alert(for:)) .onReceive(self.viewModel.$recommendedBolus) { recommendation in // If the recommendation changes, and the user has not edited the bolus amount, update the bolus amount - let amount = recommendation?.doubleValue(for: .internationalUnit()) ?? 0 + let amount = recommendation?.doubleValue(for: .internationalUnit) ?? 0 if !editedBolusAmount { var newEnteredBolusString: String if amount == 0 { @@ -136,7 +136,7 @@ struct BolusEntryView: View { LabeledQuantity( label: Text("Active Carbs", comment: "Title describing quantity of still-absorbing carbohydrates"), quantity: viewModel.activeCarbs, - unit: .gram() + unit: .gram ) } @@ -145,7 +145,7 @@ struct BolusEntryView: View { LabeledQuantity( label: Text("Active Insulin", comment: "Title describing quantity of still-absorbing insulin"), quantity: viewModel.activeInsulin, - unit: .internationalUnit(), + unit: .internationalUnit, maxFractionDigits: 2 ) } @@ -264,7 +264,7 @@ struct BolusEntryView: View { } private var bolusUnitsLabel: some View { - Text(QuantityFormatter(for: .internationalUnit()).localizedUnitStringWithPlurality()) + Text(QuantityFormatter(for: .internationalUnit).localizedUnitStringWithPlurality()) .foregroundColor(Color(.secondaryLabel)) } @@ -431,8 +431,8 @@ struct BolusEntryView: View { struct LabeledQuantity: View { var label: Text - var quantity: HKQuantity? - var unit: HKUnit + var quantity: LoopQuantity? + var unit: LoopUnit var maxFractionDigits: Int? var body: some View { diff --git a/Loop/Views/BolusProgressTableViewCell.swift b/Loop/Views/BolusProgressTableViewCell.swift index 3ac0af962b..3fa7149648 100644 --- a/Loop/Views/BolusProgressTableViewCell.swift +++ b/Loop/Views/BolusProgressTableViewCell.swift @@ -9,7 +9,7 @@ import Foundation import LoopKit import LoopUI -import HealthKit +import LoopAlgorithm import MKRingProgressView @@ -46,7 +46,7 @@ public class BolusProgressTableViewCell: UITableViewCell { } lazy var insulinFormatter: QuantityFormatter = { - let formatter = QuantityFormatter(for: .internationalUnit()) + let formatter = QuantityFormatter(for: .internationalUnit) formatter.numberFormatter.minimumFractionDigits = 2 return formatter }() @@ -99,11 +99,11 @@ public class BolusProgressTableViewCell: UITableViewCell { activityIndicator.isHidden = true tapToStopLabel.isHidden = false - let totalUnitsQuantity = HKQuantity(unit: .internationalUnit(), doubleValue: totalVolume) + let totalUnitsQuantity = LoopQuantity(unit: .internationalUnit, doubleValue: totalVolume) let totalUnitsString = insulinFormatter.string(from: totalUnitsQuantity) ?? "" if let delivered { - let deliveredUnitsQuantity = HKQuantity(unit: .internationalUnit(), doubleValue: delivered) + let deliveredUnitsQuantity = LoopQuantity(unit: .internationalUnit, doubleValue: delivered) let deliveredUnitsString = insulinFormatter.string(from: deliveredUnitsQuantity, includeUnit: false) ?? "" progressLabel.text = String(format: NSLocalizedString("Bolused %1$@ of %2$@", comment: "The format string for bolus progress. (1: delivered volume)(2: total volume)"), deliveredUnitsString, totalUnitsString) @@ -127,10 +127,10 @@ public class BolusProgressTableViewCell: UITableViewCell { activityIndicator.isHidden = true tapToStopLabel.isHidden = true - let totalUnitsQuantity = HKQuantity(unit: .internationalUnit(), doubleValue: totalVolume) + let totalUnitsQuantity = LoopQuantity(unit: .internationalUnit, doubleValue: totalVolume) let totalUnitsString = insulinFormatter.string(from: totalUnitsQuantity) ?? "" - let deliveredUnitsQuantity = HKQuantity(unit: .internationalUnit(), doubleValue: delivered) + let deliveredUnitsQuantity = LoopQuantity(unit: .internationalUnit, doubleValue: delivered) let deliveredUnitsString = insulinFormatter.string(from: deliveredUnitsQuantity, includeUnit: false) ?? "" progressLabel.text = String(format: NSLocalizedString("Bolus Canceled: Delivered %1$@ of %2$@", comment: "The title of the cell indicating a bolus has been canceled. (1: delivered volume)(2: total volume)"), deliveredUnitsString, totalUnitsString) diff --git a/Loop/Views/CarbEntryView.swift b/Loop/Views/CarbEntryView.swift index c5faffa1b4..649d645599 100644 --- a/Loop/Views/CarbEntryView.swift +++ b/Loop/Views/CarbEntryView.swift @@ -9,7 +9,6 @@ import SwiftUI import LoopKit import LoopKitUI -import HealthKit struct CarbEntryView: View, HorizontalSizeClassOverride { @EnvironmentObject private var displayGlucosePreference: DisplayGlucosePreference diff --git a/Loop/Views/Charts/CarbEffectChartView.swift b/Loop/Views/Charts/CarbEffectChartView.swift index 8a6f4eda1f..9a98113535 100644 --- a/Loop/Views/Charts/CarbEffectChartView.swift +++ b/Loop/Views/Charts/CarbEffectChartView.swift @@ -7,14 +7,13 @@ // import SwiftUI -import HealthKit import LoopKit import LoopKitUI import LoopAlgorithm struct CarbEffectChartView: View { let chartManager: ChartsManager - var glucoseUnit: HKUnit + var glucoseUnit: LoopUnit var carbAbsorptionReview: CarbAbsorptionReview? var dateInterval: DateInterval diff --git a/Loop/Views/Charts/GlucoseCarbChartView.swift b/Loop/Views/Charts/GlucoseCarbChartView.swift index 7b6ed91b37..70f1f5c4ad 100644 --- a/Loop/Views/Charts/GlucoseCarbChartView.swift +++ b/Loop/Views/Charts/GlucoseCarbChartView.swift @@ -7,14 +7,13 @@ // import SwiftUI -import HealthKit import LoopKit import LoopKitUI import LoopAlgorithm struct GlucoseCarbChartView: View { let chartManager: ChartsManager - var glucoseUnit: HKUnit + var glucoseUnit: LoopUnit var glucoseValues: [GlucoseValue] var carbEntries: [StoredCarbEntry] var dateInterval: DateInterval diff --git a/Loop/Views/Charts/PredictedGlucoseChartView.swift b/Loop/Views/Charts/PredictedGlucoseChartView.swift index 2d6725cbed..e223a2c3cc 100644 --- a/Loop/Views/Charts/PredictedGlucoseChartView.swift +++ b/Loop/Views/Charts/PredictedGlucoseChartView.swift @@ -6,7 +6,6 @@ // Copyright © 2020 LoopKit Authors. All rights reserved. // -import HealthKit import SwiftUI import LoopKit import LoopKitUI @@ -14,7 +13,7 @@ import LoopAlgorithm struct PredictedGlucoseChartView: View { let chartManager: ChartsManager - var glucoseUnit: HKUnit + var glucoseUnit: LoopUnit var glucoseValues: [GlucoseValue] var predictedGlucoseValues: [GlucoseValue] = [] var targetGlucoseSchedule: GlucoseRangeSchedule? = nil diff --git a/Loop/Views/Favorite Foods/FavoriteFoodDetailView.swift b/Loop/Views/Favorite Foods/FavoriteFoodDetailView.swift index 10f7625d68..160adb3514 100644 --- a/Loop/Views/Favorite Foods/FavoriteFoodDetailView.swift +++ b/Loop/Views/Favorite Foods/FavoriteFoodDetailView.swift @@ -9,7 +9,6 @@ import SwiftUI import LoopKit import LoopKitUI -import HealthKit public struct FavoriteFoodDetailView: View { @ObservedObject var viewModel: FavoriteFoodsViewModel diff --git a/Loop/Views/Favorite Foods/FavoriteFoodInsightsChartsView.swift b/Loop/Views/Favorite Foods/FavoriteFoodInsightsChartsView.swift index 71205485f7..8a67b7c519 100644 --- a/Loop/Views/Favorite Foods/FavoriteFoodInsightsChartsView.swift +++ b/Loop/Views/Favorite Foods/FavoriteFoodInsightsChartsView.swift @@ -10,7 +10,6 @@ import SwiftUI import LoopKit import LoopKitUI import LoopAlgorithm -import HealthKit import Combine struct FavoriteFoodsInsightsChartsView: View { diff --git a/Loop/Views/ManualEntryDoseView.swift b/Loop/Views/ManualEntryDoseView.swift index ea70d235dc..7882827a7b 100644 --- a/Loop/Views/ManualEntryDoseView.swift +++ b/Loop/Views/ManualEntryDoseView.swift @@ -7,7 +7,7 @@ // import Combine -import HealthKit +import LoopAlgorithm import SwiftUI import LoopKit import LoopKitUI @@ -103,7 +103,7 @@ struct ManualEntryDoseView: View { LabeledQuantity( label: Text("Active Carbs", comment: "Title describing quantity of still-absorbing carbohydrates"), quantity: viewModel.activeCarbs, - unit: .gram() + unit: .gram ) } @@ -112,7 +112,7 @@ struct ManualEntryDoseView: View { LabeledQuantity( label: Text("Active Insulin", comment: "Title describing quantity of still-absorbing insulin"), quantity: viewModel.activeInsulin, - unit: .internationalUnit(), + unit: .internationalUnit, maxFractionDigits: 2 ) } @@ -157,7 +157,7 @@ struct ManualEntryDoseView: View { } private static let doseAmountFormatter: NumberFormatter = { - let quantityFormatter = QuantityFormatter(for: .internationalUnit()) + let quantityFormatter = QuantityFormatter(for: .internationalUnit) return quantityFormatter.numberFormatter }() @@ -207,7 +207,7 @@ struct ManualEntryDoseView: View { } private var bolusUnitsLabel: some View { - Text(QuantityFormatter(for: .internationalUnit()).localizedUnitStringWithPlurality()) + Text(QuantityFormatter(for: .internationalUnit).localizedUnitStringWithPlurality()) .foregroundColor(Color(.secondaryLabel)) } @@ -215,7 +215,7 @@ struct ManualEntryDoseView: View { Binding( get: { self.enteredBolusString }, set: { newValue in - self.viewModel.enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: Self.doseAmountFormatter.number(from: newValue)?.doubleValue ?? 0) + self.viewModel.enteredBolus = LoopQuantity(unit: .internationalUnit, doubleValue: Self.doseAmountFormatter.number(from: newValue)?.doubleValue ?? 0) self.enteredBolusString = newValue } ) diff --git a/Loop/Views/ManualGlucoseEntryRow.swift b/Loop/Views/ManualGlucoseEntryRow.swift index 33bcecfb1b..f719bd5c1a 100644 --- a/Loop/Views/ManualGlucoseEntryRow.swift +++ b/Loop/Views/ManualGlucoseEntryRow.swift @@ -8,17 +8,17 @@ import Foundation import SwiftUI +import LoopAlgorithm import LoopKit import LoopKitUI import Combine -import HealthKit struct ManualGlucoseEntryRow: View { @EnvironmentObject private var displayGlucosePreference: DisplayGlucosePreference @State private var valueText = "" - @Binding var quantity: HKQuantity? + @Binding var quantity: LoopQuantity? @State private var isManualGlucoseEntryRowVisible = false @@ -42,7 +42,7 @@ struct ManualGlucoseEntryRow: View { ) .onChange(of: valueText, perform: { value in if let manualGlucoseValue = displayGlucosePreference.formatter.numberFormatter.number(from: valueText)?.doubleValue { - quantity = HKQuantity(unit: displayGlucosePreference.unit, doubleValue: manualGlucoseValue) + quantity = LoopQuantity(unit: displayGlucosePreference.unit, doubleValue: manualGlucoseValue) } else { quantity = nil } diff --git a/Loop/Views/SettingsView.swift b/Loop/Views/SettingsView.swift index a8fb09a3f8..c47b5f62d6 100644 --- a/Loop/Views/SettingsView.swift +++ b/Loop/Views/SettingsView.swift @@ -10,7 +10,6 @@ import LoopKit import LoopKitUI import MockKit import SwiftUI -import HealthKit import LoopUI diff --git a/Loop/Views/SimpleBolusView.swift b/Loop/Views/SimpleBolusView.swift index 903caf4c8c..de4cec2a07 100644 --- a/Loop/Views/SimpleBolusView.swift +++ b/Loop/Views/SimpleBolusView.swift @@ -9,7 +9,6 @@ import SwiftUI import LoopKit import LoopKitUI -import HealthKit import LoopCore import LoopAlgorithm @@ -68,7 +67,7 @@ struct SimpleBolusView: View { .alert(item: self.$viewModel.activeAlert, content: self.alert(for:)) } - private func formatGlucose(_ quantity: HKQuantity) -> String { + private func formatGlucose(_ quantity: LoopQuantity) -> String { return displayGlucosePreference.format(quantity) } @@ -211,7 +210,7 @@ struct SimpleBolusView: View { } private var carbUnitsLabel: some View { - Text(QuantityFormatter(for: .gram()).localizedUnitStringWithPlurality()) + Text(QuantityFormatter(for: .gram).localizedUnitStringWithPlurality()) .foregroundColor(Color(.secondaryLabel)) } @@ -222,7 +221,7 @@ struct SimpleBolusView: View { } private var bolusUnitsLabel: Text { - Text(QuantityFormatter(for: .internationalUnit()).localizedUnitStringWithPlurality()) + Text(QuantityFormatter(for: .internationalUnit).localizedUnitStringWithPlurality()) .foregroundColor(Color(.secondaryLabel)) } @@ -334,7 +333,7 @@ struct SimpleBolusView: View { title: Text("Recommended Bolus Exceeds Maximum Bolus", comment: "Title for bolus screen warning when recommended bolus exceeds max bolus"), caption: Text(String(format: NSLocalizedString("Your recommended bolus exceeds your maximum bolus amount of %1$@.", comment: "Warning for simple bolus when recommended bolus exceeds max bolus. (1: maximum bolus)"), viewModel.maximumBolusAmountString ))) case .carbohydrateEntryTooLarge: - let maximumCarbohydrateString = QuantityFormatter(for: .gram()).string(from: LoopConstants.maxCarbEntryQuantity)! + let maximumCarbohydrateString = QuantityFormatter(for: .gram).string(from: LoopConstants.maxCarbEntryQuantity)! return WarningView( title: Text("Carbohydrate Entry Too Large", comment: "Title for bolus screen warning when carbohydrate entry is too large"), caption: Text(String(format: NSLocalizedString("The maximum amount allowed is %1$@.", comment: "Warning for simple bolus when carbohydrate entry is too large. (1: maximum carbohydrate entry)"), maximumCarbohydrateString))) @@ -383,7 +382,7 @@ struct SimpleBolusCalculatorView_Previews: PreviewProvider { completion(.success(InsulinValue(startDate: date, value: 2.0))) } - func computeSimpleBolusRecommendation(at date: Date, mealCarbs: HKQuantity?, manualGlucose: HKQuantity?) -> BolusDosingDecision? { + func computeSimpleBolusRecommendation(at date: Date, mealCarbs: LoopQuantity?, manualGlucose: LoopQuantity?) -> BolusDosingDecision? { var decision = BolusDosingDecision(for: .simpleBolus) decision.manualBolusRecommendation = ManualBolusRecommendationWithDate(recommendation: ManualBolusRecommendation(amount: 3), date: Date()) @@ -401,8 +400,8 @@ struct SimpleBolusCalculatorView_Previews: PreviewProvider { return 6 } - var suspendThreshold: HKQuantity? { - return HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 75) + var suspendThreshold: LoopQuantity? { + return LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 75) } } diff --git a/LoopCore/HKUnit.swift b/LoopCore/HKUnit.swift index 7f9a5e3009..da6d179e84 100644 --- a/LoopCore/HKUnit.swift +++ b/LoopCore/HKUnit.swift @@ -17,16 +17,4 @@ extension HKUnit { public static let millimolesPerLiter: HKUnit = { return HKUnit.moleUnit(with: .milli, molarMass: HKUnitMolarMassBloodGlucose).unitDivided(by: .liter()) }() - - public static let milligramsPerDeciliterPerMinute: HKUnit = { - return HKUnit.milligramsPerDeciliter.unitDivided(by: .minute()) - }() - - public static let millimolesPerLiterPerMinute: HKUnit = { - return HKUnit.millimolesPerLiter.unitDivided(by: .minute()) - }() - - public static let internationalUnitsPerHour: HKUnit = { - return HKUnit.internationalUnit().unitDivided(by: .hour()) - }() } diff --git a/LoopCore/LoopSettings.swift b/LoopCore/LoopSettings.swift index b93aecf837..ea68ce4ad5 100644 --- a/LoopCore/LoopSettings.swift +++ b/LoopCore/LoopSettings.swift @@ -5,7 +5,6 @@ // Copyright © 2017 LoopKit Authors. All rights reserved. // -import HealthKit import LoopKit import LoopAlgorithm @@ -31,9 +30,9 @@ public struct LoopSettings: Equatable { public var carbRatioSchedule: CarbRatioSchedule? - public var preMealTargetRange: ClosedRange? + public var preMealTargetRange: ClosedRange? - public var legacyWorkoutTargetRange: ClosedRange? + public var legacyWorkoutTargetRange: ClosedRange? public var overridePresets: [TemporaryScheduleOverridePreset] = [] @@ -47,7 +46,7 @@ public struct LoopSettings: Equatable { public var defaultRapidActingModel: ExponentialInsulinModelPreset? - public var glucoseUnit: HKUnit? { + public var glucoseUnit: LoopUnit? { return glucoseTargetRangeSchedule?.unit } @@ -57,8 +56,8 @@ public struct LoopSettings: Equatable { insulinSensitivitySchedule: InsulinSensitivitySchedule? = nil, basalRateSchedule: BasalRateSchedule? = nil, carbRatioSchedule: CarbRatioSchedule? = nil, - preMealTargetRange: ClosedRange? = nil, - legacyWorkoutTargetRange: ClosedRange? = nil, + preMealTargetRange: ClosedRange? = nil, + legacyWorkoutTargetRange: ClosedRange? = nil, overridePresets: [TemporaryScheduleOverridePreset]? = nil, maximumBasalRatePerHour: Double? = nil, maximumBolus: Double? = nil, @@ -85,7 +84,7 @@ public struct LoopSettings: Equatable { extension LoopSettings: RawRepresentable { public typealias RawValue = [String: Any] private static let version = 1 - fileprivate static let codingGlucoseUnit = HKUnit.milligramsPerDeciliter + fileprivate static let codingGlucoseUnit = LoopUnit.milligramsPerDeciliter public init?(rawValue: RawValue) { guard diff --git a/LoopCore/NSUserDefaults.swift b/LoopCore/NSUserDefaults.swift index c4a2cbe172..beb9446061 100644 --- a/LoopCore/NSUserDefaults.swift +++ b/LoopCore/NSUserDefaults.swift @@ -8,7 +8,6 @@ import Foundation import LoopKit -import HealthKit import LoopAlgorithm extension UserDefaults { diff --git a/LoopTests/Managers/CGMStalenessMonitorTests.swift b/LoopTests/Managers/CGMStalenessMonitorTests.swift index 9da44f7f00..5971d75daa 100644 --- a/LoopTests/Managers/CGMStalenessMonitorTests.swift +++ b/LoopTests/Managers/CGMStalenessMonitorTests.swift @@ -9,7 +9,7 @@ import XCTest import Foundation import LoopKit -import HealthKit +import LoopAlgorithm @testable import Loop class CGMStalenessMonitorTests: XCTestCase { @@ -18,11 +18,11 @@ class CGMStalenessMonitorTests: XCTestCase { private var fetchExpectation: XCTestExpectation? private var storedGlucoseSample: StoredGlucoseSample { - return StoredGlucoseSample(uuid: UUID(), provenanceIdentifier: UUID().uuidString, syncIdentifier: "syncIdentifier", syncVersion: 1, startDate: Date().addingTimeInterval(-.minutes(5)), quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 120), condition: nil, trend: .flat, trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: 0.0), isDisplayOnly: false, wasUserEntered: false, device: nil, healthKitEligibleDate: nil) + return StoredGlucoseSample(uuid: UUID(), provenanceIdentifier: UUID().uuidString, syncIdentifier: "syncIdentifier", syncVersion: 1, startDate: Date().addingTimeInterval(-.minutes(5)), quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 120), condition: nil, trend: .flat, trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: 0.0), isDisplayOnly: false, wasUserEntered: false, device: nil, healthKitEligibleDate: nil) } private var newGlucoseSample: NewGlucoseSample { - return NewGlucoseSample(date: Date().addingTimeInterval(-.minutes(1)), quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 120), condition: nil, trend: .flat, trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: 0.0), isDisplayOnly: false, wasUserEntered: false, syncIdentifier: "syncIdentifier") + return NewGlucoseSample(date: Date().addingTimeInterval(-.minutes(1)), quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 120), condition: nil, trend: .flat, trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: 0.0), isDisplayOnly: false, wasUserEntered: false, syncIdentifier: "syncIdentifier") } func testInitialValue() { diff --git a/LoopTests/Managers/DeviceDataManagerTests.swift b/LoopTests/Managers/DeviceDataManagerTests.swift index c72a955cab..6f4976e592 100644 --- a/LoopTests/Managers/DeviceDataManagerTests.swift +++ b/LoopTests/Managers/DeviceDataManagerTests.swift @@ -8,6 +8,7 @@ import XCTest import HealthKit +import LoopAlgorithm import LoopKit import LoopKitUI import LoopCore @@ -120,7 +121,7 @@ final class DeviceDataManagerTests: XCTestCase { pumpManager.status.basalDeliveryState = .tempBasal(dose) let newLimits = DeliveryLimits( - maximumBasalRate: HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 5), + maximumBasalRate: LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: 5), maximumBolus: nil ) let limits = try await deviceDataManager.syncDeliveryLimits(deliveryLimits: newLimits) @@ -141,7 +142,7 @@ final class DeviceDataManagerTests: XCTestCase { pumpManager.status.basalDeliveryState = .tempBasal(dose) let newLimits = DeliveryLimits( - maximumBasalRate: HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 3), + maximumBasalRate: LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: 3), maximumBolus: nil ) let limits = try await deviceDataManager.syncDeliveryLimits(deliveryLimits: newLimits) @@ -205,6 +206,6 @@ extension DeviceDataManagerTests: DisplayGlucoseUnitBroadcaster { func removeDisplayGlucoseUnitObserver(_ observer: LoopKitUI.DisplayGlucoseUnitObserver) { } - func notifyObserversOfDisplayGlucoseUnitChange(to displayGlucoseUnit: HKUnit) { + func notifyObserversOfDisplayGlucoseUnitChange(to displayGlucoseUnit: LoopUnit) { } } diff --git a/LoopTests/Managers/DoseEnactorTests.swift b/LoopTests/Managers/DoseEnactorTests.swift index 08e5f4d9b5..445cd9aa7c 100644 --- a/LoopTests/Managers/DoseEnactorTests.swift +++ b/LoopTests/Managers/DoseEnactorTests.swift @@ -9,7 +9,6 @@ import XCTest import Foundation import LoopKit -import HealthKit import LoopAlgorithm @testable import Loop diff --git a/LoopTests/Managers/LoopDataManagerTests.swift b/LoopTests/Managers/LoopDataManagerTests.swift index 45d7612b7a..f833a80934 100644 --- a/LoopTests/Managers/LoopDataManagerTests.swift +++ b/LoopTests/Managers/LoopDataManagerTests.swift @@ -7,9 +7,7 @@ // import XCTest -import HealthKit import LoopKit -import HealthKit import LoopAlgorithm @testable import LoopCore @@ -50,13 +48,13 @@ class LoopDataManagerTests: XCTestCase { let defaultAccuracy = 1.0 / 40.0 var suspendThreshold: GlucoseThreshold { - return GlucoseThreshold(unit: HKUnit.milligramsPerDeciliter, value: 75) + return GlucoseThreshold(unit: .milligramsPerDeciliter, value: 75) } var adultExponentialInsulinModel: InsulinModel = ExponentialInsulinModel(actionDuration: 21600.0, peakActivityTime: 4500.0) var glucoseTargetRangeSchedule: GlucoseRangeSchedule { - return GlucoseRangeSchedule(unit: HKUnit.milligramsPerDeciliter, dailyItems: [ + return GlucoseRangeSchedule(unit: .milligramsPerDeciliter, dailyItems: [ RepeatingScheduleValue(startTime: TimeInterval(0), value: DoubleRange(minValue: 100, maxValue: 110)), RepeatingScheduleValue(startTime: TimeInterval(28800), value: DoubleRange(minValue: 90, maxValue: 100)), RepeatingScheduleValue(startTime: TimeInterval(75600), value: DoubleRange(minValue: 100, maxValue: 110)) @@ -90,7 +88,7 @@ class LoopDataManagerTests: XCTestCase { timeZone: .utcTimeZone )! let carbRatioSchedule = CarbRatioSchedule( - unit: .gram(), + unit: .gram, dailyItems: [ RepeatingScheduleValue(startTime: 0.0, value: 10.0), ], @@ -151,7 +149,7 @@ class LoopDataManagerTests: XCTestCase { let localDateFormatter = ISO8601DateFormatter.localTimeDate() return fixture.map { - return GlucoseEffect(startDate: localDateFormatter.date(from: $0["date"] as! String)!, quantity: HKQuantity(unit: HKUnit(from: $0["unit"] as! String), doubleValue:$0["amount"] as! Double)) + return GlucoseEffect(startDate: localDateFormatter.date(from: $0["date"] as! String)!, quantity: LoopQuantity(unit: LoopUnit(from: $0["unit"] as! String), doubleValue:$0["amount"] as! Double)) } } @@ -184,7 +182,7 @@ class LoopDataManagerTests: XCTestCase { timeZone: .utcTimeZone )! let carbRatioSchedule = CarbRatioSchedule( - unit: .gram(), + unit: .gram, dailyItems: [ RepeatingScheduleValue(startTime: 0.0, value: predictionInput.carbRatio.first!.value) ], @@ -475,13 +473,13 @@ extension LoopDataManagerTests { } } -extension HKQuantity { - static func glucose(value: Double) -> HKQuantity { +extension LoopQuantity { + static func glucose(value: Double) -> LoopQuantity { return .init(unit: .milligramsPerDeciliter, doubleValue: value) } - static func carbs(value: Double) -> HKQuantity { - return .init(unit: .gram(), doubleValue: value) + static func carbs(value: Double) -> LoopQuantity { + return .init(unit: .gram, doubleValue: value) } } diff --git a/LoopTests/Managers/MealDetectionManagerTests.swift b/LoopTests/Managers/MealDetectionManagerTests.swift index 7acfe1b660..202459cd2f 100644 --- a/LoopTests/Managers/MealDetectionManagerTests.swift +++ b/LoopTests/Managers/MealDetectionManagerTests.swift @@ -7,7 +7,6 @@ // import XCTest -import HealthKit import LoopCore import LoopKit import LoopAlgorithm @@ -20,10 +19,10 @@ fileprivate class MockGlucoseSample: GlucoseSampleValue { let isDisplayOnly: Bool let wasUserEntered: Bool let condition: GlucoseCondition? = nil - let trendRate: HKQuantity? = nil + let trendRate: LoopQuantity? = nil var trend: LoopKit.GlucoseTrend? var syncIdentifier: String? - let quantity: HKQuantity = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 100) + let quantity: LoopQuantity = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 100) let startDate: Date init(startDate: Date, isDisplayOnly: Bool = false, wasUserEntered: Bool = false) { @@ -112,33 +111,33 @@ extension MissedMealTestType { switch self { case .missedMealWithCOB: return [ - NewCarbEntry(quantity: HKQuantity(unit: .gram(), doubleValue: 30), + NewCarbEntry(quantity: LoopQuantity(unit: .gram, doubleValue: 30), startDate: Self.dateFormatter.date(from: "2022-10-19T15:41:36")!, foodType: nil, absorptionTime: nil), - NewCarbEntry(quantity: HKQuantity(unit: .gram(), doubleValue: 10), + NewCarbEntry(quantity: LoopQuantity(unit: .gram, doubleValue: 10), startDate: Self.dateFormatter.date(from: "2022-10-19T17:36:58")!, foodType: nil, absorptionTime: nil) ] case .noMealWithCOB: return [ - NewCarbEntry(quantity: HKQuantity(unit: .gram(), doubleValue: 30), + NewCarbEntry(quantity: LoopQuantity(unit: .gram, doubleValue: 30), startDate: Self.dateFormatter.date(from: "2022-10-17T22:40:00")!, foodType: nil, absorptionTime: nil) ] case .manyMeals: return [ - NewCarbEntry(quantity: HKQuantity(unit: .gram(), doubleValue: 30), + NewCarbEntry(quantity: LoopQuantity(unit: .gram, doubleValue: 30), startDate: Self.dateFormatter.date(from: "2022-10-19T15:41:36")!, foodType: nil, absorptionTime: nil), - NewCarbEntry(quantity: HKQuantity(unit: .gram(), doubleValue: 10), + NewCarbEntry(quantity: LoopQuantity(unit: .gram, doubleValue: 10), startDate: Self.dateFormatter.date(from: "2022-10-19T17:36:58")!, foodType: nil, absorptionTime: nil), - NewCarbEntry(quantity: HKQuantity(unit: .gram(), doubleValue: 40), + NewCarbEntry(quantity: LoopQuantity(unit: .gram, doubleValue: 40), startDate: Self.dateFormatter.date(from: "2022-10-19T19:11:43")!, foodType: nil, absorptionTime: nil) @@ -150,7 +149,7 @@ extension MissedMealTestType { var carbSchedule: CarbRatioSchedule { CarbRatioSchedule( - unit: .gram(), + unit: .gram, dailyItems: [ RepeatingScheduleValue(startTime: 0.0, value: 15.0), ], @@ -163,16 +162,16 @@ extension MissedMealTestType { switch self { case .mmolUser: return InsulinSensitivitySchedule( - unit: HKUnit.millimolesPerLiter, + unit: LoopUnit.millimolesPerLiter, dailyItems: [ RepeatingScheduleValue(startTime: 0.0, - value: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: value).doubleValue(for: .millimolesPerLiter)) + value: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: value).doubleValue(for: .millimolesPerLiter)) ], timeZone: .utcTimeZone )! default: return InsulinSensitivitySchedule( - unit: HKUnit.milligramsPerDeciliter, + unit: .milligramsPerDeciliter, dailyItems: [ RepeatingScheduleValue(startTime: 0.0, value: value) ], @@ -227,7 +226,7 @@ class MealDetectionManagerTests: XCTestCase { sensitivity: testType.insulinSensitivitySchedule.quantitiesBetween(start: historyStart, end: date), carbRatio: testType.carbSchedule.between(start: historyStart, end: date), target: glucoseTarget!.quantityBetween(start: historyStart, end: date), - suspendThreshold: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 65), + suspendThreshold: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 65), maxBolus: maximumBolus!, maxBasalRate: maximumBasalRatePerHour, useIntegralRetrospectiveCorrection: false, @@ -287,7 +286,7 @@ class MealDetectionManagerTests: XCTestCase { return fixture.map { GlucoseEffectVelocity(startDate: dateFormatter.date(from: $0["startDate"] as! String)!, endDate: dateFormatter.date(from: $0["endDate"] as! String)!, - quantity: HKQuantity(unit: HKUnit(from: $0["unit"] as! String), + quantity: LoopQuantity(unit: LoopUnit(from: $0["unit"] as! String), doubleValue:$0["value"] as! Double)) } } diff --git a/LoopTests/Mock Stores/MockCarbStore.swift b/LoopTests/Mock Stores/MockCarbStore.swift index df0f7d8b21..cce5401699 100644 --- a/LoopTests/Mock Stores/MockCarbStore.swift +++ b/LoopTests/Mock Stores/MockCarbStore.swift @@ -6,7 +6,6 @@ // Copyright © 2020 LoopKit Authors. All rights reserved. // -import HealthKit import LoopKit import LoopCore @testable import Loop diff --git a/LoopTests/Mock Stores/MockGlucoseStore.swift b/LoopTests/Mock Stores/MockGlucoseStore.swift index ea6c3f118d..eb4c488841 100644 --- a/LoopTests/Mock Stores/MockGlucoseStore.swift +++ b/LoopTests/Mock Stores/MockGlucoseStore.swift @@ -6,7 +6,6 @@ // Copyright © 2020 LoopKit Authors. All rights reserved. // -import HealthKit import LoopKit import LoopAlgorithm @testable import Loop diff --git a/LoopTests/Mocks/MockSettingsProvider.swift b/LoopTests/Mocks/MockSettingsProvider.swift index 823f0901f8..c73041511c 100644 --- a/LoopTests/Mocks/MockSettingsProvider.swift +++ b/LoopTests/Mocks/MockSettingsProvider.swift @@ -8,7 +8,6 @@ import Foundation import LoopKit -import HealthKit import LoopAlgorithm @testable import Loop @@ -23,13 +22,13 @@ class MockSettingsProvider: SettingsProvider { return carbRatioHistory ?? settings.carbRatioSchedule?.between(start: startDate, end: endDate) ?? [] } - var insulinSensitivityHistory: [AbsoluteScheduleValue]? - func getInsulinSensitivityHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue] { + var insulinSensitivityHistory: [AbsoluteScheduleValue]? + func getInsulinSensitivityHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue] { return insulinSensitivityHistory ?? settings.insulinSensitivitySchedule?.quantitiesBetween(start: startDate, end: endDate) ?? [] } - var targetRangeHistory: [AbsoluteScheduleValue>]? - func getTargetRangeHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue>] { + var targetRangeHistory: [AbsoluteScheduleValue>]? + func getTargetRangeHistory(startDate: Date, endDate: Date) async throws -> [AbsoluteScheduleValue>] { return targetRangeHistory ?? settings.glucoseTargetRangeSchedule?.quantityBetween(start: startDate, end: endDate) ?? [] } diff --git a/LoopTests/Models/SetBolusUserInfoTests.swift b/LoopTests/Models/SetBolusUserInfoTests.swift index a486abff15..2dda80dc9d 100644 --- a/LoopTests/Models/SetBolusUserInfoTests.swift +++ b/LoopTests/Models/SetBolusUserInfoTests.swift @@ -7,7 +7,7 @@ // import XCTest -import HealthKit +import LoopAlgorithm import LoopKit @testable import Loop @@ -16,7 +16,7 @@ class SetBolusUserInfoTests: XCTestCase { private var startDate = dateFormatter.date(from: "2020-05-14T22:45:00Z")! private var contextDate = dateFormatter.date(from: "2020-05-14T22:38:14Z")! private var carbEntry = NewCarbEntry(date: dateFormatter.date(from: "2020-05-14T22:39:34Z")!, - quantity: HKQuantity(unit: .gram(), doubleValue: 17), + quantity: LoopQuantity(unit: .gram, doubleValue: 17), startDate: dateFormatter.date(from: "2020-05-14T22:00:00Z")!, foodType: "Pizza", absorptionTime: .hours(5)) @@ -99,7 +99,7 @@ class SetBolusUserInfoTests: XCTestCase { XCTAssertEqual(rawValue["at"] as? BolusActivationType.RawValue, activationType.rawValue) let carbEntryRawValue = rawValue["ce"] as? NewCarbEntry.RawValue XCTAssertEqual(carbEntryRawValue?["date"] as? Date, carbEntry.date) - XCTAssertEqual(carbEntryRawValue?["grams"] as? Double, carbEntry.quantity.doubleValue(for: .gram())) + XCTAssertEqual(carbEntryRawValue?["grams"] as? Double, carbEntry.quantity.doubleValue(for: .gram)) XCTAssertEqual(carbEntryRawValue?["startDate"] as? Date, carbEntry.startDate) XCTAssertEqual(carbEntryRawValue?["foodType"] as? String, carbEntry.foodType) XCTAssertEqual(carbEntryRawValue?["absorptionTime"] as? TimeInterval, carbEntry.absorptionTime) diff --git a/LoopTests/Models/SimpleBolusCalculatorTests.swift b/LoopTests/Models/SimpleBolusCalculatorTests.swift index 069cb54368..e143bfea83 100644 --- a/LoopTests/Models/SimpleBolusCalculatorTests.swift +++ b/LoopTests/Models/SimpleBolusCalculatorTests.swift @@ -7,9 +7,8 @@ // import Foundation - import XCTest -import HealthKit +import LoopAlgorithm import LoopKit @testable import Loop @@ -22,128 +21,128 @@ class SimpleBolusCalculatorTests: XCTestCase { RepeatingScheduleValue(startTime: 0, value: DoubleRange(minValue: 100.0, maxValue: 110.0)) ])! - let carbRatioSchedule = CarbRatioSchedule(unit: .gram(), dailyItems: [RepeatingScheduleValue(startTime: 0, value: 10)])! + let carbRatioSchedule = CarbRatioSchedule(unit: .gram, dailyItems: [RepeatingScheduleValue(startTime: 0, value: 10)])! let sensitivitySchedule = InsulinSensitivitySchedule(unit: .milligramsPerDeciliter, dailyItems: [RepeatingScheduleValue(startTime: .hours(0), value: 80)])! func testMealRecommendation() { let recommendation = SimpleBolusCalculator.recommendedInsulin( - mealCarbs: HKQuantity(unit: .gram(), doubleValue: 40), + mealCarbs: LoopQuantity(unit: .gram, doubleValue: 40), manualGlucose: nil, - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 0), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 0), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(4.0, recommendation.doubleValue(for: .internationalUnit())) + XCTAssertEqual(4.0, recommendation.doubleValue(for: .internationalUnit)) } func testCorrectionRecommendation() { let recommendation = SimpleBolusCalculator.recommendedInsulin( mealCarbs: nil, - manualGlucose: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 180), - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 0), + manualGlucose: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 180), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 0), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(0.94, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(0.94, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } func testCorrectionRecommendationWithIOB() { let recommendation = SimpleBolusCalculator.recommendedInsulin( mealCarbs: nil, - manualGlucose: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 180), - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 10), + manualGlucose: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 180), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 10), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(0.0, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(0.0, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } func testCorrectionRecommendationWithNegativeIOB() { let recommendation = SimpleBolusCalculator.recommendedInsulin( mealCarbs: nil, - manualGlucose: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 180), - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: -1), + manualGlucose: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 180), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: -1), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(0.94, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(0.94, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } func testCorrectionRecommendationWhenInRange() { let recommendation = SimpleBolusCalculator.recommendedInsulin( mealCarbs: nil, - manualGlucose: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 110), - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 0), + manualGlucose: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 110), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 0), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(0.0, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(0.0, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } func testCorrectionAndCarbsRecommendationWhenBelowRange() { let recommendation = SimpleBolusCalculator.recommendedInsulin( - mealCarbs: HKQuantity(unit: .gram(), doubleValue: 40), - manualGlucose: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 70), - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 0), + mealCarbs: LoopQuantity(unit: .gram, doubleValue: 40), + manualGlucose: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 70), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 0), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(3.56, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(3.56, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } func testCarbsEntryWithActiveInsulinAndNoGlucose() { let recommendation = SimpleBolusCalculator.recommendedInsulin( - mealCarbs: HKQuantity(unit: .gram(), doubleValue: 20), + mealCarbs: LoopQuantity(unit: .gram, doubleValue: 20), manualGlucose: nil, - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 4), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 4), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(2, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(2, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } func testCarbsEntryWithActiveInsulinAndCarbsAndNoCorrection() { let recommendation = SimpleBolusCalculator.recommendedInsulin( - mealCarbs: HKQuantity(unit: .gram(), doubleValue: 20), - manualGlucose: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 100), - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 4), + mealCarbs: LoopQuantity(unit: .gram, doubleValue: 20), + manualGlucose: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 100), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 4), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(2, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(2, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } func testPredictionShouldBeZeroWhenGlucoseBelowMealBolusRecommendationLimit() { let recommendation = SimpleBolusCalculator.recommendedInsulin( - mealCarbs: HKQuantity(unit: .gram(), doubleValue: 20), - manualGlucose: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 54), - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 4), + mealCarbs: LoopQuantity(unit: .gram, doubleValue: 20), + manualGlucose: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 54), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 4), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(0, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(0, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } func testPredictionShouldBeZeroWhenGlucoseBelowBolusRecommendationLimit() { let recommendation = SimpleBolusCalculator.recommendedInsulin( mealCarbs: nil, - manualGlucose: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 69), - activeInsulin: HKQuantity(unit: .internationalUnit(), doubleValue: 4), + manualGlucose: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 69), + activeInsulin: LoopQuantity(unit: .internationalUnit, doubleValue: 4), carbRatioSchedule: carbRatioSchedule, correctionRangeSchedule: correctionRangeSchedule, sensitivitySchedule: sensitivitySchedule) - XCTAssertEqual(0, recommendation.doubleValue(for: .internationalUnit()), accuracy: 0.01) + XCTAssertEqual(0, recommendation.doubleValue(for: .internationalUnit), accuracy: 0.01) } } diff --git a/LoopTests/Models/WatchHistoricalGlucoseTest.swift b/LoopTests/Models/WatchHistoricalGlucoseTest.swift index 4478af76f7..6d0f85be19 100644 --- a/LoopTests/Models/WatchHistoricalGlucoseTest.swift +++ b/LoopTests/Models/WatchHistoricalGlucoseTest.swift @@ -8,6 +8,7 @@ import XCTest import HealthKit +import LoopAlgorithm import LoopKit @testable import Loop @@ -20,7 +21,7 @@ class WatchHistoricalGlucoseTests: XCTestCase { syncIdentifier: UUID().uuidString, syncVersion: 4, startDate: Date(timeIntervalSinceReferenceDate: .hours(100)), - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 123.45), + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 123.45), condition: nil, trend: nil, trendRate: nil, @@ -33,10 +34,10 @@ class WatchHistoricalGlucoseTests: XCTestCase { syncIdentifier: UUID().uuidString, syncVersion: 2, startDate: Date(timeIntervalSinceReferenceDate: .hours(99)), - quantity: HKQuantity(unit: .millimolesPerLiter, doubleValue: 7.2), + quantity: LoopQuantity(unit: .millimolesPerLiter, doubleValue: 7.2), condition: nil, trend: .up, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: 1.0), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: 1.0), isDisplayOnly: true, wasUserEntered: false, device: device, @@ -46,10 +47,10 @@ class WatchHistoricalGlucoseTests: XCTestCase { syncIdentifier: nil, syncVersion: nil, startDate: Date(timeIntervalSinceReferenceDate: .hours(98)), - quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 187.65), + quantity: LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 187.65), condition: .aboveRange, trend: .downDownDown, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -4.0), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -4.0), isDisplayOnly: false, wasUserEntered: false, device: nil, diff --git a/LoopTests/ViewModels/BolusEntryViewModelTests.swift b/LoopTests/ViewModels/BolusEntryViewModelTests.swift index 275b4c3743..d3a0dbb7d0 100644 --- a/LoopTests/ViewModels/BolusEntryViewModelTests.swift +++ b/LoopTests/ViewModels/BolusEntryViewModelTests.swift @@ -24,25 +24,25 @@ class BolusEntryViewModelTests: XCTestCase { static let exampleStartDate = now - .hours(2) static let exampleEndDate = now - .hours(1) static fileprivate let exampleGlucoseValue = SimpleGlucoseValue(startDate: exampleStartDate, quantity: exampleManualGlucoseQuantity) - static let exampleManualGlucoseQuantity = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 123.4) + static let exampleManualGlucoseQuantity = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 123.4) static let exampleManualGlucoseSample = HKQuantitySample(type: HKQuantityType.quantityType(forIdentifier: .bloodGlucose)!, - quantity: exampleManualGlucoseQuantity, + quantity: exampleManualGlucoseQuantity.hkQuantity, start: exampleStartDate, end: exampleEndDate) static let exampleManualStoredGlucoseSample = StoredGlucoseSample(sample: exampleManualGlucoseSample) - static let exampleCGMGlucoseQuantity = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 100.4) + static let exampleCGMGlucoseQuantity = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 100.4) static let exampleCGMGlucoseSample = - HKQuantitySample(type: HKQuantityType.quantityType(forIdentifier: .bloodGlucose)!, - quantity: exampleCGMGlucoseQuantity, + HKQuantitySample(type: HKQuantityType.quantityType(forIdentifier: .bloodGlucose)!, + quantity: exampleCGMGlucoseQuantity.hkQuantity, start: exampleStartDate, end: exampleEndDate) - static let exampleCarbQuantity = HKQuantity(unit: .gram(), doubleValue: 234.5) + static let exampleCarbQuantity = LoopQuantity(unit: .gram, doubleValue: 234.5) - static let exampleBolusQuantity = HKQuantity(unit: .internationalUnit(), doubleValue: 1.0) - static let noBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0.0) + static let exampleBolusQuantity = LoopQuantity(unit: .internationalUnit, doubleValue: 1.0) + static let noBolus = LoopQuantity(unit: .internationalUnit, doubleValue: 0.0) static let exampleGlucoseRangeSchedule = GlucoseRangeSchedule(unit: .milligramsPerDeciliter, dailyItems: [ RepeatingScheduleValue(startTime: TimeInterval(0), value: DoubleRange(minValue: 100, maxValue: 110)), @@ -115,7 +115,7 @@ class BolusEntryViewModelTests: XCTestCase { selectedCarbAbsorptionTimeEmoji: selectedCarbAbsorptionTimeEmoji) bolusEntryViewModel.authenticationHandler = { _ in return true } - bolusEntryViewModel.maximumBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 10) + bolusEntryViewModel.maximumBolus = LoopQuantity(unit: .internationalUnit, doubleValue: 10) bolusEntryViewModel.deliveryDelegate = mockDeliveryDelegate @@ -134,8 +134,8 @@ class BolusEntryViewModelTests: XCTestCase { XCTAssertFalse(bolusEntryViewModel.isManualGlucoseEntryEnabled) XCTAssertNil(bolusEntryViewModel.manualGlucoseQuantity) - XCTAssertEqual(HKQuantity(unit: .internationalUnit(), doubleValue: 0), bolusEntryViewModel.recommendedBolus) - XCTAssertEqual(HKQuantity(unit: .internationalUnit(), doubleValue: 0), bolusEntryViewModel.enteredBolus) + XCTAssertEqual(LoopQuantity(unit: .internationalUnit, doubleValue: 0), bolusEntryViewModel.recommendedBolus) + XCTAssertEqual(LoopQuantity(unit: .internationalUnit, doubleValue: 0), bolusEntryViewModel.enteredBolus) XCTAssertNil(bolusEntryViewModel.activeAlert) XCTAssertNil(bolusEntryViewModel.activeNotice) @@ -184,7 +184,7 @@ class BolusEntryViewModelTests: XCTestCase { func testManualEntryClearsEnteredBolus() throws { bolusEntryViewModel.enteredBolus = Self.exampleBolusQuantity bolusEntryViewModel.manualGlucoseQuantity = Self.exampleManualGlucoseQuantity - XCTAssertEqual(HKQuantity(unit: .internationalUnit(), doubleValue: 0), bolusEntryViewModel.enteredBolus) + XCTAssertEqual(LoopQuantity(unit: .internationalUnit, doubleValue: 0), bolusEntryViewModel.enteredBolus) } func testUpdatePredictedGlucoseValues() async throws { @@ -275,11 +275,11 @@ class BolusEntryViewModelTests: XCTestCase { delegate.activeInsulin = InsulinValue(startDate: Self.exampleStartDate, value: 1.5) XCTAssertNil(bolusEntryViewModel.activeInsulin) await bolusEntryViewModel.update() - XCTAssertEqual(HKQuantity(unit: .internationalUnit(), doubleValue: 1.5), bolusEntryViewModel.activeInsulin) + XCTAssertEqual(LoopQuantity(unit: .internationalUnit, doubleValue: 1.5), bolusEntryViewModel.activeInsulin) } func testUpdateCarbsOnBoard() async throws { - delegate.activeCarbs = CarbValue(startDate: Self.exampleStartDate, endDate: Self.exampleEndDate, value: Self.exampleCarbQuantity.doubleValue(for: .gram())) + delegate.activeCarbs = CarbValue(startDate: Self.exampleStartDate, endDate: Self.exampleEndDate, value: Self.exampleCarbQuantity.doubleValue(for: .gram)) XCTAssertNil(bolusEntryViewModel.activeCarbs) await bolusEntryViewModel.update() XCTAssertEqual(Self.exampleCarbQuantity, bolusEntryViewModel.activeCarbs) @@ -308,7 +308,7 @@ class BolusEntryViewModelTests: XCTestCase { XCTAssertTrue(bolusEntryViewModel.isBolusRecommended) let recommendedBolus = bolusEntryViewModel.recommendedBolus XCTAssertNotNil(recommendedBolus) - XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit())) + XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit)) XCTAssertEqual(delegate.originalCarbEntryForBolusRecommendation?.quantity, originalCarbEntry.quantity) XCTAssertEqual(delegate.potentialCarbEntryForBolusRecommendation?.quantity, editedCarbEntry.quantity) @@ -329,7 +329,7 @@ class BolusEntryViewModelTests: XCTestCase { XCTAssertTrue(bolusEntryViewModel.isBolusRecommended) let recommendedBolus = bolusEntryViewModel.recommendedBolus XCTAssertNotNil(recommendedBolus) - XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit())) + XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit)) XCTAssertEqual(BolusEntryViewModel.Notice.predictedGlucoseBelowSuspendThreshold(suspendThreshold: Self.exampleCGMGlucoseQuantity), bolusEntryViewModel.activeNotice) } @@ -342,7 +342,7 @@ class BolusEntryViewModelTests: XCTestCase { XCTAssertTrue(bolusEntryViewModel.isBolusRecommended) let recommendedBolus = bolusEntryViewModel.recommendedBolus XCTAssertNotNil(recommendedBolus) - XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit())) + XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit)) XCTAssertNil(bolusEntryViewModel.activeNotice) } @@ -354,7 +354,7 @@ class BolusEntryViewModelTests: XCTestCase { XCTAssertTrue(bolusEntryViewModel.isBolusRecommended) let recommendedBolus = bolusEntryViewModel.recommendedBolus XCTAssertNotNil(recommendedBolus) - XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit())) + XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit)) XCTAssertNil(bolusEntryViewModel.activeNotice) } @@ -416,7 +416,7 @@ class BolusEntryViewModelTests: XCTestCase { await setUpViewModel(originalCarbEntry: originalCarbEntry, potentialCarbEntry: editedCarbEntry) - let manualGlucoseQuantity = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 123) + let manualGlucoseQuantity = LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 123) bolusEntryViewModel.manualGlucoseQuantity = manualGlucoseQuantity XCTAssertFalse(bolusEntryViewModel.isBolusRecommended) @@ -428,7 +428,7 @@ class BolusEntryViewModelTests: XCTestCase { XCTAssertTrue(bolusEntryViewModel.isBolusRecommended) let recommendedBolus = bolusEntryViewModel.recommendedBolus XCTAssertNotNil(recommendedBolus) - XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit())) + XCTAssertEqual(recommendation.amount, recommendedBolus?.doubleValue(for: .internationalUnit)) XCTAssertEqual(delegate.potentialCarbEntryForBolusRecommendation, editedCarbEntry) XCTAssertEqual(delegate.originalCarbEntryForBolusRecommendation, originalCarbEntry) @@ -456,7 +456,7 @@ class BolusEntryViewModelTests: XCTestCase { } func testBolusTooSmall() async throws { - bolusEntryViewModel.enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0.01) + bolusEntryViewModel.enteredBolus = LoopQuantity(unit: .internationalUnit, doubleValue: 0.01) let success = await bolusEntryViewModel.saveAndDeliver() XCTAssertEqual(.bolusTooSmall, bolusEntryViewModel.activeAlert) XCTAssertNil(delegate.enactedBolusUnits) @@ -516,7 +516,7 @@ class BolusEntryViewModelTests: XCTestCase { XCTAssertTrue(delegate.bolusDosingDecisionsAdded.isEmpty) } - private func saveAndDeliver(_ bolus: HKQuantity, file: StaticString = #file, line: UInt = #line) async throws { + private func saveAndDeliver(_ bolus: LoopQuantity, file: StaticString = #file, line: UInt = #line) async throws { bolusEntryViewModel.enteredBolus = bolus self.saveAndDeliverSuccess = await bolusEntryViewModel.saveAndDeliver() @@ -830,7 +830,7 @@ fileprivate class MockBolusEntryViewModelDelegate: BolusEntryViewModelDelegate { glucoseTargetRangeSchedule: BolusEntryViewModelTests.exampleGlucoseRangeSchedule, maximumBasalRatePerHour: 3.0, maximumBolus: 10.0, - suspendThreshold: GlucoseThreshold(unit: .internationalUnit(), value: 75)) + suspendThreshold: GlucoseThreshold(unit: .internationalUnit, value: 75)) { didSet { NotificationCenter.default.post(name: .LoopDataUpdated, object: nil, userInfo: [ @@ -970,7 +970,7 @@ fileprivate struct MockInsulinModel: InsulinModel { } fileprivate struct MockGlucoseValue: GlucoseValue { - var quantity: HKQuantity + var quantity: LoopQuantity var startDate: Date } @@ -1025,7 +1025,7 @@ extension LoopAlgorithmEffects { extension NewCarbEntry { static func mock(_ grams: Double, at date: Date) -> NewCarbEntry { NewCarbEntry( - quantity: .init(unit: .gram(), doubleValue: grams), + quantity: .init(unit: .gram, doubleValue: grams), startDate: date, foodType: nil, absorptionTime: nil @@ -1035,7 +1035,7 @@ extension NewCarbEntry { extension StoredCarbEntry { static func mock(_ grams: Double, at date: Date) -> StoredCarbEntry { - StoredCarbEntry(startDate: date, quantity: .init(unit: .gram(), doubleValue: grams)) + StoredCarbEntry(startDate: date, quantity: .init(unit: .gram, doubleValue: grams)) } } diff --git a/LoopTests/ViewModels/CGMStatusHUDViewModelTests.swift b/LoopTests/ViewModels/CGMStatusHUDViewModelTests.swift index 9728578c0c..8f9bd9d3ac 100644 --- a/LoopTests/ViewModels/CGMStatusHUDViewModelTests.swift +++ b/LoopTests/ViewModels/CGMStatusHUDViewModelTests.swift @@ -7,7 +7,7 @@ // import XCTest -import HealthKit +import LoopAlgorithm import LoopKit @testable import LoopUI @@ -38,7 +38,7 @@ class CGMStatusHUDViewModelTests: XCTestCase { func testSetGlucoseQuantityCGM() { let glucoseDisplay = TestGlucoseDisplay(isStateValid: true, trendType: .down, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), isLocal: true, glucoseRangeCategory: .urgentLow) let glucoseStartDate = Date() @@ -56,13 +56,13 @@ class CGMStatusHUDViewModelTests: XCTestCase { XCTAssertEqual(viewModel.trend, .down) XCTAssertEqual(viewModel.glucoseTrendTintColor, glucoseDisplay.glucoseRangeCategory?.trendColor) XCTAssertEqual(viewModel.glucoseValueTintColor, glucoseDisplay.glucoseRangeCategory?.glucoseColor) - XCTAssertEqual(viewModel.unitsString, HKUnit.milligramsPerDeciliter.localizedShortUnitString) + XCTAssertEqual(viewModel.unitsString, LoopUnit.milligramsPerDeciliter.localizedShortUnitString) } func testSetGlucoseQuantityCGMStale() { let glucoseDisplay = TestGlucoseDisplay(isStateValid: true, trendType: .down, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), isLocal: true, glucoseRangeCategory: .urgentLow) let glucoseStartDate = Date() @@ -82,13 +82,13 @@ class CGMStatusHUDViewModelTests: XCTestCase { XCTAssertEqual(viewModel.glucoseTrendTintColor, .glucoseTintColor) XCTAssertNotEqual(viewModel.glucoseValueTintColor, glucoseDisplay.glucoseRangeCategory?.glucoseColor) XCTAssertEqual(viewModel.glucoseValueTintColor, .label) - XCTAssertEqual(viewModel.unitsString, HKUnit.milligramsPerDeciliter.localizedShortUnitString) + XCTAssertEqual(viewModel.unitsString, LoopUnit.milligramsPerDeciliter.localizedShortUnitString) } func testSetGlucoseQuantityManualGlucose() { let glucoseDisplay = TestGlucoseDisplay(isStateValid: true, trendType: .down, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), isLocal: true, glucoseRangeCategory: .urgentLow) let glucoseStartDate = Date() @@ -107,13 +107,13 @@ class CGMStatusHUDViewModelTests: XCTestCase { XCTAssertNotEqual(viewModel.glucoseTrendTintColor, glucoseDisplay.glucoseRangeCategory?.trendColor) XCTAssertEqual(viewModel.glucoseTrendTintColor, .glucoseTintColor) XCTAssertEqual(viewModel.glucoseValueTintColor, glucoseDisplay.glucoseRangeCategory?.glucoseColor) - XCTAssertEqual(viewModel.unitsString, HKUnit.milligramsPerDeciliter.localizedShortUnitString) + XCTAssertEqual(viewModel.unitsString, LoopUnit.milligramsPerDeciliter.localizedShortUnitString) } func testSetGlucoseQuantityCalibrationDoesNotShow() { let glucoseDisplay = TestGlucoseDisplay(isStateValid: true, trendType: .down, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), isLocal: true, glucoseRangeCategory: .urgentLow) let glucoseStartDate = Date() @@ -130,7 +130,7 @@ class CGMStatusHUDViewModelTests: XCTestCase { XCTAssertEqual(viewModel.trend, .down) XCTAssertEqual(viewModel.glucoseTrendTintColor, glucoseDisplay.glucoseRangeCategory?.trendColor) XCTAssertEqual(viewModel.glucoseValueTintColor, glucoseDisplay.glucoseRangeCategory?.glucoseColor) - XCTAssertEqual(viewModel.unitsString, HKUnit.milligramsPerDeciliter.localizedShortUnitString) + XCTAssertEqual(viewModel.unitsString, LoopUnit.milligramsPerDeciliter.localizedShortUnitString) } func testSetManualGlucoseIconOverride() { @@ -151,7 +151,7 @@ class CGMStatusHUDViewModelTests: XCTestCase { // when there is a manual glucose override icon, the status highlight isn't returned to be presented let glucoseDisplay = TestGlucoseDisplay(isStateValid: true, trendType: .down, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), isLocal: true, glucoseRangeCategory: .urgentLow) let glucoseStartDate = Date() @@ -182,7 +182,7 @@ class CGMStatusHUDViewModelTests: XCTestCase { // add manual glucose let glucoseDisplay = TestGlucoseDisplay(isStateValid: true, trendType: .down, - trendRate: HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), + trendRate: LoopQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: -1.0), isLocal: true, glucoseRangeCategory: .urgentLow) viewModel.setGlucoseQuantity(90, @@ -294,7 +294,7 @@ extension CGMStatusHUDViewModelTests { var trendType: GlucoseTrend? - var trendRate: HKQuantity? + var trendRate: LoopQuantity? var isLocal: Bool diff --git a/LoopTests/ViewModels/ManualEntryDoseViewModelTests.swift b/LoopTests/ViewModels/ManualEntryDoseViewModelTests.swift index d21c3f9e43..4eaa0fbb3b 100644 --- a/LoopTests/ViewModels/ManualEntryDoseViewModelTests.swift +++ b/LoopTests/ViewModels/ManualEntryDoseViewModelTests.swift @@ -6,7 +6,6 @@ // Copyright © 2021 LoopKit Authors. All rights reserved. // -import HealthKit import LoopCore import LoopKit import XCTest @@ -23,9 +22,9 @@ class ManualEntryDoseViewModelTests: XCTestCase { var manualEntryDoseViewModel: ManualEntryDoseViewModel! - static let exampleBolusQuantity = HKQuantity(unit: .internationalUnit(), doubleValue: 1.0) + static let exampleBolusQuantity = LoopQuantity(unit: .internationalUnit, doubleValue: 1.0) - static let noBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0.0) + static let noBolus = LoopQuantity(unit: .internationalUnit, doubleValue: 0.0) fileprivate var delegate: MockManualEntryDoseViewModelDelegate! @@ -53,7 +52,7 @@ class ManualEntryDoseViewModelTests: XCTestCase { try await manualEntryDoseViewModel.saveManualDose() - XCTAssertEqual(delegate.manualEntryBolusUnits, Self.exampleBolusQuantity.doubleValue(for: .internationalUnit())) + XCTAssertEqual(delegate.manualEntryBolusUnits, Self.exampleBolusQuantity.doubleValue(for: .internationalUnit)) XCTAssertEqual(delegate.manuallyEnteredDoseInsulinType, .novolog) } diff --git a/LoopTests/ViewModels/SimpleBolusViewModelTests.swift b/LoopTests/ViewModels/SimpleBolusViewModelTests.swift index d2425abd0b..c4e17bd1ed 100644 --- a/LoopTests/ViewModels/SimpleBolusViewModelTests.swift +++ b/LoopTests/ViewModels/SimpleBolusViewModelTests.swift @@ -85,7 +85,7 @@ class SimpleBolusViewModelTests: XCTestCase { let _ = await viewModel.saveAndDeliver() - XCTAssertEqual(20, addedCarbEntry?.quantity.doubleValue(for: .gram())) + XCTAssertEqual(20, addedCarbEntry?.quantity.doubleValue(for: .gram)) XCTAssertEqual(180, addedGlucose.first?.quantity.doubleValue(for: .milligramsPerDeciliter)) XCTAssertEqual(2.5, enactedBolus?.units) @@ -112,7 +112,7 @@ class SimpleBolusViewModelTests: XCTestCase { let _ = await viewModel.saveAndDeliver() - XCTAssertEqual(20, addedCarbEntry?.quantity.doubleValue(for: .gram())) + XCTAssertEqual(20, addedCarbEntry?.quantity.doubleValue(for: .gram)) XCTAssertEqual(0.1, enactedBolus?.units) @@ -299,7 +299,7 @@ extension SimpleBolusViewModelTests: SimpleBolusViewModelDelegate { } - func computeSimpleBolusRecommendation(at date: Date, mealCarbs: HKQuantity?, manualGlucose: HKQuantity?) -> BolusDosingDecision? { + func computeSimpleBolusRecommendation(at date: Date, mealCarbs: LoopQuantity?, manualGlucose: LoopQuantity?) -> BolusDosingDecision? { var decision = BolusDosingDecision(for: .simpleBolus) decision.manualBolusRecommendation = ManualBolusRecommendationWithDate(recommendation: ManualBolusRecommendation(amount: currentRecommendation, notice: .none), date: date) @@ -312,7 +312,7 @@ extension SimpleBolusViewModelTests: SimpleBolusViewModelDelegate { return 3.0 } - var suspendThreshold: HKQuantity? { - return HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 80) + var suspendThreshold: LoopQuantity? { + return LoopQuantity(unit: .milligramsPerDeciliter, doubleValue: 80) } } diff --git a/LoopUI/ViewModel/CGMStatusHUDViewModel.swift b/LoopUI/ViewModel/CGMStatusHUDViewModel.swift index 06dc1d456d..2d6f04bec7 100644 --- a/LoopUI/ViewModel/CGMStatusHUDViewModel.swift +++ b/LoopUI/ViewModel/CGMStatusHUDViewModel.swift @@ -6,7 +6,7 @@ // Copyright © 2020 LoopKit Authors. All rights reserved. // -import HealthKit +import LoopAlgorithm import LoopKit public class CGMStatusHUDViewModel { @@ -73,7 +73,7 @@ public class CGMStatusHUDViewModel { func setGlucoseQuantity(_ glucoseQuantity: Double, at glucoseStartDate: Date, - unit: HKUnit, + unit: LoopUnit, glucoseDisplay: GlucoseDisplayable?, wasUserEntered: Bool, isDisplayOnly: Bool, diff --git a/LoopUI/Views/CGMStatusHUDView.swift b/LoopUI/Views/CGMStatusHUDView.swift index 5a40459c3c..2f53c0f89d 100644 --- a/LoopUI/Views/CGMStatusHUDView.swift +++ b/LoopUI/Views/CGMStatusHUDView.swift @@ -7,7 +7,7 @@ // import UIKit -import HealthKit +import LoopAlgorithm import LoopKit import LoopKitUI @@ -116,7 +116,7 @@ public final class CGMStatusHUDView: DeviceStatusHUDView, NibLoadable { public func setGlucoseQuantity(_ glucoseQuantity: Double, at glucoseStartDate: Date, - unit: HKUnit, + unit: LoopUnit, glucoseDisplay: GlucoseDisplayable?, wasUserEntered: Bool, isDisplayOnly: Bool, diff --git a/LoopUI/Views/DeviceStatusHUDView.swift b/LoopUI/Views/DeviceStatusHUDView.swift index 3951aca3ec..32d7aea767 100644 --- a/LoopUI/Views/DeviceStatusHUDView.swift +++ b/LoopUI/Views/DeviceStatusHUDView.swift @@ -7,7 +7,6 @@ // import UIKit -import HealthKit import LoopKit import LoopKitUI diff --git a/LoopUI/Views/GlucoseHUDView.swift b/LoopUI/Views/GlucoseHUDView.swift index 8201e82a51..e54bdf2db1 100644 --- a/LoopUI/Views/GlucoseHUDView.swift +++ b/LoopUI/Views/GlucoseHUDView.swift @@ -7,7 +7,7 @@ // import UIKit -import HealthKit +import LoopAlgorithm import LoopKit import LoopKitUI @@ -127,7 +127,7 @@ public final class GlucoseHUDView: BaseHUDView { } } - public func setGlucoseQuantity(_ glucoseQuantity: Double, at glucoseStartDate: Date, unit: HKUnit, staleGlucoseAge: TimeInterval, sensor: GlucoseDisplayable?) { + public func setGlucoseQuantity(_ glucoseQuantity: Double, at glucoseStartDate: Date, unit: LoopUnit, staleGlucoseAge: TimeInterval, sensor: GlucoseDisplayable?) { var accessibilityStrings = [String]() let time = timeFormatter.string(from: glucoseStartDate) diff --git a/LoopUI/Views/GlucoseTrendHUDView.swift b/LoopUI/Views/GlucoseTrendHUDView.swift index c31dd812da..332e3b545f 100644 --- a/LoopUI/Views/GlucoseTrendHUDView.swift +++ b/LoopUI/Views/GlucoseTrendHUDView.swift @@ -7,7 +7,6 @@ // import UIKit -import HealthKit import LoopKit import LoopKitUI diff --git a/LoopUI/Views/GlucoseValueHUDView.swift b/LoopUI/Views/GlucoseValueHUDView.swift index 4a0858e746..1fe64e0b60 100644 --- a/LoopUI/Views/GlucoseValueHUDView.swift +++ b/LoopUI/Views/GlucoseValueHUDView.swift @@ -7,7 +7,6 @@ // import UIKit -import HealthKit import LoopKit import LoopKitUI diff --git a/LoopUI/Views/PumpStatusHUDView.swift b/LoopUI/Views/PumpStatusHUDView.swift index 754aa6e7fe..2b019e3e5e 100644 --- a/LoopUI/Views/PumpStatusHUDView.swift +++ b/LoopUI/Views/PumpStatusHUDView.swift @@ -7,7 +7,6 @@ // import UIKit -import HealthKit import LoopKit import LoopKitUI diff --git a/WatchApp Extension/Controllers/ActionHUDController.swift b/WatchApp Extension/Controllers/ActionHUDController.swift index bb2df24563..8719415d27 100644 --- a/WatchApp Extension/Controllers/ActionHUDController.swift +++ b/WatchApp Extension/Controllers/ActionHUDController.swift @@ -8,7 +8,7 @@ import WatchKit import WatchConnectivity -import HealthKit +import LoopAlgorithm import LoopKit import LoopCore import SwiftUI @@ -224,7 +224,7 @@ final class ActionHUDController: HUDInterfaceController { } } - private func formattedGlucoseRangeString(from range: ClosedRange) -> String { + private func formattedGlucoseRangeString(from range: ClosedRange) -> String { let unit = loopManager.displayGlucoseUnit glucoseFormatter.updateUnit(to: unit) let rangeDouble = range.doubleRange(for: unit) diff --git a/WatchApp Extension/Controllers/CarbAndBolusFlowController.swift b/WatchApp Extension/Controllers/CarbAndBolusFlowController.swift index 102bc98de8..aeea4066a7 100644 --- a/WatchApp Extension/Controllers/CarbAndBolusFlowController.swift +++ b/WatchApp Extension/Controllers/CarbAndBolusFlowController.swift @@ -8,7 +8,6 @@ import WatchKit import SwiftUI -import HealthKit import LoopCore import LoopKit diff --git a/WatchApp Extension/Controllers/CarbEntryListController.swift b/WatchApp Extension/Controllers/CarbEntryListController.swift index 8a2b74a420..ab02242643 100644 --- a/WatchApp Extension/Controllers/CarbEntryListController.swift +++ b/WatchApp Extension/Controllers/CarbEntryListController.swift @@ -5,7 +5,6 @@ // Copyright © 2019 LoopKit Authors. All rights reserved. // -import HealthKit import LoopCore import LoopKit import os.log @@ -26,7 +25,7 @@ class CarbEntryListController: WKInterfaceController, IdentifiableClass { private lazy var loopManager = ExtensionDelegate.shared().loopManager private lazy var carbFormatter: QuantityFormatter = { - let formatter = QuantityFormatter(for: .gram()) + let formatter = QuantityFormatter(for: .gram) formatter.numberFormatter.numberStyle = .none return formatter }() @@ -105,7 +104,7 @@ extension CarbEntryListController { timeFormatter.dateStyle = .none timeFormatter.timeStyle = .short - let unit = loopManager.carbStore.preferredUnit ?? .gram() + let unit = loopManager.carbStore.preferredUnit ?? .gram for (index, entry) in entries.reversed().enumerated() { guard let row = table.rowController(at: index) as? TextRowController else { @@ -118,6 +117,6 @@ extension CarbEntryListController { row.detailTextLabel.setText(carbFormatter.string(from: entry.quantity)) } - totalLabel.setText(carbFormatter.string(from: HKQuantity(unit: unit, doubleValue: total))) + totalLabel.setText(carbFormatter.string(from: LoopQuantity(unit: unit, doubleValue: total))) } } diff --git a/WatchApp Extension/Controllers/ChartHUDController.swift b/WatchApp Extension/Controllers/ChartHUDController.swift index d093bca3c9..b9e9292b95 100644 --- a/WatchApp Extension/Controllers/ChartHUDController.swift +++ b/WatchApp Extension/Controllers/ChartHUDController.swift @@ -9,7 +9,6 @@ import WatchKit import WatchConnectivity import LoopKit -import HealthKit import SpriteKit import os.log import LoopCore diff --git a/WatchApp Extension/Controllers/HUDRowController.swift b/WatchApp Extension/Controllers/HUDRowController.swift index d1c8ee5cca..c45dd12fcb 100644 --- a/WatchApp Extension/Controllers/HUDRowController.swift +++ b/WatchApp Extension/Controllers/HUDRowController.swift @@ -5,7 +5,7 @@ // Copyright © 2019 LoopKit Authors. All rights reserved. // -import HealthKit +import LoopAlgorithm import LoopCore import LoopKit import WatchKit @@ -36,14 +36,14 @@ extension HUDRowController { } extension HUDRowController { - func setActiveInsulin(_ activeInsulin: HKQuantity?) { + func setActiveInsulin(_ activeInsulin: LoopQuantity?) { guard let activeInsulin = activeInsulin else { setDetail(nil) return } let insulinFormatter: QuantityFormatter = { - let insulinFormatter = QuantityFormatter(for: .internationalUnit()) + let insulinFormatter = QuantityFormatter(for: .internationalUnit) insulinFormatter.numberFormatter.minimumFractionDigits = 1 insulinFormatter.numberFormatter.maximumFractionDigits = 1 @@ -53,13 +53,13 @@ extension HUDRowController { setDetail(insulinFormatter.string(from: activeInsulin)) } - func setActiveCarbohydrates(_ activeCarbohydrates: HKQuantity?) { + func setActiveCarbohydrates(_ activeCarbohydrates: LoopQuantity?) { guard let activeCarbohydrates = activeCarbohydrates else { setDetail(nil) return } - let carbFormatter = QuantityFormatter(for: .gram()) + let carbFormatter = QuantityFormatter(for: .gram) carbFormatter.numberFormatter.maximumFractionDigits = 0 setDetail(carbFormatter.string(from: activeCarbohydrates)) @@ -85,14 +85,14 @@ extension HUDRowController { setDetail(basalFormatter.string(from: tempBasal, unit: unit)) } - func setReservoirVolume(_ reservoirVolume: HKQuantity?) { + func setReservoirVolume(_ reservoirVolume: LoopQuantity?) { guard let reservoirVolume = reservoirVolume else { setDetail(nil) return } let insulinFormatter: QuantityFormatter = { - let insulinFormatter = QuantityFormatter(for: .internationalUnit()) + let insulinFormatter = QuantityFormatter(for: .internationalUnit) insulinFormatter.unitStyle = .long insulinFormatter.numberFormatter.minimumFractionDigits = 0 insulinFormatter.numberFormatter.maximumFractionDigits = 0 diff --git a/WatchApp Extension/ExtensionDelegate.swift b/WatchApp Extension/ExtensionDelegate.swift index 946669adf4..3a150f1e9e 100644 --- a/WatchApp Extension/ExtensionDelegate.swift +++ b/WatchApp Extension/ExtensionDelegate.swift @@ -9,6 +9,7 @@ import WatchConnectivity import WatchKit import HealthKit +import LoopAlgorithm import Intents import os import os.log @@ -165,11 +166,18 @@ final class ExtensionDelegate: NSObject, WKExtensionDelegate { if context.displayGlucoseUnit == nil { let type = HKQuantityType.quantityType(forIdentifier: .bloodGlucose)! loopManager.healthStore.preferredUnits(for: [type]) { (units, error) in - context.displayGlucoseUnit = units[type] - - DispatchQueue.main.async { - self.loopManager.updateContext(context) + defer { + DispatchQueue.main.async { + self.loopManager.updateContext(context) + } + } + + guard let unit = units[type] else { + context.displayGlucoseUnit = nil + return } + + context.displayGlucoseUnit = LoopUnit(from: unit) } } else { DispatchQueue.main.async { @@ -262,7 +270,7 @@ extension ExtensionDelegate: UNUserNotificationCenterDelegate { let mealTime = userInfo[LoopNotificationUserInfoKey.missedMealTime.rawValue] as? Date, let carbAmount = userInfo[LoopNotificationUserInfoKey.missedMealCarbAmount.rawValue] as? Double { - let missedEntry = NewCarbEntry(quantity: HKQuantity(unit: .gram(), + let missedEntry = NewCarbEntry(quantity: LoopQuantity(unit: .gram, doubleValue: carbAmount), startDate: mealTime, foodType: nil, diff --git a/WatchApp Extension/Extensions/CLKComplicationTemplate.swift b/WatchApp Extension/Extensions/CLKComplicationTemplate.swift index 2518644375..dee7c6c6d8 100644 --- a/WatchApp Extension/Extensions/CLKComplicationTemplate.swift +++ b/WatchApp Extension/Extensions/CLKComplicationTemplate.swift @@ -7,7 +7,6 @@ // import ClockKit -import HealthKit import LoopKit import Foundation import LoopCore @@ -43,12 +42,12 @@ extension CLKComplicationTemplate { static func templateForFamily( _ family: CLKComplicationFamily, - glucose: HKQuantity, - unit: HKUnit, + glucose: LoopQuantity, + unit: LoopUnit, glucoseDate: Date?, trend: GlucoseTrend?, glucoseCondition: GlucoseCondition?, - eventualGlucose: HKQuantity?, + eventualGlucose: LoopQuantity?, at date: Date, loopLastRunDate: Date?, recencyInterval: TimeInterval, diff --git a/WatchApp Extension/Extensions/WatchContext+WatchApp.swift b/WatchApp Extension/Extensions/WatchContext+WatchApp.swift index 6c77afd7c2..41253d309a 100644 --- a/WatchApp Extension/Extensions/WatchContext+WatchApp.swift +++ b/WatchApp Extension/Extensions/WatchContext+WatchApp.swift @@ -7,31 +7,31 @@ // import Foundation -import HealthKit +import LoopAlgorithm import LoopKit extension WatchContext { - var activeInsulin: HKQuantity? { + var activeInsulin: LoopQuantity? { guard let value = iob else { return nil } - return HKQuantity(unit: .internationalUnit(), doubleValue: value) + return LoopQuantity(unit: .internationalUnit, doubleValue: value) } - var activeCarbohydrates: HKQuantity? { + var activeCarbohydrates: LoopQuantity? { guard let value = cob else { return nil } - return HKQuantity(unit: .gram(), doubleValue: value) + return LoopQuantity(unit: .gram, doubleValue: value) } - var reservoirVolume: HKQuantity? { + var reservoirVolume: LoopQuantity? { guard let value = reservoir else { return nil } - return HKQuantity(unit: .internationalUnit(), doubleValue: value) + return LoopQuantity(unit: .internationalUnit, doubleValue: value) } } diff --git a/WatchApp Extension/Managers/ComplicationChartManager.swift b/WatchApp Extension/Managers/ComplicationChartManager.swift index 1d71f66446..17b87c4c36 100644 --- a/WatchApp Extension/Managers/ComplicationChartManager.swift +++ b/WatchApp Extension/Managers/ComplicationChartManager.swift @@ -8,7 +8,6 @@ import Foundation import UIKit -import HealthKit import WatchKit import LoopKit import LoopAlgorithm @@ -46,7 +45,7 @@ final class ComplicationChartManager { private var renderedChartImage: UIImage? private var visibleInterval: TimeInterval = .hours(4) - private var unit: HKUnit { + private var unit: LoopUnit { return data?.unit ?? .milligramsPerDeciliter } diff --git a/WatchApp Extension/Managers/LoopDataManager.swift b/WatchApp Extension/Managers/LoopDataManager.swift index b8b2d4a50f..37ccd2a4d4 100644 --- a/WatchApp Extension/Managers/LoopDataManager.swift +++ b/WatchApp Extension/Managers/LoopDataManager.swift @@ -193,7 +193,7 @@ extension LoopDataManager { } extension LoopDataManager { - var displayGlucoseUnit: HKUnit { + var displayGlucoseUnit: LoopUnit { activeContext?.displayGlucoseUnit ?? .milligramsPerDeciliter } } diff --git a/WatchApp Extension/Models/GlucoseChartData.swift b/WatchApp Extension/Models/GlucoseChartData.swift index 4bf9a2b2c8..868b53121a 100644 --- a/WatchApp Extension/Models/GlucoseChartData.swift +++ b/WatchApp Extension/Models/GlucoseChartData.swift @@ -7,13 +7,12 @@ // import Foundation -import HealthKit import LoopKit import LoopAlgorithm struct GlucoseChartData { - var unit: HKUnit? + var unit: LoopUnit? var correctionRange: GlucoseRangeSchedule? @@ -27,7 +26,7 @@ struct GlucoseChartData { } } - private(set) var historicalGlucoseRange: ClosedRange? + private(set) var historicalGlucoseRange: ClosedRange? var predictedGlucose: [SampleValue]? { didSet { @@ -35,9 +34,9 @@ struct GlucoseChartData { } } - private(set) var predictedGlucoseRange: ClosedRange? + private(set) var predictedGlucoseRange: ClosedRange? - init(unit: HKUnit?, correctionRange: GlucoseRangeSchedule?, preMealOverride: TemporaryScheduleOverride?, scheduleOverride: TemporaryScheduleOverride?, historicalGlucose: [SampleValue]?, predictedGlucose: [SampleValue]?) { + init(unit: LoopUnit?, correctionRange: GlucoseRangeSchedule?, preMealOverride: TemporaryScheduleOverride?, scheduleOverride: TemporaryScheduleOverride?, historicalGlucose: [SampleValue]?, predictedGlucose: [SampleValue]?) { self.unit = unit self.correctionRange = correctionRange self.preMealOverride = preMealOverride @@ -48,7 +47,7 @@ struct GlucoseChartData { self.predictedGlucoseRange = predictedGlucose?.quantityRange } - func chartableGlucoseRange(from interval: DateInterval) -> ClosedRange { + func chartableGlucoseRange(from interval: DateInterval) -> ClosedRange { let unit = self.unit ?? .milligramsPerDeciliter // Defaults @@ -85,8 +84,8 @@ struct GlucoseChartData { min = Swift.max(0, min.floored(to: unit.axisIncrement)) max = max.ceiled(to: unit.axisIncrement) - let lowerBound = HKQuantity(unit: unit, doubleValue: min) - let upperBound = HKQuantity(unit: unit, doubleValue: max) + let lowerBound = LoopQuantity(unit: unit, doubleValue: min) + let upperBound = LoopQuantity(unit: unit, doubleValue: max) return lowerBound...upperBound } @@ -106,7 +105,7 @@ struct GlucoseChartData { } } -private extension HKUnit { +private extension LoopUnit { var axisIncrement: Double { return chartableIncrement * 25 } diff --git a/WatchApp Extension/Models/GlucoseChartScaler.swift b/WatchApp Extension/Models/GlucoseChartScaler.swift index 953f5bf1ea..979eeb5e74 100644 --- a/WatchApp Extension/Models/GlucoseChartScaler.swift +++ b/WatchApp Extension/Models/GlucoseChartScaler.swift @@ -8,7 +8,6 @@ import Foundation import CoreGraphics -import HealthKit import LoopKit import WatchKit import LoopAlgorithm @@ -49,14 +48,14 @@ struct GlucoseChartScaler { return CGPoint(x: xCoordinate(for: date), y: yCoordinate(for: glucose)) } - func point(for glucose: SampleValue, unit: HKUnit) -> CGPoint { + func point(for glucose: SampleValue, unit: LoopUnit) -> CGPoint { return point(glucose.startDate, glucose.quantity.doubleValue(for: unit)) } // By default enforce a minimum height so that the range is visible func rect( for range: GlucoseChartValueHashable, - unit: HKUnit, + unit: LoopUnit, minHeight: CGFloat = 2, alignedToScreenScale screenScale: CGFloat = WKInterfaceDevice.current().screenScale ) -> CGRect { @@ -80,7 +79,7 @@ struct GlucoseChartScaler { } extension GlucoseChartScaler { - init(size: CGSize, dateInterval: DateInterval, glucoseRange: ClosedRange, unit: HKUnit, coordinateSystem: CoordinateSystem = .standard) { + init(size: CGSize, dateInterval: DateInterval, glucoseRange: ClosedRange, unit: LoopUnit, coordinateSystem: CoordinateSystem = .standard) { self.dates = dateInterval self.glucoseMin = glucoseRange.lowerBound.doubleValue(for: unit) self.glucoseMax = glucoseRange.upperBound.doubleValue(for: unit) @@ -90,8 +89,8 @@ extension GlucoseChartScaler { } } -extension ClosedRange where Bound == HKQuantity { - fileprivate func span(with unit: HKUnit) -> Double { +extension ClosedRange where Bound == LoopQuantity { + fileprivate func span(with unit: LoopUnit) -> Double { return upperBound.doubleValue(for: unit) - lowerBound.doubleValue(for: unit) } } diff --git a/WatchApp Extension/Scenes/GlucoseChartScene.swift b/WatchApp Extension/Scenes/GlucoseChartScene.swift index 8f69ff5e1d..010022908c 100644 --- a/WatchApp Extension/Scenes/GlucoseChartScene.swift +++ b/WatchApp Extension/Scenes/GlucoseChartScene.swift @@ -8,7 +8,6 @@ import Foundation import SpriteKit -import HealthKit import LoopKit import WatchKit import os.log diff --git a/WatchApp Extension/Scenes/GlucoseChartValueHashable.swift b/WatchApp Extension/Scenes/GlucoseChartValueHashable.swift index 5060e5d372..1809d72ca0 100644 --- a/WatchApp Extension/Scenes/GlucoseChartValueHashable.swift +++ b/WatchApp Extension/Scenes/GlucoseChartValueHashable.swift @@ -6,15 +6,14 @@ // import LoopKit -import HealthKit import LoopAlgorithm protocol GlucoseChartValueHashable { var start: Date { get } var end: Date { get } - var min: HKQuantity { get } - var max: HKQuantity { get } + var min: LoopQuantity { get } + var max: LoopQuantity { get } var chartHashValue: Int { get } } @@ -59,7 +58,7 @@ extension SampleValue { } -extension AbsoluteScheduleValue: GlucoseChartValueHashable where T == ClosedRange { +extension AbsoluteScheduleValue: GlucoseChartValueHashable where T == ClosedRange { var start: Date { return startDate } @@ -68,11 +67,11 @@ extension AbsoluteScheduleValue: GlucoseChartValueHashable where T == ClosedRang return endDate } - var min: HKQuantity { + var min: LoopQuantity { return value.lowerBound } - var max: HKQuantity { + var max: LoopQuantity { return value.upperBound } } @@ -95,11 +94,11 @@ struct TemporaryScheduleOverrideHashable: GlucoseChartValueHashable { return override.activeInterval.end } - var min: HKQuantity { + var min: LoopQuantity { return override.settings.targetRange!.lowerBound } - var max: HKQuantity { + var max: LoopQuantity { return override.settings.targetRange!.upperBound } } diff --git a/WatchApp Extension/View Models/CarbAndBolusFlowViewModel.swift b/WatchApp Extension/View Models/CarbAndBolusFlowViewModel.swift index 8241fab62a..d264f04992 100644 --- a/WatchApp Extension/View Models/CarbAndBolusFlowViewModel.swift +++ b/WatchApp Extension/View Models/CarbAndBolusFlowViewModel.swift @@ -8,7 +8,7 @@ import Foundation import Combine -import HealthKit +import LoopAlgorithm import WatchKit import WatchConnectivity import LoopKit @@ -115,13 +115,13 @@ final class CarbAndBolusFlowViewModel: ObservableObject { func recommendBolus(forGrams grams: Int, eatenAt carbEntryDate: Date, absorptionTime carbAbsorptionTime: CarbAbsorptionTime, lastEntryDate: Date) { let entry = NewCarbEntry( date: lastEntryDate, - quantity: HKQuantity(unit: .gram(), doubleValue: Double(grams)), + quantity: LoopQuantity(unit: .gram, doubleValue: Double(grams)), startDate: carbEntryDate, foodType: nil, absorptionTime: absorptionTime(for: carbAbsorptionTime) ) - guard entry.quantity.doubleValue(for: .gram()) > 0 else { + guard entry.quantity.doubleValue(for: .gram) > 0 else { return } diff --git a/WatchApp Extension/Views/Carb Entry & Bolus/BolusInput.swift b/WatchApp Extension/Views/Carb Entry & Bolus/BolusInput.swift index 4c01e5c4be..c87048f0cf 100644 --- a/WatchApp Extension/Views/Carb Entry & Bolus/BolusInput.swift +++ b/WatchApp Extension/Views/Carb Entry & Bolus/BolusInput.swift @@ -26,12 +26,12 @@ struct BolusInput: View { } private static let amountFormatter: NumberFormatter = { - let formatter = QuantityFormatter(for: .internationalUnit()) + let formatter = QuantityFormatter(for: .internationalUnit) return formatter.numberFormatter }() private static let recommendedAmountFormatter: NumberFormatter = { - let formatter = QuantityFormatter(for: .internationalUnit()) + let formatter = QuantityFormatter(for: .internationalUnit) return formatter.numberFormatter }() diff --git a/WatchApp Extension/Views/Carb Entry & Bolus/CarbAndBolusFlow.swift b/WatchApp Extension/Views/Carb Entry & Bolus/CarbAndBolusFlow.swift index 0c27958fe9..23761a82bf 100644 --- a/WatchApp Extension/Views/Carb Entry & Bolus/CarbAndBolusFlow.swift +++ b/WatchApp Extension/Views/Carb Entry & Bolus/CarbAndBolusFlow.swift @@ -7,7 +7,6 @@ // import SwiftUI -import HealthKit import LoopKit @@ -62,7 +61,7 @@ struct CarbAndBolusFlow: View { if let entry = entry { _carbEntryDate = State(initialValue: entry.startDate) - let initialCarbAmount = entry.quantity.doubleValue(for: .gram()) + let initialCarbAmount = entry.quantity.doubleValue(for: .gram) _carbAmount = State(initialValue: Int(initialCarbAmount)) } case .manualBolus: