Skip to content

Commit a1e4f99

Browse files
authored
Merge pull request #1584 from LoopKit/tidepool-merge
Tidepool merge
2 parents 75db2fe + 7608bf1 commit a1e4f99

File tree

95 files changed

+2597
-3496
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+2597
-3496
lines changed

Common/Extensions/NSBundle.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ extension Bundle {
3636
var appGroupSuiteName: String {
3737
return object(forInfoDictionaryKey: "AppGroupIdentifier") as! String
3838
}
39+
40+
var appStoreURL: String? {
41+
return object(forInfoDictionaryKey: "AppStoreURL") as? String
42+
}
3943

4044
var isAppExtension: Bool {
4145
return bundleURL.pathExtension == "appex"

Common/FeatureFlags.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ struct FeatureFlagConfiguration: Decodable {
1818
let fiaspInsulinModelEnabled: Bool
1919
let includeServicesInSettingsEnabled: Bool
2020
let manualDoseEntryEnabled: Bool
21+
let insulinDeliveryReservoirViewEnabled: Bool
2122
let mockTherapySettingsEnabled: Bool
2223
let nonlinearCarbModelEnabled: Bool
2324
let observeHealthKitSamplesFromOtherApps: Bool
@@ -83,6 +84,13 @@ struct FeatureFlagConfiguration: Decodable {
8384
self.manualDoseEntryEnabled = true
8485
#endif
8586

87+
// Swift compiler config is inverse, since the default state is enabled.
88+
#if INSULIN_DELIVERY_RESERVOIR_VIEW_DISABLED
89+
self.insulinDeliveryReservoirViewEnabled = false
90+
#else
91+
self.insulinDeliveryReservoirViewEnabled = true
92+
#endif
93+
8694
// Swift compiler config is inverse, since the default state is enabled.
8795
#if MOCK_THERAPY_SETTINGS_ENABLED
8896
self.mockTherapySettingsEnabled = true

Common/Models/StatusExtensionContext.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct GlucoseDisplayableContext: GlucoseDisplayable {
2424
let isStateValid: Bool
2525
let stateDescription: String
2626
let trendType: GlucoseTrend?
27+
let trendRate: HKQuantity?
2728
let isLocal: Bool
2829
let glucoseRangeCategory: GlucoseRangeCategory?
2930
}
@@ -136,6 +137,7 @@ extension GlucoseDisplayableContext: RawRepresentable {
136137
stateDescription = other.stateDescription
137138
isLocal = other.isLocal
138139
trendType = other.trendType
140+
trendRate = other.trendRate
139141
glucoseRangeCategory = other.glucoseRangeCategory
140142
}
141143

@@ -158,6 +160,12 @@ extension GlucoseDisplayableContext: RawRepresentable {
158160
trendType = nil
159161
}
160162

163+
if let trendRateUnit = rawValue["trendRateUnit"] as? String, let trendRateValue = rawValue["trendRateValue"] as? Double {
164+
trendRate = HKQuantity(unit: HKUnit(from: trendRateUnit), doubleValue: trendRateValue)
165+
} else {
166+
trendRate = nil
167+
}
168+
161169
if let glucoseRangeCategoryRawValue = rawValue["glucoseRangeCategory"] as? GlucoseRangeCategory.RawValue {
162170
glucoseRangeCategory = GlucoseRangeCategory(rawValue: glucoseRangeCategoryRawValue)
163171
} else {
@@ -172,6 +180,10 @@ extension GlucoseDisplayableContext: RawRepresentable {
172180
"isLocal": isLocal
173181
]
174182
raw["trendType"] = trendType?.rawValue
183+
if let trendRate = trendRate {
184+
raw["trendRateUnit"] = HKUnit.milligramsPerDeciliterPerMinute.unitString
185+
raw["trendRateValue"] = trendRate.doubleValue(for: HKUnit.milligramsPerDeciliterPerMinute)
186+
}
175187
raw["glucoseRangeCategory"] = glucoseRangeCategory?.rawValue
176188

177189
return raw

Common/Models/WatchContext.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ final class WatchContext: RawRepresentable {
2121
var displayGlucoseUnit: HKUnit?
2222

2323
var glucose: HKQuantity?
24-
var glucoseTrendRawValue: Int?
24+
var glucoseCondition: GlucoseCondition?
25+
var glucoseTrend: GlucoseTrend?
26+
var glucoseTrendRate: HKQuantity?
2527
var glucoseDate: Date?
2628
var glucoseIsDisplayOnly: Bool?
2729
var glucoseWasUserEntered: Bool?
@@ -68,7 +70,15 @@ final class WatchContext: RawRepresentable {
6870
glucose = HKQuantity(unit: unit, doubleValue: glucoseValue)
6971
}
7072

71-
glucoseTrendRawValue = rawValue["gt"] as? Int
73+
if let rawGlucoseCondition = rawValue["gc"] as? GlucoseCondition.RawValue {
74+
glucoseCondition = GlucoseCondition(rawValue: rawGlucoseCondition)
75+
}
76+
if let rawGlucoseTrend = rawValue["gt"] as? GlucoseTrend.RawValue {
77+
glucoseTrend = GlucoseTrend(rawValue: rawGlucoseTrend)
78+
}
79+
if let glucoseTrendRateUnitString = rawValue["gtru"] as? String, let glucoseTrendRateValue = rawValue["gtrv"] as? Double {
80+
glucoseTrendRate = HKQuantity(unit: HKUnit(from: glucoseTrendRateUnitString), doubleValue: glucoseTrendRateValue)
81+
}
7282
glucoseDate = rawValue["gd"] as? Date
7383
glucoseIsDisplayOnly = rawValue["gdo"] as? Bool
7484
glucoseWasUserEntered = rawValue["gue"] as? Bool
@@ -114,7 +124,13 @@ final class WatchContext: RawRepresentable {
114124
raw["gu"] = displayGlucoseUnit?.unitString
115125
raw["gv"] = glucose?.doubleValue(for: unit)
116126

117-
raw["gt"] = glucoseTrendRawValue
127+
raw["gc"] = glucoseCondition?.rawValue
128+
raw["gt"] = glucoseTrend?.rawValue
129+
if let glucoseTrendRate = glucoseTrendRate {
130+
let unitPerMinute = unit.unitDivided(by: .minute())
131+
raw["gtru"] = unitPerMinute.unitString
132+
raw["gtrv"] = glucoseTrendRate.doubleValue(for: unitPerMinute)
133+
}
118134
raw["gd"] = glucoseDate
119135
raw["gdo"] = glucoseIsDisplayOnly
120136
raw["gue"] = glucoseWasUserEntered
@@ -149,7 +165,9 @@ extension WatchContext {
149165
if let quantity = glucose, let date = glucoseDate, let syncIdentifier = glucoseSyncIdentifier {
150166
return NewGlucoseSample(date: date,
151167
quantity: quantity,
152-
trend: glucoseTrendRawValue.flatMap { GlucoseTrend(rawValue: $0) },
168+
condition: glucoseCondition,
169+
trend: glucoseTrend,
170+
trendRate: glucoseTrendRate,
153171
isDisplayOnly: glucoseIsDisplayOnly ?? false,
154172
wasUserEntered: glucoseWasUserEntered ?? false,
155173
syncIdentifier: syncIdentifier, syncVersion: 0)

Common/Models/WatchHistoricalGlucose.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ extension WatchHistoricalGlucose: RawRepresentable {
4141
let syncVersions: [Int?]
4242
let startDates: [Date]
4343
let quantities: [Double]
44+
let conditions: [GlucoseCondition?]
4445
let trends: [GlucoseTrend?]
46+
let trendRates: [Double?]
4547
let isDisplayOnlys: [Bool]
4648
let wasUserEntereds: [Bool]
4749
let devices: [Data?]
@@ -54,7 +56,9 @@ extension WatchHistoricalGlucose: RawRepresentable {
5456
self.syncVersions = samples.map { $0.syncVersion }
5557
self.startDates = samples.map { $0.startDate }
5658
self.quantities = samples.map { $0.quantity.doubleValue(for: .milligramsPerDeciliter) }
59+
self.conditions = samples.map { $0.condition }
5760
self.trends = samples.map { $0.trend }
61+
self.trendRates = samples.map { $0.trendRate.flatMap { $0.doubleValue(for: .milligramsPerDeciliterPerMinute) } }
5862
self.isDisplayOnlys = samples.map { $0.isDisplayOnly }
5963
self.wasUserEntereds = samples.map { $0.wasUserEntered }
6064
self.devices = samples.map { try? WatchHistoricalGlucose.encoder.encode($0.device) }
@@ -69,7 +73,9 @@ extension WatchHistoricalGlucose: RawRepresentable {
6973
syncVersion: syncVersions[$0],
7074
startDate: startDates[$0],
7175
quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: quantities[$0]),
76+
condition: conditions[$0],
7277
trend: trends[$0],
78+
trendRate: trendRates[$0].flatMap { HKQuantity(unit: .milligramsPerDeciliterPerMinute, doubleValue: $0) },
7379
isDisplayOnly: isDisplayOnlys[$0],
7480
wasUserEntered: wasUserEntereds[$0],
7581
device: devices[$0].flatMap { try? HKDevice(from: $0) },

DoseMathTests/DoseMathTests.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ class RecommendTempBasalTests: XCTestCase {
194194

195195
XCTAssertEqual(0.8, dose!.basalAdjustment!.unitsPerHour, accuracy: 1.0 / 40.0)
196196
XCTAssertEqual(TimeInterval(minutes: 30), dose!.basalAdjustment!.duration)
197-
XCTAssertEqual(0, dose!.bolusUnits)
197+
XCTAssertEqual(0, dose!.bolusUnits!)
198198
}
199199

200200
func testStartHighEndInRange() {
@@ -277,7 +277,7 @@ class RecommendTempBasalTests: XCTestCase {
277277

278278
XCTAssertEqual(0, dose!.basalAdjustment!.unitsPerHour)
279279
XCTAssertEqual(TimeInterval(minutes: 0), dose!.basalAdjustment!.duration)
280-
XCTAssertEqual(0, dose!.bolusUnits)
280+
XCTAssertEqual(0, dose!.bolusUnits!)
281281
}
282282

283283
func testStartHighEndInRangeAutomaticBolusWithOverride() {
@@ -441,7 +441,7 @@ class RecommendTempBasalTests: XCTestCase {
441441

442442
XCTAssertEqual(0, dose!.basalAdjustment!.unitsPerHour)
443443
XCTAssertEqual(TimeInterval(minutes: 0), dose!.basalAdjustment!.duration)
444-
XCTAssertEqual(0, dose!.bolusUnits)
444+
XCTAssertEqual(0, dose!.bolusUnits!)
445445
}
446446

447447
func testCorrectLowAtMin() {
@@ -510,7 +510,7 @@ class RecommendTempBasalTests: XCTestCase {
510510

511511
XCTAssertEqual(0, dose!.basalAdjustment!.unitsPerHour)
512512
XCTAssertEqual(TimeInterval(minutes: 0), dose!.basalAdjustment!.duration)
513-
XCTAssertEqual(0, dose!.bolusUnits)
513+
XCTAssertEqual(0, dose!.bolusUnits!)
514514

515515
dose = glucose.recommendedAutomaticDose(
516516
to: glucoseTargetRange,
@@ -562,7 +562,7 @@ class RecommendTempBasalTests: XCTestCase {
562562

563563
XCTAssertEqual(0, dose!.basalAdjustment!.unitsPerHour)
564564
XCTAssertEqual(TimeInterval(minutes: 30), dose!.basalAdjustment!.duration)
565-
XCTAssertEqual(0, dose!.bolusUnits)
565+
XCTAssertEqual(0, dose!.bolusUnits!)
566566
}
567567

568568
func testStartHighEndLowExponentialModel() {
@@ -662,7 +662,7 @@ class RecommendTempBasalTests: XCTestCase {
662662

663663
XCTAssertEqual(0, dose!.basalAdjustment!.unitsPerHour)
664664
XCTAssertEqual(TimeInterval(minutes: 0), dose!.basalAdjustment!.duration)
665-
XCTAssertEqual(0, dose!.bolusUnits)
665+
XCTAssertEqual(0, dose!.bolusUnits!)
666666
}
667667

668668
func testFlatAndHigh() {
@@ -699,7 +699,7 @@ class RecommendTempBasalTests: XCTestCase {
699699
)
700700

701701
XCTAssertNil(dose!.basalAdjustment)
702-
XCTAssertEqual(0.85, dose!.bolusUnits, accuracy: 1.0 / 40.0)
702+
XCTAssertEqual(0.85, dose!.bolusUnits!, accuracy: 1.0 / 40.0)
703703
}
704704

705705
func testFlatAndHighAutomaticBolusWithOverride() {
@@ -720,7 +720,7 @@ class RecommendTempBasalTests: XCTestCase {
720720

721721
XCTAssertEqual(0.8, dose!.basalAdjustment!.unitsPerHour, accuracy: 1.0 / 40.0)
722722
XCTAssertEqual(TimeInterval(minutes: 30), dose!.basalAdjustment!.duration)
723-
XCTAssertEqual(0.85, dose!.bolusUnits, accuracy: 1.0 / 40.0)
723+
XCTAssertEqual(0.85, dose!.bolusUnits!, accuracy: 1.0 / 40.0)
724724

725725
// Continue temp
726726
let lastTempBasal = DoseEntry(
@@ -745,7 +745,7 @@ class RecommendTempBasalTests: XCTestCase {
745745
)
746746

747747
XCTAssertNil(dose!.basalAdjustment)
748-
XCTAssertEqual(0.85, dose!.bolusUnits, accuracy: 1.0 / 40.0)
748+
XCTAssertEqual(0.85, dose!.bolusUnits!, accuracy: 1.0 / 40.0)
749749

750750
}
751751

@@ -785,7 +785,7 @@ class RecommendTempBasalTests: XCTestCase {
785785
)
786786

787787
XCTAssertNil(dose!.basalAdjustment)
788-
XCTAssertEqual(0.2, dose!.bolusUnits, accuracy: 1.0 / 40.0)
788+
XCTAssertEqual(0.2, dose!.bolusUnits!, accuracy: 1.0 / 40.0)
789789
}
790790

791791
func testHighAndFallingExponentialModel() {
@@ -822,7 +822,7 @@ class RecommendTempBasalTests: XCTestCase {
822822
)
823823

824824
XCTAssertNil(dose!.basalAdjustment)
825-
XCTAssertEqual(0.2, dose!.bolusUnits, accuracy: 1.0 / 40.0)
825+
XCTAssertEqual(0.2, dose!.bolusUnits!, accuracy: 1.0 / 40.0)
826826
}
827827

828828
func testInRangeAndRising() {

Loop Status Extension/StatusViewController.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class StatusViewController: UIViewController, NCWidgetProviding {
8080
lazy var glucoseStore = GlucoseStore(
8181
healthStore: healthStore,
8282
observeHealthKitSamplesFromOtherApps: FeatureFlags.observeHealthKitSamplesFromOtherApps,
83+
storeSamplesToHealthKit: false,
8384
cacheStore: cacheStore,
8485
observationEnabled: false,
8586
provenanceIdentifier: HKSource.default().bundleIdentifier
@@ -88,6 +89,7 @@ class StatusViewController: UIViewController, NCWidgetProviding {
8889
lazy var doseStore = DoseStore(
8990
healthStore: healthStore,
9091
observeHealthKitSamplesFromOtherApps: FeatureFlags.observeHealthKitSamplesFromOtherApps,
92+
storeSamplesToHealthKit: false,
9193
cacheStore: cacheStore,
9294
observationEnabled: false,
9395
insulinModelProvider: PresetInsulinModelProvider(defaultRapidActingModel: defaults?.defaultRapidActingModel),

Loop.xcconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ MAIN_APP_DISPLAY_NAME = Loop
1616
// Appication icon [DEFAULT]
1717
APPICON_NAME = AppIcon
1818

19+
// App Store URL
20+
APP_STORE_URL =
21+
1922
// Features [DEFAULT]
2023
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited)
2124

0 commit comments

Comments
 (0)