Sfoglia il codice sorgente

feat: show patch age if patch does not have an expiration

bastiaanv 7 mesi fa
parent
commit
8561becf59

+ 1 - 1
MedtrumKit

@@ -1 +1 @@
-Subproject commit 8b46b60835072f02340de351d99b7c1ca2264ec1
+Subproject commit fa8c19760476c0aa275ddb85383f884f84aeeda9

+ 5 - 0
Trio/Sources/APS/APSManager.swift

@@ -18,6 +18,7 @@ protocol APSManager {
     var lastLoopDateSubject: PassthroughSubject<Date, Never> { get }
     var bolusProgress: CurrentValueSubject<Decimal?, Never> { get }
     var pumpExpiresAtDate: CurrentValueSubject<Date?, Never> { get }
+    var pumpActivatedAtDate: CurrentValueSubject<Date?, Never> { get }
     var isManualTempBasal: Bool { get }
     func enactTempBasal(rate: Double, duration: TimeInterval) async
     func determineBasal() async throws
@@ -124,6 +125,10 @@ final class BaseAPSManager: APSManager, Injectable {
         deviceDataManager.pumpExpiresAtDate
     }
 
+    var pumpActivatedAtDate: CurrentValueSubject<Date?, Never> {
+        deviceDataManager.pumpActivatedAtDate
+    }
+
     var settings: TrioSettings {
         get { settingsManager.settings }
         set { settingsManager.settings = newValue }

+ 26 - 7
Trio/Sources/APS/DeviceDataManager.swift

@@ -26,6 +26,7 @@ protocol DeviceDataManager: GlucoseSource {
     var errorSubject: PassthroughSubject<Error, Never> { get }
     var pumpName: CurrentValueSubject<String, Never> { get }
     var pumpExpiresAtDate: CurrentValueSubject<Date?, Never> { get }
+    var pumpActivatedAtDate: CurrentValueSubject<Date?, Never> { get }
 
     func heartbeat(date: Date)
     func createBolusProgressReporter() -> DoseProgressReporter?
@@ -101,6 +102,7 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
                 storage.save(modifiedPreferences, as: OpenAPS.Settings.preferences)
 
                 if let omnipod = pumpManager as? OmnipodPumpManager {
+                    pumpActivatedAtDate.send(nil)
                     guard let endTime = omnipod.state.podState?.expiresAt else {
                         pumpExpiresAtDate.send(nil)
                         return
@@ -108,6 +110,7 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
                     pumpExpiresAtDate.send(endTime)
                 }
                 if let omnipodBLE = pumpManager as? OmniBLEPumpManager {
+                    pumpActivatedAtDate.send(nil)
                     guard let endTime = omnipodBLE.state.podState?.expiresAt else {
                         pumpExpiresAtDate.send(nil)
                         return
@@ -115,11 +118,17 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
                     pumpExpiresAtDate.send(endTime)
                 }
                 if let medtrum = pumpManager as? MedtrumPumpManager {
-                    guard let endTime = medtrum.state.patchExpiresAt else {
+                    if medtrum.state.expirationTimer == 1 {
+                        pumpActivatedAtDate.send(nil)
+                        guard let endTime = medtrum.state.patchExpiresAt else {
+                            pumpExpiresAtDate.send(nil)
+                            return
+                        }
+                        pumpExpiresAtDate.send(endTime)
+                    } else {
+                        pumpActivatedAtDate.send(medtrum.state.patchActivatedAt)
                         pumpExpiresAtDate.send(nil)
-                        return
                     }
-                    pumpExpiresAtDate.send(endTime)
                 }
                 if let simulatorPump = pumpManager as? MockPumpManager {
                     pumpDisplayState.value = PumpDisplayState(name: simulatorPump.localizedTitle, image: simulatorPump.smallImage)
@@ -165,6 +174,7 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
             } else {
                 pumpDisplayState.value = nil
                 pumpExpiresAtDate.send(nil)
+                pumpActivatedAtDate.send(nil)
                 pumpName.send("")
                 // Reset bolusIncrement setting to default value, which is 0.1 U
                 var modifiedPreferences = settingsManager.preferences
@@ -204,6 +214,7 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
 
     let pumpDisplayState = CurrentValueSubject<PumpDisplayState?, Never>(nil)
     let pumpExpiresAtDate = CurrentValueSubject<Date?, Never>(nil)
+    let pumpActivatedAtDate = CurrentValueSubject<Date?, Never>(nil)
     let pumpName = CurrentValueSubject<String, Never>("Pump")
 
     init(resolver: Resolver) {
@@ -446,6 +457,7 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
                 manualTempBasal.send(false)
             }
 
+            pumpActivatedAtDate.send(nil)
             guard let endTime = omnipod.state.podState?.expiresAt else {
                 pumpExpiresAtDate.send(nil)
                 return
@@ -479,6 +491,7 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
                 manualTempBasal.send(false)
             }
 
+            pumpActivatedAtDate.send(nil)
             guard let endTime = omnipodBLE.state.podState?.expiresAt else {
                 pumpExpiresAtDate.send(nil)
                 return
@@ -489,18 +502,24 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
                 storage.save(startTime, as: OpenAPS.Monitor.podAge)
             }
         }
-        
+
         if let medtrumPump = pumpManager as? MedtrumPumpManager {
             storage.save(Decimal(medtrumPump.state.reservoir), as: OpenAPS.Monitor.reservoir)
             broadcaster.notify(PumpReservoirObserver.self, on: processQueue) {
                 $0.pumpReservoirDidChange(Decimal(medtrumPump.state.reservoir))
             }
 
-            guard let endTime = medtrumPump.state.patchExpiresAt else {
+            if medtrumPump.state.expirationTimer == 1 {
+                pumpActivatedAtDate.send(nil)
+                guard let endTime = medtrumPump.state.patchExpiresAt else {
+                    pumpExpiresAtDate.send(nil)
+                    return
+                }
+                pumpExpiresAtDate.send(endTime)
+            } else {
+                pumpActivatedAtDate.send(medtrumPump.state.patchActivatedAt)
                 pumpExpiresAtDate.send(nil)
-                return
             }
-            pumpExpiresAtDate.send(endTime)
         }
 
         if let simulatorPump = pumpManager as? MockPumpManager {

+ 6 - 0
Trio/Sources/Modules/Home/HomeStateModel.swift

@@ -48,6 +48,7 @@ extension Home {
         var reservoir: Decimal?
         var pumpName = ""
         var pumpExpiresAtDate: Date?
+        var pumpActivatedAtDate: Date?
         var highTTraisesSens: Bool = false
         var lowTTlowersSens: Bool = false
         var isExerciseModeActive: Bool = false
@@ -343,6 +344,11 @@ extension Home {
                 .weakAssign(to: \.pumpExpiresAtDate, on: self)
                 .store(in: &lifetime)
 
+            apsManager.pumpActivatedAtDate
+                .receive(on: DispatchQueue.main)
+                .weakAssign(to: \.pumpActivatedAtDate, on: self)
+                .store(in: &lifetime)
+
             apsManager.lastError
                 .receive(on: DispatchQueue.main)
                 .map { [weak self] error in

+ 41 - 24
Trio/Sources/Modules/Home/View/Header/PumpView.swift

@@ -5,6 +5,7 @@ struct PumpView: View {
     let reservoir: Decimal?
     let name: String
     let expiresAtDate: Date?
+    let activatedAtDate: Date?
     let timerDate: Date
     let pumpStatusHighlightMessage: String?
     let battery: [OpenAPS_Battery]
@@ -17,6 +18,7 @@ struct PumpView: View {
     }
 
     private var hourglassIcon: String {
+        if activatedAtDate != nil { return "hourglass" }
         guard let expiration = expiresAtDate else { return "hourglass" }
 
         let hoursRemaining = expiration.timeIntervalSince(timerDate) / 3600
@@ -96,34 +98,45 @@ struct PumpView: View {
                 }
 
                 if let date = expiresAtDate {
-                    HStack {
-                        Image(systemName: hourglassIcon)
-                            .font(.callout)
-                            .foregroundStyle(timerColor, Color.yellow)
-                            .symbolRenderingMode(.palette)
-
-                        let remainingTimeString = remainingTimeString(time: date.timeIntervalSince(timerDate))
+                    PatchTimer(date, isExpiration: true)
+                }
 
-                        Text(remainingTimeString)
-                            .font(date.timeIntervalSince(timerDate) > 0 ? .callout : .subheadline)
-                            .fontWeight(.bold)
-                            .fontDesign(.rounded)
-                            .lineLimit(2)
-                            .multilineTextAlignment(.leading)
-                            .frame(
-                                // If the string is > 6 chars, i.e., exceeds "xd yh", limit width to 80 pts
-                                // This forces the "Replace pod" string to wrap to 2 lines.
-                                maxWidth: remainingTimeString.count > 6 ? 80 : .infinity,
-                                alignment: .leading
-                            )
-                    }
-                    // aligns the stopwatch icon exactly with the first pixel of the reservoir icon
-                    .padding(.leading, date.timeIntervalSince(timerDate) > 0 ? 12 : 0)
+                if let date = activatedAtDate {
+                    PatchTimer(date, isExpiration: false)
                 }
             }
         }
     }
 
+    @ViewBuilder private func PatchTimer(_ date: Date, isExpiration: Bool) -> some View {
+        HStack {
+            Image(systemName: hourglassIcon)
+                .font(.callout)
+                .foregroundStyle(timerColor, Color.yellow)
+                .symbolRenderingMode(.palette)
+
+            let remainingTimeString = remainingTimeString(
+                time: isExpiration ? date.timeIntervalSince(timerDate) : timerDate
+                    .timeIntervalSince(date)
+            )
+
+            Text(remainingTimeString)
+                .font(date.timeIntervalSince(timerDate) > 0 ? .callout : .subheadline)
+                .fontWeight(.bold)
+                .fontDesign(.rounded)
+                .lineLimit(2)
+                .multilineTextAlignment(.leading)
+                .frame(
+                    // If the string is > 6 chars, i.e., exceeds "xd yh", limit width to 80 pts
+                    // This forces the "Replace pod" string to wrap to 2 lines.
+                    maxWidth: remainingTimeString.count > 6 ? 80 : .infinity,
+                    alignment: .leading
+                )
+        }
+        // aligns the stopwatch icon exactly with the first pixel of the reservoir icon
+        .padding(.leading, date.timeIntervalSince(timerDate) > 0 || !isExpiration ? 12 : 0)
+    }
+
     private func remainingTimeString(time: TimeInterval) -> String {
         guard time > 0 else {
             return String(localized: "Replace pod", comment: "View/Header when pod expired")
@@ -179,11 +192,15 @@ struct PumpView: View {
     }
 
     private var timerColor: Color {
-        guard let expisesAt = expiresAtDate else {
+        if activatedAtDate != nil {
+            return Color.loopGreen
+        }
+
+        guard let expiresAt = expiresAtDate else {
             return .gray
         }
 
-        let time = expisesAt.timeIntervalSince(timerDate)
+        let time = expiresAt.timeIntervalSince(timerDate)
 
         switch time {
         case ...8.hours.timeInterval:

+ 1 - 0
Trio/Sources/Modules/Home/View/HomeRootView.swift

@@ -147,6 +147,7 @@ extension Home {
                 reservoir: state.reservoir,
                 name: state.pumpName,
                 expiresAtDate: state.pumpExpiresAtDate,
+                activatedAtDate: state.pumpActivatedAtDate,
                 timerDate: state.timerDate,
                 pumpStatusHighlightMessage: state.pumpStatusHighlightMessage,
                 battery: state.batteryFromPersistence