Skip to content

Commit 31974cb

Browse files
committed
model and view
1 parent 0d28665 commit 31974cb

File tree

4 files changed

+128
-35
lines changed

4 files changed

+128
-35
lines changed

Loop/Managers/LoopDataManager.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,8 @@ extension LoopDataManager {
10781078
return
10791079
}
10801080

1081+
let overrideLowerBound = settings.scheduleOverride?.settings.targetRange?.lowerBound //HKQuantity
1082+
10811083
guard let bolusState = delegate?.bolusState, case .none = bolusState else {
10821084
logger.debug("Already bolusing. Cancel microbolus calculation.")
10831085
completion(false, nil)

Loop/View Controllers/SettingsTableViewController.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -593,16 +593,13 @@ final class SettingsTableViewController: UITableViewController {
593593
show(vc, sender: sender)
594594
case .microbolus:
595595
var settings = dataManager.loopManager.settings
596-
guard settings.dosingEnabled else { break }
596+
guard settings.dosingEnabled,
597+
let unit = dataManager.loopManager.glucoseStore.preferredUnit
598+
else { break }
597599

598600
let viewModel = MicrobolusView.ViewModel(
599-
microbolusesWithCOB: settings.microbolusSettings.enabled,
600-
withCOBValue: settings.microbolusSettings.size,
601-
microbolusesWithoutCOB: settings.microbolusSettings.enabledWithoutCarbs,
602-
withoutCOBValue: settings.microbolusSettings.sizeWithoutCarbs,
603-
safeMode: settings.microbolusSettings.safeMode,
604-
microbolusesMinimumBolusSize: settings.microbolusSettings.minimumBolusSize,
605-
openBolusScreen: settings.microbolusSettings.shouldOpenBolusScreen
601+
settings: settings.microbolusSettings,
602+
glucoseUnit: unit
606603
)
607604

608605
microbolusCancellable = viewModel.changes()

Loop/Views/MicrobolusView.swift

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import SwiftUI
1010
import Combine
1111
import LoopCore
12+
import LoopKit
13+
import HealthKit
1214

1315
struct MicrobolusView: View {
1416
final class ViewModel: ObservableObject {
@@ -19,6 +21,8 @@ struct MicrobolusView: View {
1921
@Published var safeMode: Microbolus.SafeMode
2022
@Published var microbolusesMinimumBolusSize: Double
2123
@Published var openBolusScreen: Bool
24+
@Published var disableByOverride: Bool
25+
@Published var lowerBound: Double
2226

2327
@Published fileprivate var pickerWithCOBIndex: Int
2428
@Published fileprivate var pickerWithoutCOBIndex: Int
@@ -29,19 +33,25 @@ struct MicrobolusView: View {
2933
fileprivate let minimumBolusSizeValues = stride(from: 0.0, to: 0.51, by: 0.05).map { $0 }
3034

3135
private var cancellable: AnyCancellable!
36+
fileprivate let formatter = QuantityFormatter()
37+
fileprivate let unit: HKUnit
3238

33-
init(microbolusesWithCOB: Bool, withCOBValue: Double, microbolusesWithoutCOB: Bool, withoutCOBValue: Double, safeMode: Microbolus.SafeMode, microbolusesMinimumBolusSize: Double, openBolusScreen: Bool) {
34-
self.microbolusesWithCOB = microbolusesWithCOB
35-
self.withCOBValue = withCOBValue
36-
self.microbolusesWithoutCOB = microbolusesWithoutCOB
37-
self.withoutCOBValue = withoutCOBValue
38-
self.safeMode = safeMode
39-
self.microbolusesMinimumBolusSize = microbolusesMinimumBolusSize
40-
self.openBolusScreen = openBolusScreen
39+
init(settings: Microbolus.Settings, glucoseUnit: HKUnit) {
40+
self.microbolusesWithCOB = settings.enabled
41+
self.withCOBValue = settings.size
42+
self.microbolusesWithoutCOB = settings.enabledWithoutCarbs
43+
self.withoutCOBValue = settings.sizeWithoutCarbs
44+
self.safeMode = settings.safeMode
45+
self.microbolusesMinimumBolusSize = settings.minimumBolusSize
46+
self.openBolusScreen = settings.shouldOpenBolusScreen
47+
self.disableByOverride = settings.disableByOverride
48+
self.lowerBound = settings.overrideLowerBound
49+
self.unit = glucoseUnit
50+
formatter.setPreferredNumberFormatter(for: glucoseUnit)
4151

42-
pickerWithCOBIndex = values.firstIndex(of: Int(withCOBValue)) ?? 0
43-
pickerWithoutCOBIndex = values.firstIndex(of: Int(withoutCOBValue)) ?? 0
44-
pickerMinimumBolusSizeIndex = minimumBolusSizeValues.firstIndex(of: Double(microbolusesMinimumBolusSize)) ?? 0
52+
pickerWithCOBIndex = values.firstIndex(of: Int(settings.size)) ?? 0
53+
pickerWithoutCOBIndex = values.firstIndex(of: Int(settings.sizeWithoutCarbs)) ?? 0
54+
pickerMinimumBolusSizeIndex = minimumBolusSizeValues.firstIndex(of: Double(settings.minimumBolusSize)) ?? 0
4555

4656
let withCOBCancellable = $pickerWithCOBIndex
4757
.map { Double(self.values[$0]) }
@@ -63,33 +73,40 @@ struct MicrobolusView: View {
6373
}
6474

6575
func changes() -> AnyPublisher<Microbolus.Settings, Never> {
66-
Publishers.CombineLatest4(
76+
Publishers.CombineLatest3(
6777
Publishers.CombineLatest4(
6878
$microbolusesWithCOB,
6979
$withCOBValue,
7080
$microbolusesWithoutCOB,
7181
$withoutCOBValue
7282
),
73-
$safeMode,
74-
$microbolusesMinimumBolusSize,
75-
$openBolusScreen
83+
Publishers.CombineLatest4(
84+
$safeMode,
85+
$microbolusesMinimumBolusSize,
86+
$openBolusScreen,
87+
$disableByOverride
88+
),
89+
$lowerBound
7690
)
7791
.map {
7892
Microbolus.Settings(
7993
enabled: $0.0.0,
8094
size: $0.0.1,
8195
enabledWithoutCarbs: $0.0.2,
8296
sizeWithoutCarb: $0.0.3,
83-
safeMode: $0.1,
84-
minimumBolusSize: $0.2,
85-
shouldOpenBolusScreen: $0.3
97+
safeMode: $0.1.0,
98+
minimumBolusSize: $0.1.1,
99+
shouldOpenBolusScreen: $0.1.2,
100+
disableByOverride: $0.1.3,
101+
overrideLowerBound: $0.2
86102
)
87103
}
88104
.eraseToAnyPublisher()
89105
}
90106
}
91107

92108
@ObservedObject var viewModel: ViewModel
109+
@ObservedObject private var keyboard = KeyboardResponder()
93110

94111
init(viewModel: ViewModel) {
95112
self.viewModel = viewModel
@@ -152,6 +169,28 @@ struct MicrobolusView: View {
152169
Toggle (isOn: $viewModel.openBolusScreen) {
153170
Text("Open Bolus screen after Carbs")
154171
}
172+
173+
Toggle (isOn: $viewModel.disableByOverride) {
174+
Text("Disable microboluses by override ")
175+
}
176+
177+
if viewModel.disableByOverride {
178+
Text("Blablabla")
179+
.font(.caption)
180+
181+
HStack {
182+
Text("Lower bound")
183+
184+
TextField("0", value: $viewModel.lowerBound, formatter: viewModel.formatter.numberFormatter, onEditingChanged: { changed in
185+
186+
}) { self.dismissKeyboard() }
187+
.keyboardType(.numberPad)
188+
.multilineTextAlignment(.trailing)
189+
190+
Text(viewModel.unit.localizedShortUnitString)
191+
}
192+
}
193+
155194
Picker(selection: $viewModel.pickerMinimumBolusSizeIndex, label: Text("Minimum Bolus Size")) {
156195
ForEach(0 ..< viewModel.minimumBolusSizeValues.count) { index in Text(String(format: "%.2f U", self.viewModel.minimumBolusSizeValues[index])).tag(index)
157196
}
@@ -160,6 +199,11 @@ struct MicrobolusView: View {
160199

161200
}
162201
.navigationBarTitle("Microboluses")
202+
.padding(.bottom, keyboard.currentHeight)
203+
.animation(.easeOut(duration: 0.16))
204+
.onTapGesture {
205+
self.dismissKeyboard()
206+
}
163207
}
164208
}
165209

@@ -179,16 +223,50 @@ private extension Microbolus.SafeMode {
179223
struct MicrobolusView_Previews: PreviewProvider {
180224
static var previews: some View {
181225
MicrobolusView(viewModel: .init(
182-
microbolusesWithCOB: true,
183-
withCOBValue: 30,
184-
microbolusesWithoutCOB: false,
185-
withoutCOBValue: 30,
186-
safeMode: .enabled,
187-
microbolusesMinimumBolusSize: 0.0,
188-
openBolusScreen: false
226+
settings: Microbolus.Settings(),
227+
glucoseUnit: HKUnit(from: "mmol/L")
189228
)
190229
)
191230
.environment(\.colorScheme, .dark)
192231
.previewLayout(.sizeThatFits)
193232
}
194233
}
234+
235+
// MARK: - Helpers
236+
237+
extension UIApplication {
238+
func endEditing() {
239+
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
240+
}
241+
}
242+
243+
extension View {
244+
func dismissKeyboard() {
245+
UIApplication.shared.endEditing()
246+
}
247+
}
248+
249+
final class KeyboardResponder: ObservableObject {
250+
private var notificationCenter: NotificationCenter
251+
@Published private(set) var currentHeight: CGFloat = 0
252+
253+
init(center: NotificationCenter = .default) {
254+
notificationCenter = center
255+
notificationCenter.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
256+
notificationCenter.addObserver(self, selector: #selector(keyBoardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
257+
}
258+
259+
deinit {
260+
notificationCenter.removeObserver(self)
261+
}
262+
263+
@objc func keyBoardWillShow(notification: Notification) {
264+
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
265+
currentHeight = keyboardSize.height
266+
}
267+
}
268+
269+
@objc func keyBoardWillHide(notification: Notification) {
270+
currentHeight = 0
271+
}
272+
}

LoopCore/Microbolus.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public enum Microbolus {
2929
public var safeMode: SafeMode
3030
public var minimumBolusSize: Double
3131
public var shouldOpenBolusScreen: Bool
32+
public var disableByOverride: Bool
33+
public var overrideLowerBound: Double
3234

3335
public init(
3436
enabled: Bool = false,
@@ -37,7 +39,9 @@ public enum Microbolus {
3739
sizeWithoutCarb: Double = 30,
3840
safeMode: SafeMode = .enabled,
3941
minimumBolusSize: Double = 0,
40-
shouldOpenBolusScreen: Bool = false
42+
shouldOpenBolusScreen: Bool = false,
43+
disableByOverride: Bool = false,
44+
overrideLowerBound: Double = 0
4145
) {
4246
self.enabled = enabled
4347
self.size = size
@@ -46,6 +50,8 @@ public enum Microbolus {
4650
self.safeMode = safeMode
4751
self.minimumBolusSize = minimumBolusSize
4852
self.shouldOpenBolusScreen = shouldOpenBolusScreen
53+
self.disableByOverride = disableByOverride
54+
self.overrideLowerBound = overrideLowerBound
4955
}
5056

5157
public init?(rawValue: [String : Any]) {
@@ -79,6 +85,14 @@ public enum Microbolus {
7985
if let shouldOpenBolusScreen = rawValue["shouldOpenBolusScreen"] as? Bool {
8086
self.shouldOpenBolusScreen = shouldOpenBolusScreen
8187
}
88+
89+
if let disableByOverride = rawValue["disableByOverride"] as? Bool {
90+
self.disableByOverride = disableByOverride
91+
}
92+
93+
if let overrideLowerBound = rawValue["overrideLowerBound"] as? Double {
94+
self.overrideLowerBound = overrideLowerBound
95+
}
8296
}
8397

8498
public var rawValue: [String : Any] {
@@ -89,7 +103,9 @@ public enum Microbolus {
89103
"sizeWithoutCarbs": sizeWithoutCarbs,
90104
"safeMode": safeMode.rawValue,
91105
"minimumBolusSize": minimumBolusSize,
92-
"shouldOpenBolusScreen": shouldOpenBolusScreen
106+
"shouldOpenBolusScreen": shouldOpenBolusScreen,
107+
"disableByOverride": disableByOverride,
108+
"overrideLowerBound": overrideLowerBound
93109
]
94110
}
95111
}

0 commit comments

Comments
 (0)