Skip to content

Commit 239afba

Browse files
committed
Merge branch 'dev-ivan' into dev-spike-microbolus-dt
* dev-ivan: MB with COB and without COB work independently revert notification names Cartfile.resolved Notification names changed in LoopKit (LoopKit#1165)
2 parents b0c63b4 + 959fe30 commit 239afba

9 files changed

Lines changed: 80 additions & 63 deletions

File tree

Common/Models/WatchContext.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ final class WatchContext: RawRepresentable {
3131
var lastNetTempBasalDose: Double?
3232
var lastNetTempBasalDate: Date?
3333
var recommendedBolusDose: Double?
34-
var isMicrobolusesActive: Bool?
34+
var doNotOpenBolusScreenWithMicroboluses: Bool?
3535

3636
var cob: Double?
3737
var iob: Double?
@@ -69,7 +69,7 @@ final class WatchContext: RawRepresentable {
6969
lastNetTempBasalDate = rawValue["bad"] as? Date
7070
recommendedBolusDose = rawValue["rbo"] as? Double
7171
cob = rawValue["cob"] as? Double
72-
isMicrobolusesActive = rawValue["mb"] as? Bool
72+
doNotOpenBolusScreenWithMicroboluses = rawValue["mb"] as? Bool
7373

7474
cgmManagerState = rawValue["cgmManagerState"] as? CGMManager.RawStateValue
7575

@@ -102,7 +102,7 @@ final class WatchContext: RawRepresentable {
102102
raw["r"] = reservoir
103103
raw["rbo"] = recommendedBolusDose
104104
raw["rp"] = reservoirPercentage
105-
raw["mb"] = isMicrobolusesActive
105+
raw["mb"] = doNotOpenBolusScreenWithMicroboluses
106106

107107
raw["pg"] = predictedGlucose?.rawValue
108108

Loop.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3369,7 +3369,7 @@
33693369
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
33703370
CODE_SIGN_IDENTITY = "iPhone Developer: loudnate@gmail.com (XZN842LDLT)";
33713371
COPY_PHASE_STRIP = NO;
3372-
CURRENT_PROJECT_VERSION = 091119a;
3372+
CURRENT_PROJECT_VERSION = 131119a;
33733373
DEBUG_INFORMATION_FORMAT = dwarf;
33743374
ENABLE_STRICT_OBJC_MSGSEND = YES;
33753375
ENABLE_TESTABILITY = YES;
@@ -3441,7 +3441,7 @@
34413441
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
34423442
CODE_SIGN_IDENTITY = "iPhone Developer: loudnate@gmail.com (XZN842LDLT)";
34433443
COPY_PHASE_STRIP = NO;
3444-
CURRENT_PROJECT_VERSION = 091119a;
3444+
CURRENT_PROJECT_VERSION = 131119a;
34453445
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
34463446
ENABLE_NS_ASSERTIONS = NO;
34473447
ENABLE_STRICT_OBJC_MSGSEND = YES;

Loop/Managers/LoopDataManager.swift

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,6 @@ extension LoopDataManager {
655655

656656
let enactBolusPublisher = Deferred {
657657
Future<Bool, Error> { promise in
658-
guard self.settings.isMicrobolusesActive else {
659-
return promise(.success(false))
660-
}
661658
self.calculateAndEnactMicroBolusIfNeeded { enacted, error in
662659
if let error = error {
663660
promise(.failure(error))
@@ -1075,8 +1072,17 @@ extension LoopDataManager {
10751072
private func calculateAndEnactMicroBolusIfNeeded(_ completion: @escaping (_ enacted: Bool, _ error: Error?) -> Void) {
10761073
dispatchPrecondition(condition: .onQueue(dataAccessQueue))
10771074

1078-
guard settings.isMicrobolusesActive else {
1079-
logger.debug("Closed loop or microboluses disabled. Cancel microbolus calculation.")
1075+
guard settings.dosingEnabled else {
1076+
logger.debug("Closed loop disabled. Cancel microbolus calculation.")
1077+
completion(false, nil)
1078+
return
1079+
}
1080+
1081+
let cob = carbsOnBoard?.quantity.doubleValue(for: .gram()) ?? 0
1082+
let cobChek = (cob > 0 && settings.microbolusesEnabled) || (cob == 0 && settings.microbolusesWithoutCarbsEnabled)
1083+
1084+
guard cobChek else {
1085+
logger.debug("Microboluses disabled.")
10801086
completion(false, nil)
10811087
return
10821088
}
@@ -1107,13 +1113,6 @@ extension LoopDataManager {
11071113
return
11081114
}
11091115

1110-
let cob = carbsOnBoard?.quantity.doubleValue(for: .gram()) ?? 0
1111-
guard cob != 0 || settings.microbolusesWithoutCarbsEnabled else {
1112-
logger.debug("Microboluses without COB disabled.")
1113-
completion(false, nil)
1114-
return
1115-
}
1116-
11171116
guard let glucose = self.glucoseStore.latestGlucose, let predictedGlucose = predictedGlucose else {
11181117
logger.debug("Glucose data not found.")
11191118
completion(false, nil)

Loop/Managers/WatchDataManager.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ final class WatchDataManager: NSObject {
155155
context.recommendedBolusDose = state.recommendedBolus?.recommendation.amount
156156
context.cob = state.carbsOnBoard?.quantity.doubleValue(for: HKUnit.gram())
157157
context.glucoseTrendRawValue = self.deviceManager.sensorState?.trendType?.rawValue
158-
context.isMicrobolusesActive = loopManager.settings.isMicrobolusesActive
158+
context.doNotOpenBolusScreenWithMicroboluses = loopManager.settings.dosingEnabled
159+
&& loopManager.settings.microbolusesEnabled
160+
&& !loopManager.settings.microbolusesOpenBolusScreen
159161

160162
context.cgmManagerState = self.deviceManager.cgmManager?.rawValue
161163

Loop/View Controllers/SettingsTableViewController.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,15 @@ final class SettingsTableViewController: UITableViewController {
178178
cell.textLabel?.text = NSLocalizedString("Microboluses", comment: "The title text for the Microboluses cell")
179179
let settings = dataManager.loopManager.settings
180180
cell.detailTextLabel?.text = {
181-
guard settings.isMicrobolusesActive else {
181+
guard settings.dosingEnabled else {
182182
return "Disabled"
183183
}
184-
guard settings.microbolusesWithoutCarbsEnabled else {
185-
return "With COB"
184+
switch (settings.microbolusesWithoutCarbsEnabled, settings.microbolusesEnabled) {
185+
case (true, true): return "Always"
186+
case (false, true): return "With Carbs"
187+
case (true, false): return "Without Carbs"
188+
default: return "Disabled"
186189
}
187-
return "Always"
188190
}()
189191
cell.accessoryType = .disclosureIndicator
190192

@@ -599,7 +601,8 @@ final class SettingsTableViewController: UITableViewController {
599601
microbolusesWithoutCOB: settings.microbolusesWithoutCarbsEnabled,
600602
withoutCOBValue: settings.microbolusesWithoutCarbsSize,
601603
safeMode: settings.microbolusesSafeMode,
602-
microbolusesMinimumBolusSize: settings.microbolusesMinimumBolusSize
604+
microbolusesMinimumBolusSize: settings.microbolusesMinimumBolusSize,
605+
openBolusScreen: settings.microbolusesOpenBolusScreen
603606
)
604607

605608
microbolusCancellable = viewModel.changes()
@@ -610,6 +613,7 @@ final class SettingsTableViewController: UITableViewController {
610613
settings.microbolusesWithoutCarbsSize = result.withoutCOBValue
611614
settings.microbolusesSafeMode = result.safeMode
612615
settings.microbolusesMinimumBolusSize = result.microbolusesMinimumBolusSize
616+
settings.microbolusesOpenBolusScreen = result.openBolusScreen
613617

614618
self?.dataManager.loopManager.settings = settings
615619
self?.tableView.reloadRows(at: [indexPath], with: .none)

Loop/View Controllers/StatusTableViewController.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,12 +1115,14 @@ final class StatusTableViewController: ChartsTableViewController {
11151115
}
11161116
}
11171117

1118-
let isMicrobolusesActive = deviceManager.loopManager.settings.isMicrobolusesActive
1118+
let notOpenBolusScreen = deviceManager.loopManager.settings.dosingEnabled
1119+
&& deviceManager.loopManager.settings.microbolusesEnabled
1120+
&& !deviceManager.loopManager.settings.microbolusesOpenBolusScreen
11191121
deviceManager.loopManager.addCarbEntryAndRecommendBolus(updatedEntry) { (result) -> Void in
11201122
DispatchQueue.main.async {
11211123
switch result {
11221124
case .success(let recommendation):
1123-
guard !isMicrobolusesActive else { return }
1125+
guard !notOpenBolusScreen else { return }
11241126
if self.active && self.visible, let bolus = recommendation?.amount, bolus > 0 {
11251127
self.performSegue(withIdentifier: BolusViewController.className, sender: recommendation)
11261128
}

Loop/Views/MicrobolusView.swift

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Combine
1111
import LoopCore
1212

1313
struct MicrobolusView: View {
14-
typealias Result = (microbolusesWithCOB: Bool, withCOBValue: Double, microbolusesWithoutCOB: Bool, withoutCOBValue: Double, safeMode: Microbolus.SafeMode, microbolusesMinimumBolusSize: Double)
14+
typealias Result = (microbolusesWithCOB: Bool, withCOBValue: Double, microbolusesWithoutCOB: Bool, withoutCOBValue: Double, safeMode: Microbolus.SafeMode, microbolusesMinimumBolusSize: Double, openBolusScreen: Bool)
1515

1616
final class ViewModel: ObservableObject {
1717
@Published var microbolusesWithCOB: Bool
@@ -20,6 +20,7 @@ struct MicrobolusView: View {
2020
@Published var withoutCOBValue: Double
2121
@Published var safeMode: Microbolus.SafeMode
2222
@Published var microbolusesMinimumBolusSize: Double
23+
@Published var openBolusScreen: Bool
2324

2425
@Published fileprivate var pickerWithCOBIndex: Int
2526
@Published fileprivate var pickerWithoutCOBIndex: Int
@@ -31,13 +32,14 @@ struct MicrobolusView: View {
3132

3233
private var cancellable: AnyCancellable!
3334

34-
init(microbolusesWithCOB: Bool, withCOBValue: Double, microbolusesWithoutCOB: Bool, withoutCOBValue: Double, safeMode: Microbolus.SafeMode, microbolusesMinimumBolusSize: Double) {
35+
init(microbolusesWithCOB: Bool, withCOBValue: Double, microbolusesWithoutCOB: Bool, withoutCOBValue: Double, safeMode: Microbolus.SafeMode, microbolusesMinimumBolusSize: Double, openBolusScreen: Bool) {
3536
self.microbolusesWithCOB = microbolusesWithCOB
3637
self.withCOBValue = withCOBValue
3738
self.microbolusesWithoutCOB = microbolusesWithoutCOB
3839
self.withoutCOBValue = withoutCOBValue
3940
self.safeMode = safeMode
4041
self.microbolusesMinimumBolusSize = microbolusesMinimumBolusSize
42+
self.openBolusScreen = openBolusScreen
4143

4244
pickerWithCOBIndex = values.firstIndex(of: Int(withCOBValue)) ?? 0
4345
pickerWithoutCOBIndex = values.firstIndex(of: Int(withoutCOBValue)) ?? 0
@@ -63,19 +65,19 @@ struct MicrobolusView: View {
6365
}
6466

6567
func changes() -> AnyPublisher<Result, Never> {
66-
// Publishers.CombineLatest5
67-
Publishers.CombineLatest3(
68+
Publishers.CombineLatest4(
6869
Publishers.CombineLatest4(
6970
$microbolusesWithCOB,
7071
$withCOBValue,
7172
$microbolusesWithoutCOB,
7273
$withoutCOBValue
7374
),
7475
$safeMode,
75-
$microbolusesMinimumBolusSize
76+
$microbolusesMinimumBolusSize,
77+
$openBolusScreen
7678
)
77-
.map { ($0.0.0, $0.0.1, $0.0.2, $0.0.3, $0.1, $0.2) }
78-
.eraseToAnyPublisher()
79+
.map { ($0.0.0, $0.0.1, $0.0.2, $0.0.3, $0.1, $0.2, $0.3) }
80+
.eraseToAnyPublisher()
7981
}
8082
}
8183

@@ -112,38 +114,39 @@ struct MicrobolusView: View {
112114
}
113115
}
114116

115-
if viewModel.microbolusesWithCOB {
116-
Section(footer:
117-
Text("This is the minimum Microbolus size in units that will be delivered. Only if the Microbolus calculated is equal to or greater than this number of units will a bolus be delivered.")
118-
) {
119-
Picker(selection: $viewModel.pickerMinimumBolusSizeIndex, label: Text("Minimum Bolus Size")) {
120-
ForEach(0 ..< viewModel.minimumBolusSizeValues.count) { index in Text(String(format: "%.2f U", self.viewModel.minimumBolusSizeValues[index])).tag(index)
121-
}
117+
Section(footer:
118+
Text("This is the maximum minutes of basal that can be delivered as a single microbolus without COB.")
119+
) {
120+
Toggle (isOn: $viewModel.microbolusesWithoutCOB) {
121+
Text("Enable Without Carbs")
122+
}
123+
Picker(selection: $viewModel.pickerWithoutCOBIndex, label: Text("Maximum Size")) {
124+
ForEach(0 ..< viewModel.values.count) { index in
125+
Text("\(self.viewModel.values[index])").tag(index)
122126
}
123127
}
128+
}
124129

125-
Section(footer:
126-
Text("This is the maximum minutes of basal that can be delivered as a single microbolus without COB.")
127-
) {
128-
Toggle (isOn: $viewModel.microbolusesWithoutCOB) {
129-
Text("Enable Without Carbs")
130-
}
131-
Picker(selection: $viewModel.pickerWithoutCOBIndex, label: Text("Maximum Size")) {
132-
ForEach(0 ..< viewModel.values.count) { index in
133-
Text("\(self.viewModel.values[index])").tag(index)
134-
}
130+
Section(header: Text("Safe Mode").font(.headline), footer:
131+
Text("• If Enabled and predicted glucose in 15 minutes is lower than current glucose, microboluses are not allowed.\n• If Limited and the predicted glucose in 15 minutes is lower than current glucose, the maximum microbolus size is limited to 30 basal minutes.\n• If Disabled, there are no restrictions.")
132+
) {
133+
Picker(selection: $viewModel.safeMode, label: Text("Safe Mode")) {
134+
ForEach(Microbolus.SafeMode.allCases, id: \.self) { value in
135+
Text("\(value.displayName)").tag(value)
135136
}
136137
}
138+
.pickerStyle(SegmentedPickerStyle())
139+
}
137140

138-
Section(header: Text("Safe Mode").font(.headline), footer:
139-
Text("• If Enabled and predicted glucose in 15 minutes is lower than current glucose, microboluses are not allowed.\n• If Limited and the predicted glucose in 15 minutes is lower than current glucose, the maximum microbolus size is limited to 30 basal minutes.\n• If Disabled, there are no restrictions.")
140-
) {
141-
Picker(selection: $viewModel.safeMode, label: Text("Safe Mode")) {
142-
ForEach(Microbolus.SafeMode.allCases, id: \.self) { value in
143-
Text("\(value.displayName)").tag(value)
144-
}
141+
Section(header: Text("Other Options").font(.headline), footer:
142+
Text("This is the minimum microbolus size in units that will be delivered. Only if the microbolus calculated is equal to or greater than this number of units will a bolus be delivered.")
143+
) {
144+
Toggle (isOn: $viewModel.openBolusScreen) {
145+
Text("Open Bolus screen after Carbs")
146+
}
147+
Picker(selection: $viewModel.pickerMinimumBolusSizeIndex, label: Text("Minimum Bolus Size")) {
148+
ForEach(0 ..< viewModel.minimumBolusSizeValues.count) { index in Text(String(format: "%.2f U", self.viewModel.minimumBolusSizeValues[index])).tag(index)
145149
}
146-
.pickerStyle(SegmentedPickerStyle())
147150
}
148151
}
149152

@@ -173,9 +176,11 @@ struct MicrobolusView_Previews: PreviewProvider {
173176
microbolusesWithoutCOB: false,
174177
withoutCOBValue: 30,
175178
safeMode: .enabled,
176-
microbolusesMinimumBolusSize: 0.0
179+
microbolusesMinimumBolusSize: 0.0,
180+
openBolusScreen: false
177181
)
178182
)
179183
.environment(\.colorScheme, .dark)
184+
.previewLayout(.sizeThatFits)
180185
}
181186
}

LoopCore/LoopSettings.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public struct LoopSettings: Equatable {
2323

2424
public var microbolusesMinimumBolusSize = 0.0
2525

26+
public var microbolusesOpenBolusScreen = false
27+
2628
public let dynamicCarbAbsorptionEnabled = true
2729

2830
public static let defaultCarbAbsorptionTimes: CarbStore.DefaultAbsorptionTimes = (fast: .hours(2), medium: .hours(3), slow: .hours(4))
@@ -67,8 +69,6 @@ public struct LoopSettings: Equatable {
6769
return glucoseTargetRangeSchedule?.unit
6870
}
6971

70-
public var isMicrobolusesActive: Bool { microbolusesEnabled && dosingEnabled }
71-
7272
// MARK - Push Notifications
7373

7474
public var deviceToken: Data?
@@ -231,6 +231,10 @@ extension LoopSettings: RawRepresentable {
231231
self.microbolusesMinimumBolusSize = microbolusesMinimumBolusSize
232232
}
233233

234+
if let microbolusesOpenBolusScreen = rawValue["microbolusesOpenBolusScreen"] as? Bool {
235+
self.microbolusesOpenBolusScreen = microbolusesOpenBolusScreen
236+
}
237+
234238
if let glucoseRangeScheduleRawValue = rawValue["glucoseTargetRangeSchedule"] as? GlucoseRangeSchedule.RawValue {
235239
self.glucoseTargetRangeSchedule = GlucoseRangeSchedule(rawValue: glucoseRangeScheduleRawValue)
236240

@@ -280,7 +284,8 @@ extension LoopSettings: RawRepresentable {
280284
"microbolusesWithoutCarbsEnabled": microbolusesWithoutCarbsEnabled,
281285
"microbolusesWithoutCarbsSize": microbolusesWithoutCarbsSize,
282286
"microbolusesSafeMode": microbolusesSafeMode.rawValue,
283-
"microbolusesMinimumBolusSize": microbolusesMinimumBolusSize
287+
"microbolusesMinimumBolusSize": microbolusesMinimumBolusSize,
288+
"microbolusesOpenBolusScreen": microbolusesOpenBolusScreen
284289
]
285290

286291
raw["glucoseTargetRangeSchedule"] = glucoseTargetRangeSchedule?.rawValue

WatchApp Extension/Controllers/AddCarbsInterfaceController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ final class AddCarbsInterfaceController: WKInterfaceController, IdentifiableClas
216216
loopManager.addConfirmedCarbEntry(entry.carbEntry)
217217
loopManager.updateContext(context)
218218

219-
let isMicrobolusesActive = context.isMicrobolusesActive ?? false
220-
if let units = context.recommendedBolusDose, units > 0.0, !isMicrobolusesActive {
219+
let doNotOpenBolusScreenWithMicroboluses = context.doNotOpenBolusScreenWithMicroboluses ?? false
220+
if let units = context.recommendedBolusDose, units > 0.0, !doNotOpenBolusScreenWithMicroboluses {
221221
WKExtension.shared().rootInterfaceController?.presentController(withName: BolusInterfaceController.className, context: context)
222222
}
223223
}

0 commit comments

Comments
 (0)