// // PodLifeHUDView.swift // OmniKit // // Based on OmniKitUI/Views/PodLifeHUDView.swift // Created by Pete Schwamb on 10/22/18. // Copyright © 2021 LoopKit Authors. All rights reserved. // import UIKit import LoopKitUI import MKRingProgressView public enum PodAlertState { case none case warning case fault } public class PodLifeHUDView: BaseHUDView, NibLoadable { override public var orderPriority: HUDViewOrderPriority { return 12 } @IBOutlet private weak var timeLabel: UILabel! { didSet { // Setting this color in code because the nib isn't being applied correctly if #available(iOSApplicationExtension 13.0, *) { timeLabel.textColor = .label } } } @IBOutlet private weak var progressRing: RingProgressView! @IBOutlet private weak var alertLabel: UILabel! { didSet { alertLabel.alpha = 0 alertLabel.textColor = UIColor.white alertLabel.layer.cornerRadius = 9 alertLabel.clipsToBounds = true } } @IBOutlet private weak var backgroundRing: UIImageView! { didSet { if #available(iOSApplicationExtension 13.0, iOS 13.0, *) { backgroundRing.tintColor = .systemGray5 } else { backgroundRing.tintColor = UIColor(red: 198 / 255, green: 199 / 255, blue: 201 / 255, alpha: 1) } } } private var startTime: Date? private var lifetime: TimeInterval? private var timer: Timer? public var alertState: PodAlertState = .none { didSet { updateAlertStateLabel() } } public class func instantiate() -> PodLifeHUDView { return nib().instantiate(withOwner: nil, options: nil)[0] as! PodLifeHUDView } public func setPodLifeCycle(startTime: Date, lifetime: TimeInterval) { self.startTime = startTime self.lifetime = lifetime updateProgressCircle() if timer == nil { self.timer = Timer.scheduledTimer(withTimeInterval: .seconds(10), repeats: true) { [weak self] _ in self?.updateProgressCircle() } } } override open func stateColorsDidUpdate() { super.stateColorsDidUpdate() updateProgressCircle() updateAlertStateLabel() } private var endColor: UIColor? { didSet { let primaryColor = endColor ?? UIColor(red: 198 / 255, green: 199 / 255, blue: 201 / 255, alpha: 1) self.progressRing.endColor = primaryColor self.progressRing.startColor = primaryColor } } private lazy var timeFormatter: DateComponentsFormatter = { let formatter = DateComponentsFormatter() formatter.allowedUnits = [.hour, .minute] formatter.maximumUnitCount = 1 formatter.unitsStyle = .abbreviated return formatter }() private func updateAlertStateLabel() { var alertLabelAlpha: CGFloat = 1 if alertState == .fault { timer = nil } switch alertState { case .fault: alertLabel.text = "!" alertLabel.backgroundColor = stateColors?.error case .warning: alertLabel.text = "!" alertLabel.backgroundColor = stateColors?.warning case .none: alertLabelAlpha = 0 } alertLabel.alpha = alertLabelAlpha UIView.animate(withDuration: 0.25, animations: { self.alertLabel.alpha = alertLabelAlpha }) } private func updateProgressCircle() { if let startTime = startTime, let lifetime = lifetime { let age = -startTime.timeIntervalSinceNow let progress = Double(age / lifetime) progressRing.progress = progress if progress < 0.75 { self.endColor = stateColors?.normal progressRing.shadowOpacity = 0 } else if progress < 1.0 { self.endColor = stateColors?.warning progressRing.shadowOpacity = 0.5 } else { self.endColor = stateColors?.error progressRing.shadowOpacity = 0.8 } let remaining = (lifetime - age) // Update time label and caption if alertState == .fault { timeLabel.isHidden = true caption.text = LocalizedString("Fault", comment: "Pod life HUD view label") } else if remaining > .hours(24) { timeLabel.isHidden = true caption.text = LocalizedString("Pod Age", comment: "Label describing pod age view") } else if remaining > 0 { let remainingFlooredToHour = remaining > .hours(1) ? remaining - remaining.truncatingRemainder(dividingBy: .hours(1)) : remaining if let timeString = timeFormatter.string(from: remainingFlooredToHour) { timeLabel.isHidden = false timeLabel.text = timeString } caption.text = LocalizedString("Remaining", comment: "Label describing time remaining view") } else { timeLabel.isHidden = true caption.text = LocalizedString("Replace Pod", comment: "Label indicating pod replacement necessary") } } } func pauseUpdates() { timer?.invalidate() timer = nil } override public func awakeFromNib() { super.awakeFromNib() } }