PreferencesEditorDataFlow.swift 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import Foundation
  2. import LoopKit
  3. protocol SettableValue {}
  4. extension Bool: SettableValue {}
  5. extension Decimal: SettableValue {}
  6. extension InsulinCurve: SettableValue {}
  7. enum PreferencesEditor {
  8. enum Config {}
  9. enum FieldType {
  10. case boolean(keypath: WritableKeyPath<Preferences, Bool>)
  11. case decimal(
  12. keypath: WritableKeyPath<Preferences, Decimal>,
  13. minVal: WritableKeyPath<Preferences, Decimal>? = nil,
  14. maxVal: WritableKeyPath<Preferences, Decimal>? = nil
  15. )
  16. case insulinCurve(keypath: WritableKeyPath<Preferences, InsulinCurve>)
  17. }
  18. class Field: Identifiable {
  19. var displayName: String
  20. var type: FieldType
  21. var infoText: String
  22. var boolValue: Bool {
  23. get {
  24. switch type {
  25. case let .boolean(keypath):
  26. return settable?.get(keypath) ?? false
  27. default: return false
  28. }
  29. }
  30. set { set(value: newValue) }
  31. }
  32. var decimalValue: Decimal {
  33. get {
  34. switch type {
  35. case let .decimal(keypath, _, _):
  36. return settable?.get(keypath) ?? 0
  37. default: return 0
  38. }
  39. }
  40. set { set(value: newValue) }
  41. }
  42. var insulinCurveValue: InsulinCurve {
  43. get {
  44. switch type {
  45. case let .insulinCurve(keypath):
  46. return settable?.get(keypath) ?? .rapidActing
  47. default: return .rapidActing
  48. }
  49. }
  50. set { set(value: newValue) }
  51. }
  52. private func set<T: SettableValue>(value: T) {
  53. switch (type, value) {
  54. case let (.boolean(keypath), value as Bool):
  55. settable?.set(keypath, value: value)
  56. case let (.decimal(keypath, minVal, maxVal), value as Decimal):
  57. let constrainedValue: Decimal
  58. if let minValue = minVal, let minValueDecimal: Decimal = settable?.get(minValue), let maxValue = maxVal,
  59. let maxValueDecimal: Decimal = settable?.get(maxValue)
  60. {
  61. constrainedValue = min(max(value, minValueDecimal), maxValueDecimal)
  62. } else if let minValue = minVal, let minValueDecimal: Decimal = settable?.get(minValue) {
  63. constrainedValue = max(value, minValueDecimal)
  64. } else if let maxValue = maxVal, let maxValueDecimal: Decimal = settable?.get(maxValue) {
  65. constrainedValue = min(value, maxValueDecimal)
  66. } else {
  67. constrainedValue = value
  68. }
  69. settable?.set(keypath, value: constrainedValue)
  70. case let (.insulinCurve(keypath), value as InsulinCurve):
  71. settable?.set(keypath, value: value)
  72. default: break
  73. }
  74. }
  75. weak var settable: PreferencesSettable?
  76. init(
  77. displayName: String,
  78. type: FieldType,
  79. infoText: String,
  80. settable: PreferencesSettable? = nil
  81. ) {
  82. self.displayName = displayName
  83. self.type = type
  84. self.infoText = infoText
  85. self.settable = settable
  86. }
  87. let id = UUID()
  88. }
  89. struct FieldSection: Identifiable {
  90. let displayName: String
  91. var fields: [Field]
  92. let id = UUID()
  93. }
  94. }
  95. protocol PreferencesEditorProvider: Provider {
  96. var preferences: Preferences { get }
  97. func savePreferences(_ preferences: Preferences)
  98. func migrateUnits()
  99. func updateManagerUnits()
  100. }
  101. protocol PreferencesSettable: AnyObject {
  102. func set<T>(_ keypath: WritableKeyPath<Preferences, T>, value: T)
  103. func get<T>(_ keypath: WritableKeyPath<Preferences, T>) -> T
  104. }