GuardrailWarning.swift 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. //
  2. // GuardrailWarning.swift
  3. // LoopKitUI
  4. //
  5. // Created by Michael Pangburn on 4/14/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. import LoopKit
  10. public struct GuardrailWarning: View {
  11. private enum CrossedThresholds {
  12. case one(SafetyClassification.Threshold)
  13. case oneOrMore([SafetyClassification.Threshold])
  14. }
  15. private var therapySetting: TherapySetting
  16. private var title: Text
  17. private var crossedThresholds: CrossedThresholds
  18. private var captionOverride: Text?
  19. public init(
  20. therapySetting: TherapySetting,
  21. title: Text,
  22. threshold: SafetyClassification.Threshold,
  23. caption: Text? = nil
  24. ) {
  25. self.therapySetting = therapySetting
  26. self.title = title
  27. self.crossedThresholds = .one(threshold)
  28. self.captionOverride = caption
  29. }
  30. public init(
  31. therapySetting: TherapySetting,
  32. title: Text,
  33. thresholds: [SafetyClassification.Threshold],
  34. caption: Text? = nil
  35. ) {
  36. precondition(!thresholds.isEmpty)
  37. self.therapySetting = therapySetting
  38. self.title = title
  39. self.crossedThresholds = .oneOrMore(thresholds)
  40. self.captionOverride = caption
  41. }
  42. public var body: some View {
  43. WarningView(title: title, caption: caption, severity: severity)
  44. }
  45. private var severity: WarningSeverity {
  46. switch crossedThresholds {
  47. case .one(let threshold):
  48. return threshold.severity
  49. case .oneOrMore(let thresholds):
  50. return thresholds.lazy.map({ $0.severity }).max()!
  51. }
  52. }
  53. private var caption: Text {
  54. if let caption = captionOverride {
  55. return caption
  56. }
  57. switch crossedThresholds {
  58. case .one(let threshold):
  59. return captionForThreshold(threshold)
  60. case .oneOrMore(let thresholds):
  61. if thresholds.count == 1, let threshold = thresholds.first {
  62. return captionForThreshold(threshold)
  63. } else {
  64. return captionForThresholds()
  65. }
  66. }
  67. }
  68. private func captionForThreshold(_ threshold: SafetyClassification.Threshold) -> Text {
  69. switch threshold {
  70. case .minimum, .belowRecommended:
  71. return Text(therapySetting.guardrailCaptionForLowValue)
  72. case .aboveRecommended, .maximum:
  73. return Text(therapySetting.guardrailCaptionForHighValue)
  74. }
  75. }
  76. private func captionForThresholds() -> Text {
  77. return Text(therapySetting.guardrailCaptionForOutsideValues)
  78. }
  79. }
  80. fileprivate extension SafetyClassification.Threshold {
  81. var severity: WarningSeverity {
  82. switch self {
  83. case .belowRecommended, .aboveRecommended:
  84. return .default
  85. case .minimum, .maximum:
  86. return .critical
  87. }
  88. }
  89. }