Skip to content

Commit c45d3f3

Browse files
authored
[LOOP-3554] manual glucose display in cgm pill (#403)
* display manual glucose in CGM pill when current * corrected typo
1 parent 9cd92d6 commit c45d3f3

File tree

2 files changed

+139
-11
lines changed

2 files changed

+139
-11
lines changed

LoopTests/ViewModels/CGMStatusHUDViewModelTests.swift

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,17 +179,135 @@ class CGMStatusHUDViewModelTests: XCTestCase {
179179

180180
// ensure status highlight icon is set to the manual glucose override icon
181181
// when there is a manual glucose override icon, the status highlight isn't returned to be presented
182-
viewModel.setManualGlucoseTrendIconOverride()
182+
let glucoseDisplay = TestGlucoseDisplay(isStateValid: true,
183+
trendType: .down,
184+
isLocal: true,
185+
glucoseRangeCategory: .urgentLow)
186+
let glucoseStartDate = Date()
187+
let staleGlucoseAge: TimeInterval = .minutes(15)
188+
viewModel.setGlucoseQuantity(90,
189+
at: glucoseStartDate,
190+
unit: .milligramsPerDeciliter,
191+
staleGlucoseAge: staleGlucoseAge,
192+
glucoseDisplay: glucoseDisplay,
193+
wasUserEntered: true,
194+
isDisplayOnly: false)
195+
196+
XCTAssertEqual(viewModel.glucoseValueString, "90")
197+
XCTAssertNil(viewModel.trend)
183198
XCTAssertNil(viewModel.statusHighlight)
184199
XCTAssertEqual(viewModel.manualGlucoseTrendIconOverride, statusHighlight1.image)
185200
XCTAssertEqual(viewModel.glucoseTrendTintColor, statusHighlight1.state.color)
186201

187202
// ensure updating the status highlight icon also updates the manual glucose override icon
188203
viewModel.statusHighlight = statusHighlight2
189204
XCTAssertNil(viewModel.statusHighlight)
205+
XCTAssertEqual(viewModel.glucoseValueString, "90")
206+
XCTAssertNil(viewModel.trend)
190207
XCTAssertEqual(viewModel.manualGlucoseTrendIconOverride, statusHighlight2.image)
191208
XCTAssertEqual(viewModel.glucoseTrendTintColor, statusHighlight2.state.color)
192209
}
210+
211+
func testManualGlucoseOverridesStatusHighlight() {
212+
// add manual glucose
213+
let glucoseDisplay = TestGlucoseDisplay(isStateValid: true,
214+
trendType: .down,
215+
isLocal: true,
216+
glucoseRangeCategory: .urgentLow)
217+
let staleGlucoseAge: TimeInterval = .minutes(15)
218+
viewModel.setGlucoseQuantity(90,
219+
at: Date(),
220+
unit: .milligramsPerDeciliter,
221+
staleGlucoseAge: staleGlucoseAge,
222+
glucoseDisplay: glucoseDisplay,
223+
wasUserEntered: true,
224+
isDisplayOnly: false)
225+
226+
// check that manual glucose is displayed
227+
XCTAssertEqual(viewModel.glucoseValueString, "90")
228+
XCTAssertNil(viewModel.trend)
229+
XCTAssertNil(viewModel.statusHighlight)
230+
XCTAssertNil(viewModel.manualGlucoseTrendIconOverride)
231+
XCTAssertEqual(viewModel.glucoseTrendTintColor, .glucoseTintColor)
232+
233+
// add status highlight
234+
let statusHighlight1 = TestStatusHighlight(localizedMessage: "Test 1",
235+
imageName: "plus.circle",
236+
state: .normalCGM)
237+
viewModel.statusHighlight = statusHighlight1
238+
239+
// check that manual glucose is still displayed (this time with status highlight icon)
240+
XCTAssertEqual(viewModel.glucoseValueString, "90")
241+
XCTAssertNil(viewModel.trend)
242+
XCTAssertNil(viewModel.statusHighlight)
243+
XCTAssertEqual(viewModel.manualGlucoseTrendIconOverride, statusHighlight1.image)
244+
XCTAssertEqual(viewModel.glucoseTrendTintColor, statusHighlight1.state.color)
245+
246+
// add CGM glucose
247+
viewModel.setGlucoseQuantity(95,
248+
at: Date(),
249+
unit: .milligramsPerDeciliter,
250+
staleGlucoseAge: staleGlucoseAge,
251+
glucoseDisplay: glucoseDisplay,
252+
wasUserEntered: false,
253+
isDisplayOnly: false)
254+
255+
// check that status highlight is displayed
256+
XCTAssertEqual(viewModel.glucoseValueString, "95")
257+
XCTAssertEqual(viewModel.trend, .down)
258+
XCTAssertEqual(viewModel.statusHighlight as! TestStatusHighlight, statusHighlight1)
259+
XCTAssertNil(viewModel.manualGlucoseTrendIconOverride)
260+
261+
// remove status highlight
262+
viewModel.statusHighlight = nil
263+
264+
// check that CGM glucose is displayed
265+
XCTAssertEqual(viewModel.glucoseValueString, "95")
266+
XCTAssertEqual(viewModel.trend, .down)
267+
XCTAssertNil(viewModel.statusHighlight)
268+
XCTAssertNil(viewModel.manualGlucoseTrendIconOverride)
269+
270+
// add status highlight
271+
let statusHighlight2 = TestStatusHighlight(localizedMessage: "Test 2",
272+
imageName: "exclamationmark.circle",
273+
state: .critical)
274+
viewModel.statusHighlight = statusHighlight2
275+
276+
// check that status highlight is displayed
277+
XCTAssertEqual(viewModel.glucoseValueString, "95")
278+
XCTAssertEqual(viewModel.trend, .down)
279+
XCTAssertEqual(viewModel.statusHighlight as! TestStatusHighlight, statusHighlight2)
280+
XCTAssertNil(viewModel.manualGlucoseTrendIconOverride)
281+
282+
// add manual glucose
283+
viewModel.setGlucoseQuantity(100,
284+
at: Date(),
285+
unit: .milligramsPerDeciliter,
286+
staleGlucoseAge: staleGlucoseAge,
287+
glucoseDisplay: glucoseDisplay,
288+
wasUserEntered: true,
289+
isDisplayOnly: false)
290+
291+
// check that manual glucose is still displayed (again with status highlight icon)
292+
XCTAssertEqual(viewModel.glucoseValueString, "100")
293+
XCTAssertNil(viewModel.trend)
294+
XCTAssertNil(viewModel.statusHighlight)
295+
XCTAssertEqual(viewModel.manualGlucoseTrendIconOverride, statusHighlight2.image)
296+
XCTAssertEqual(viewModel.glucoseTrendTintColor, statusHighlight2.state.color)
297+
298+
// add stale manual glucose
299+
viewModel.setGlucoseQuantity(100,
300+
at: Date(),
301+
unit: .milligramsPerDeciliter,
302+
staleGlucoseAge: .minutes(-1),
303+
glucoseDisplay: glucoseDisplay,
304+
wasUserEntered: true,
305+
isDisplayOnly: false)
306+
307+
// check that the status highlight is displayed
308+
XCTAssertEqual(viewModel.statusHighlight as! TestStatusHighlight, statusHighlight2)
309+
XCTAssertNil(viewModel.manualGlucoseTrendIconOverride)
310+
}
193311
}
194312

