-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathG7SettingsViewModel.swift
More file actions
209 lines (187 loc) · 6.55 KB
/
G7SettingsViewModel.swift
File metadata and controls
209 lines (187 loc) · 6.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
//
// G7SettingsViewModel.swift
// CGMBLEKitUI
//
// Created by Pete Schwamb on 10/4/22.
// Copyright © 2022 LoopKit Authors. All rights reserved.
//
import Foundation
import G7SensorKit
import LoopKit
import LoopKitUI
import HealthKit
public enum ColorStyle {
case glucose, warning, critical, normal, dimmed
}
class G7SettingsViewModel: ObservableObject {
@Published private(set) var scanning: Bool = false
@Published private(set) var connected: Bool = false
@Published private(set) var sensorName: String?
@Published private(set) var sensorType: G7SensorType = .unknown
@Published private(set) var activatedAt: Date?
@Published private(set) var lastConnect: Date?
@Published private(set) var latestReadingTimestamp: Date?
@Published var uploadReadings: Bool = false {
didSet {
cgmManager.uploadReadings = uploadReadings
}
}
let displayGlucosePreference: DisplayGlucosePreference
private var lastReading: G7GlucoseMessage?
lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .short
return formatter
}()
private var cgmManager: G7CGMManager
var progressBarState: G7ProgressBarState {
switch cgmManager.lifecycleState {
case .searching:
return .searchingForSensor
case .ok:
return .lifetimeRemaining
case .warmup:
return .warmupProgress
case .failed:
return .sensorFailed
case .gracePeriod:
return .gracePeriodRemaining
case .expired:
return .sensorExpired
}
}
init(cgmManager: G7CGMManager, displayGlucosePreference: DisplayGlucosePreference) {
self.cgmManager = cgmManager
self.displayGlucosePreference = displayGlucosePreference
updateValues()
self.cgmManager.addStateObserver(self, queue: DispatchQueue.main)
}
var sensorTypeDisplayName: String {
return sensorType.displayName
}
func updateValues() {
scanning = cgmManager.isScanning
sensorName = cgmManager.sensorName
sensorType = cgmManager.state.sensorType
activatedAt = cgmManager.sensorActivatedAt
connected = cgmManager.isConnected
lastConnect = cgmManager.lastConnect
lastReading = cgmManager.latestReading
latestReadingTimestamp = cgmManager.latestReadingTimestamp
uploadReadings = cgmManager.state.uploadReadings
}
var progressBarColorStyle: ColorStyle {
switch progressBarState {
case .warmupProgress:
return .glucose
case .searchingForSensor:
return .dimmed
case .sensorExpired, .sensorFailed:
return .critical
case .lifetimeRemaining:
guard let remaining = progressValue else {
return .dimmed
}
if remaining > .hours(24) {
return .glucose
} else {
return .warning
}
case .gracePeriodRemaining:
return .critical
}
}
var progressBarProgress: Double {
switch progressBarState {
case .searchingForSensor:
return 0
case .warmupProgress:
guard let value = progressValue, value > 0 else {
return 0
}
return 1 - value / sensorType.warmupDuration
case .lifetimeRemaining:
guard let value = progressValue, value > 0 else {
return 0
}
return 1 - value / sensorType.lifetime
case .gracePeriodRemaining:
guard let value = progressValue, value > 0 else {
return 0
}
return 1 - value / sensorType.gracePeriod
case .sensorExpired, .sensorFailed:
return 1
}
}
var progressReferenceDate: Date? {
switch progressBarState {
case .searchingForSensor:
return nil
case .sensorExpired, .gracePeriodRemaining:
return cgmManager.sensorEndsAt
case .warmupProgress:
return cgmManager.sensorFinishesWarmupAt
case .lifetimeRemaining:
return cgmManager.sensorExpiresAt
case .sensorFailed:
return nil
}
}
var progressValue: TimeInterval? {
switch progressBarState {
case .sensorExpired, .sensorFailed, .searchingForSensor:
guard let sensorEndsAt = cgmManager.sensorEndsAt else {
return nil
}
return sensorEndsAt.timeIntervalSinceNow
case .warmupProgress:
guard let warmupFinishedAt = cgmManager.sensorFinishesWarmupAt else {
return nil
}
return max(0, warmupFinishedAt.timeIntervalSinceNow)
case .lifetimeRemaining:
guard let expiration = cgmManager.sensorExpiresAt else {
return nil
}
return max(0, expiration.timeIntervalSinceNow)
case .gracePeriodRemaining:
guard let sensorEndsAt = cgmManager.sensorEndsAt else {
return nil
}
return max(0, sensorEndsAt.timeIntervalSinceNow)
}
}
func scanForNewSensor() {
cgmManager.scanForNewSensor()
}
var lastGlucoseString: String {
guard let lastReading = lastReading, lastReading.hasReliableGlucose, let quantity = lastReading.glucoseQuantity else {
return LocalizedString("– – –", comment: "No glucose value representation (3 dashes for mg/dL)")
}
switch lastReading.glucoseRangeCategory {
case .some(.belowRange):
return LocalizedString("LOW", comment: "String displayed instead of a glucose value below the CGM range")
case .some(.aboveRange):
return LocalizedString("HIGH", comment: "String displayed instead of a glucose value above the CGM range")
default:
return displayGlucosePreference.formatter.string(from: quantity)!
}
}
var lastGlucoseTrendString: String {
if let lastReading = lastReading, lastReading.hasReliableGlucose, let trendRate = lastReading.trendRate {
return displayGlucosePreference.minuteRateFormatter.string(from: trendRate)!
} else {
return ""
}
}
}
extension G7SettingsViewModel: G7StateObserver {
func g7StateDidUpdate(_ state: G7CGMManagerState?) {
updateValues()
}
func g7ConnectionStatusDidChange() {
updateValues()
}
}