PreferencesEditorDataFlow.swift 3.4 KB

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