UserInterfaceSettingsRootView.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import SwiftUI
  2. import Swinject
  3. extension UserInterfaceSettings {
  4. struct RootView: BaseView {
  5. let resolver: Resolver
  6. @StateObject var state = StateModel()
  7. @State private var shouldDisplayHint: Bool = false
  8. @State var hintDetent = PresentationDetent.large
  9. @State var selectedVerboseHint: String?
  10. @State var hintLabel: String?
  11. @State private var decimalPlaceholder: Decimal = 0.0
  12. @State private var booleanPlaceholder: Bool = false
  13. @Environment(\.colorScheme) var colorScheme
  14. var color: LinearGradient {
  15. colorScheme == .dark ? LinearGradient(
  16. gradient: Gradient(colors: [
  17. Color.bgDarkBlue,
  18. Color.bgDarkerDarkBlue
  19. ]),
  20. startPoint: .top,
  21. endPoint: .bottom
  22. )
  23. :
  24. LinearGradient(
  25. gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
  26. startPoint: .top,
  27. endPoint: .bottom
  28. )
  29. }
  30. private var glucoseFormatter: NumberFormatter {
  31. let formatter = NumberFormatter()
  32. formatter.numberStyle = .decimal
  33. formatter.maximumFractionDigits = 0
  34. if state.units == .mmolL {
  35. formatter.maximumFractionDigits = 1
  36. }
  37. formatter.roundingMode = .halfUp
  38. return formatter
  39. }
  40. private var carbsFormatter: NumberFormatter {
  41. let formatter = NumberFormatter()
  42. formatter.numberStyle = .decimal
  43. formatter.maximumFractionDigits = 0
  44. return formatter
  45. }
  46. var body: some View {
  47. Form {
  48. Section(
  49. header: Text("Home View Settings"),
  50. content: {
  51. VStack {
  52. Toggle("Show X-Axis Grid Lines", isOn: $state.xGridLines)
  53. Toggle("Show Y-Axis Grid Line", isOn: $state.yGridLines)
  54. HStack(alignment: .top) {
  55. Text(
  56. "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
  57. )
  58. .font(.footnote)
  59. .foregroundColor(.secondary)
  60. .lineLimit(nil)
  61. Spacer()
  62. Button(
  63. action: {
  64. hintLabel = "Show Main Chart X- and Y-Axis Grid Lines"
  65. selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
  66. shouldDisplayHint.toggle()
  67. },
  68. label: {
  69. HStack {
  70. Image(systemName: "questionmark.circle")
  71. }
  72. }
  73. ).buttonStyle(BorderlessButtonStyle())
  74. }.padding(.top)
  75. }.padding(.bottom)
  76. }
  77. ).listRowBackground(Color.chart)
  78. SettingInputSection(
  79. decimalValue: $decimalPlaceholder,
  80. booleanValue: $state.rulerMarks,
  81. shouldDisplayHint: $shouldDisplayHint,
  82. selectedVerboseHint: Binding(
  83. get: { selectedVerboseHint },
  84. set: {
  85. selectedVerboseHint = $0
  86. hintLabel = "Show Low and High Thresholds"
  87. }
  88. ),
  89. type: .boolean,
  90. label: "Show Low and High Thresholds",
  91. miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
  92. verboseHint: "Display Low and High Thresholds… bla bla bla"
  93. )
  94. Section {
  95. VStack {
  96. HStack {
  97. Text("Low Threshold")
  98. Spacer()
  99. TextFieldWithToolBar(text: $state.low, placeholder: "0", numberFormatter: glucoseFormatter)
  100. Text(state.units.rawValue).foregroundColor(.secondary)
  101. }.padding(.top)
  102. HStack {
  103. Text("High Threshold")
  104. Spacer()
  105. TextFieldWithToolBar(text: $state.high, placeholder: "0", numberFormatter: glucoseFormatter)
  106. Text(state.units.rawValue).foregroundColor(.secondary)
  107. }
  108. HStack(alignment: .top) {
  109. Text(
  110. "Sets thresholds for low and high glucose in home view main chart and statistics view."
  111. )
  112. .lineLimit(nil)
  113. .font(.footnote)
  114. .foregroundColor(.secondary)
  115. Spacer()
  116. Button(
  117. action: {
  118. hintLabel = "Low and High Thresholds"
  119. selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
  120. shouldDisplayHint.toggle()
  121. },
  122. label: {
  123. HStack {
  124. Image(systemName: "questionmark.circle")
  125. }
  126. }
  127. ).buttonStyle(BorderlessButtonStyle())
  128. }
  129. }.padding(.bottom)
  130. }.listRowBackground(Color.chart)
  131. SettingInputSection(
  132. decimalValue: $state.hours,
  133. booleanValue: $booleanPlaceholder,
  134. shouldDisplayHint: $shouldDisplayHint,
  135. selectedVerboseHint: Binding(
  136. get: { selectedVerboseHint },
  137. set: {
  138. selectedVerboseHint = $0
  139. hintLabel = "X-Axis Interval Step"
  140. }
  141. ),
  142. type: .decimal,
  143. label: "X-Axis Interval Step",
  144. miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
  145. verboseHint: "X-Axis Interval Step… bla bla bla"
  146. )
  147. Section {
  148. VStack {
  149. Picker(
  150. selection: $state.totalInsulinDisplayType,
  151. label: Text("Total Insulin Display Type")
  152. ) {
  153. ForEach(TotalInsulinDisplayType.allCases) { selection in
  154. Text(selection.displayName).tag(selection)
  155. }
  156. }.padding(.top)
  157. HStack(alignment: .top) {
  158. Text(
  159. "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
  160. )
  161. .font(.footnote)
  162. .foregroundColor(.secondary)
  163. .lineLimit(nil)
  164. Spacer()
  165. Button(
  166. action: {
  167. hintLabel = "Total Insulin Display Type"
  168. selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
  169. shouldDisplayHint.toggle()
  170. },
  171. label: {
  172. HStack {
  173. Image(systemName: "questionmark.circle")
  174. }
  175. }
  176. ).buttonStyle(BorderlessButtonStyle())
  177. }.padding(.top)
  178. }.padding(.bottom)
  179. }.listRowBackground(Color.chart)
  180. // TODO: this needs to be a picker: mmol/L or %
  181. SettingInputSection(
  182. decimalValue: $decimalPlaceholder,
  183. booleanValue: $state.overrideHbA1cUnit,
  184. shouldDisplayHint: $shouldDisplayHint,
  185. selectedVerboseHint: Binding(
  186. get: { selectedVerboseHint },
  187. set: {
  188. selectedVerboseHint = $0
  189. hintLabel = "Override HbA1c Unit"
  190. }
  191. ),
  192. type: .boolean,
  193. label: "Override HbA1c Unit",
  194. miniHint: "Display HbA1c in mmol/L or %. Default is percent.",
  195. verboseHint: "Override HbA1c Unit… bla bla bla",
  196. headerText: "Trio Statistics"
  197. )
  198. // TODO: this needs to be a picker: choose bar chart or progress bar
  199. SettingInputSection(
  200. decimalValue: $decimalPlaceholder,
  201. booleanValue: $state.oneDimensionalGraph,
  202. shouldDisplayHint: $shouldDisplayHint,
  203. selectedVerboseHint: Binding(
  204. get: { selectedVerboseHint },
  205. set: {
  206. selectedVerboseHint = $0
  207. hintLabel = "Standing / Laying TIR Chart"
  208. }
  209. ),
  210. type: .boolean,
  211. label: "Standing / Laying TIR Chart",
  212. miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
  213. verboseHint: "Standing / Laying TIR Chart… bla bla bla"
  214. )
  215. SettingInputSection(
  216. decimalValue: $state.carbsRequiredThreshold,
  217. booleanValue: $state.showCarbsRequiredBadge,
  218. shouldDisplayHint: $shouldDisplayHint,
  219. selectedVerboseHint: Binding(
  220. get: { selectedVerboseHint },
  221. set: {
  222. selectedVerboseHint = $0
  223. hintLabel = "Show Carbs Required Badge"
  224. }
  225. ),
  226. type: .conditionalDecimal,
  227. label: "Show Carbs Required Badge",
  228. conditionalLabel: "Carbs Required Threshold",
  229. miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
  230. verboseHint: "Show Carbs Required Badge… bla bla bla",
  231. headerText: "Carbs Required Badge"
  232. )
  233. }
  234. .sheet(isPresented: $shouldDisplayHint) {
  235. SettingInputHintView(
  236. hintDetent: $hintDetent,
  237. shouldDisplayHint: $shouldDisplayHint,
  238. hintLabel: hintLabel ?? "",
  239. hintText: selectedVerboseHint ?? "",
  240. sheetTitle: "Help"
  241. )
  242. }
  243. .scrollContentBackground(.hidden).background(color)
  244. .onAppear(perform: configureView)
  245. .navigationBarTitle("User Interface")
  246. .navigationBarTitleDisplayMode(.automatic)
  247. }
  248. }
  249. }