195313
extension CGMStatusHUDViewModelTests {

LoopUI/ViewModel/CGMStatusHUDViewModel.swift

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,34 @@ public class CGMStatusHUDViewModel {
3131
}
3232
return manualGlucoseTrendIconOverride
3333
}
34-
34+
35+
private var glucoseValueCurrent: Bool {
36+
guard let isStaleAt = isStaleAt else { return true }
37+
return Date() < isStaleAt
38+
}
39+
40+
private var isManualGlucose: Bool = false
41+
42+
private var isManualGlucoseCurrent: Bool {
43+
return isManualGlucose && glucoseValueCurrent
44+
}
45+
3546
var manualGlucoseTrendIconOverride: UIImage?
3647

3748
private var storedStatusHighlight: DeviceStatusHighlight?
3849

3950
var statusHighlight: DeviceStatusHighlight? {
4051
get {
41-
guard manualGlucoseTrendIconOverride == nil else {
42-
// if there is an icon override for a manual glucose, don't provide the stored status highlight
52+
guard !isManualGlucoseCurrent else {
53+
// if there is a current manual glucose, don't provide the stored status highlight
4354
return nil
4455
}
4556
return storedStatusHighlight
4657
}
4758
set {
4859
storedStatusHighlight = newValue
49-
if manualGlucoseTrendIconOverride != nil {
50-
// If there is an icon override for a manual glucose, it displays the current status highlight icon
60+
if isManualGlucoseCurrent {
61+
// If there is a current manual glucose, it displays the current status highlight icon
5162
setManualGlucoseTrendIconOverride()
5263
}
5364
}
@@ -76,7 +87,7 @@ public class CGMStatusHUDViewModel {
7687
}
7788
}
7889
}
79-
90+
8091
private func startStalenessTimerIfNeeded() {
8192
if let fireDate = isStaleAt,
8293
isVisible,
@@ -115,8 +126,7 @@ public class CGMStatusHUDViewModel {
115126
let time = timeFormatter.string(from: glucoseStartDate)
116127

117128
isStaleAt = glucoseStartDate.addingTimeInterval(staleGlucoseAge)
118-
let glucoseValueCurrent = Date() < isStaleAt!
119-
129+
120130
glucoseValueTintColor = glucoseDisplay?.glucoseRangeCategory?.glucoseColor ?? .label
121131

122132
let numberFormatter = NumberFormatter.glucoseFormatter(for: unit)
@@ -138,8 +148,8 @@ public class CGMStatusHUDViewModel {
138148
}
139149

140150
// Only a user-entered glucose value that is *not* display-only (i.e. a calibration) is considered a manual glucose entry.
141-
let isManualGlucose = wasUserEntered && !isDisplayOnly
142-
if isManualGlucose, glucoseValueCurrent {
151+
isManualGlucose = wasUserEntered && !isDisplayOnly
152+
if isManualGlucoseCurrent {
143153
// a manual glucose value presents any status highlight icon instead of a trend icon
144154
setManualGlucoseTrendIconOverride()
145155
} else if let trend = glucoseDisplay?.trendType, glucoseValueCurrent {

0 commit comments

Comments
 (0)