| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- //
- // MockPumpManagerSettingsViewModel.swift
- // MockKitUI
- //
- // Created by Nathaniel Hamming on 2023-05-18.
- // Copyright © 2023 LoopKit Authors. All rights reserved.
- //
- import SwiftUI
- import LoopKit
- import MockKit
- class MockPumpManagerSettingsViewModel: ObservableObject {
- let pumpManager: MockPumpManager
-
- @Published private(set) var isDeliverySuspended: Bool {
- didSet {
- transitioningSuspendResumeInsulinDelivery = false
- basalDeliveryState = pumpManager.status.basalDeliveryState
- }
- }
-
- @Published private(set) var transitioningSuspendResumeInsulinDelivery = false
-
- @Published private(set) var suspendedAtString: String? = nil
-
- var suspendResumeInsulinDeliveryLabel: String {
- if isDeliverySuspended {
- return "Tap to Resume Insulin Delivery"
- } else {
- return "Suspend Insulin Delivery"
- }
- }
-
- static private let dateTimeFormatter: DateFormatter = {
- let timeFormatter = DateFormatter()
- timeFormatter.dateStyle = .short
- timeFormatter.timeStyle = .short
- return timeFormatter
- }()
-
- static private let shortTimeFormatter: DateFormatter = {
- let formatter = DateFormatter()
- formatter.dateStyle = .none
- formatter.timeStyle = .short
- return formatter
- }()
-
- private var pumpPairedInterval: TimeInterval {
- pumpExpirationRemaing - pumpLifeTime
- }
-
- var lastPumpPairedDateTimeString: String {
- Self.dateTimeFormatter.string(from: Date().addingTimeInterval(pumpPairedInterval))
- }
- private let pumpExpirationRemaing = TimeInterval(days: 2.0)
- private let pumpLifeTime = TimeInterval(days: 3.0)
- var pumpExpirationPercentComplete: Double {
- (pumpLifeTime - pumpExpirationRemaing) / pumpLifeTime
- }
- var pumpExpirationDateTimeString: String {
- Self.dateTimeFormatter.string(from: Date().addingTimeInterval(pumpExpirationRemaing))
- }
-
- var pumpTimeString: String {
- Self.shortTimeFormatter.string(from: Date())
- }
-
- @Published private(set) var basalDeliveryState: PumpManagerStatus.BasalDeliveryState? {
- didSet {
- setSuspenededAtString()
- }
- }
- @Published private(set) var basalDeliveryRate: Double?
- @Published private(set) var presentDeliveryWarning: Bool?
-
- var isScheduledBasal: Bool {
- switch basalDeliveryState {
- case .active, .initiatingTempBasal:
- return true
- case .tempBasal, .cancelingTempBasal, .suspending, .suspended, .resuming, .none:
- return false
- }
- }
-
- var isTempBasal: Bool {
- switch basalDeliveryState {
- case .tempBasal, .cancelingTempBasal:
- return true
- case .active, .initiatingTempBasal, .suspending, .suspended, .resuming, .none:
- return false
- }
- }
-
- init(pumpManager: MockPumpManager) {
- self.pumpManager = pumpManager
-
- isDeliverySuspended = pumpManager.status.basalDeliveryState?.isSuspended == true
- basalDeliveryState = pumpManager.status.basalDeliveryState
- basalDeliveryRate = pumpManager.state.basalDeliveryRate(at: Date())
- setSuspenededAtString()
-
- pumpManager.addStateObserver(self, queue: .main)
- }
-
- private func setSuspenededAtString() {
- switch basalDeliveryState {
- case .suspended(let suspendedAt):
- let formatter = DateFormatter()
- formatter.dateStyle = .medium
- formatter.timeStyle = .short
- formatter.doesRelativeDateFormatting = true
- suspendedAtString = formatter.string(from: suspendedAt)
- default:
- suspendedAtString = nil
- }
- }
-
- func resumeDelivery(completion: @escaping (Error?) -> Void) {
- transitioningSuspendResumeInsulinDelivery = true
- pumpManager.resumeDelivery() { [weak self] error in
- DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
- if error == nil {
- self?.isDeliverySuspended = false
- }
- completion(error)
- }
- }
- }
-
- func suspendDelivery(completion: @escaping (Error?) -> Void) {
- transitioningSuspendResumeInsulinDelivery = true
- pumpManager.suspendDelivery() { [weak self] error in
- DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
- if error == nil {
- self?.isDeliverySuspended = true
- }
- completion(error)
- }
- }
- }
- }
- extension MockPumpManagerSettingsViewModel: MockPumpManagerStateObserver {
- func mockPumpManager(_ manager: MockKit.MockPumpManager, didUpdate state: MockKit.MockPumpManagerState) {
- guard !transitioningSuspendResumeInsulinDelivery else { return }
- basalDeliveryRate = state.basalDeliveryRate(at: Date())
- basalDeliveryState = manager.status.basalDeliveryState
- }
-
- func mockPumpManager(_ manager: MockKit.MockPumpManager, didUpdate status: LoopKit.PumpManagerStatus, oldStatus: LoopKit.PumpManagerStatus) {
- guard !transitioningSuspendResumeInsulinDelivery else { return }
- basalDeliveryRate = manager.state.basalDeliveryRate(at: Date())
- basalDeliveryState = status.basalDeliveryState
- }
- }
-
- extension MockPumpManagerState {
- func basalDeliveryRate(at now: Date) -> Double? {
- switch suspendState {
- case .resumed:
- if let tempBasal = unfinalizedTempBasal, !tempBasal.isFinished(at: now) {
- return tempBasal.rate
- } else {
- return basalRateSchedule?.value(at: now)
- }
- case .suspended:
- return nil
- }
- }
- }
|