GlucoseNotificationSettingsRootView.swift 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import ActivityKit
  2. import Combine
  3. import SwiftUI
  4. import Swinject
  5. extension GlucoseNotificationSettings {
  6. struct RootView: BaseView {
  7. let resolver: Resolver
  8. @StateObject var state = StateModel()
  9. @State private var shouldDisplayHint: Bool = false
  10. @State var hintDetent = PresentationDetent.large
  11. @State var selectedVerboseHint: AnyView?
  12. @State var hintLabel: String?
  13. @State private var decimalPlaceholder: Decimal = 0.0
  14. @State private var booleanPlaceholder: Bool = false
  15. private var glucoseFormatter: NumberFormatter {
  16. let formatter = NumberFormatter()
  17. formatter.numberStyle = .decimal
  18. formatter.maximumFractionDigits = 0
  19. if state.units == .mmolL {
  20. formatter.maximumFractionDigits = 1
  21. }
  22. formatter.roundingMode = .halfUp
  23. return formatter
  24. }
  25. private var carbsFormatter: NumberFormatter {
  26. let formatter = NumberFormatter()
  27. formatter.numberStyle = .decimal
  28. formatter.maximumFractionDigits = 0
  29. return formatter
  30. }
  31. @Environment(\.colorScheme) var colorScheme
  32. var color: LinearGradient {
  33. colorScheme == .dark ? LinearGradient(
  34. gradient: Gradient(colors: [
  35. Color.bgDarkBlue,
  36. Color.bgDarkerDarkBlue
  37. ]),
  38. startPoint: .top,
  39. endPoint: .bottom
  40. )
  41. :
  42. LinearGradient(
  43. gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
  44. startPoint: .top,
  45. endPoint: .bottom
  46. )
  47. }
  48. var body: some View {
  49. Form {
  50. SettingInputSection(
  51. decimalValue: $decimalPlaceholder,
  52. booleanValue: $state.glucoseBadge,
  53. shouldDisplayHint: $shouldDisplayHint,
  54. selectedVerboseHint: Binding(
  55. get: { selectedVerboseHint },
  56. set: {
  57. selectedVerboseHint = $0.map { AnyView($0) }
  58. hintLabel = "Show Glucose App Badge"
  59. }
  60. ),
  61. units: state.units,
  62. type: .boolean,
  63. label: "Show Glucose App Badge",
  64. miniHint: """
  65. Show your current glucose reading at the top of the Trio app icon
  66. Default: OFF
  67. """,
  68. verboseHint: VStack {
  69. Text("Default: OFF").bold()
  70. Text("""
  71. This will add your current glucose on the top right of your Trio icon as a red notification badge.
  72. """)
  73. },
  74. headerText: "Various Glucose Notifications"
  75. )
  76. SettingInputSection(
  77. decimalValue: $decimalPlaceholder,
  78. booleanValue: $state.glucoseNotificationsAlways,
  79. shouldDisplayHint: $shouldDisplayHint,
  80. selectedVerboseHint: Binding(
  81. get: { selectedVerboseHint },
  82. set: {
  83. selectedVerboseHint = $0.map { AnyView($0) }
  84. hintLabel = "Always Notify Glucose"
  85. }
  86. ),
  87. units: state.units,
  88. type: .boolean,
  89. label: "Always Notify Glucose",
  90. miniHint: """
  91. A notification will be triggered every time your glucose is updated in Trio
  92. Default: OFF
  93. """,
  94. verboseHint: VStack {
  95. Text("Default: OFF").bold()
  96. Text("""
  97. A notification will be triggered every time your glucose is updated in Trio.
  98. """)
  99. }
  100. )
  101. SettingInputSection(
  102. decimalValue: $decimalPlaceholder,
  103. booleanValue: $state.useAlarmSound,
  104. shouldDisplayHint: $shouldDisplayHint,
  105. selectedVerboseHint: Binding(
  106. get: { selectedVerboseHint },
  107. set: {
  108. selectedVerboseHint = $0.map { AnyView($0) }
  109. hintLabel = "Play Alarm Sound"
  110. }
  111. ),
  112. units: state.units,
  113. type: .boolean,
  114. label: "Play Alarm Sound",
  115. miniHint: """
  116. This will cause a sound to be triggered by every Trio notification
  117. Default: OFF
  118. """,
  119. verboseHint: VStack {
  120. Text("Default: OFF").bold()
  121. Text("""
  122. This will cause a sound to be triggered by every Trio notification.
  123. """)
  124. }
  125. )
  126. SettingInputSection(
  127. decimalValue: $decimalPlaceholder,
  128. booleanValue: $state.addSourceInfoToGlucoseNotifications,
  129. shouldDisplayHint: $shouldDisplayHint,
  130. selectedVerboseHint: Binding(
  131. get: { selectedVerboseHint },
  132. set: {
  133. selectedVerboseHint = $0.map { AnyView($0) }
  134. hintLabel = "Add Glucose Source to Alarm"
  135. }
  136. ),
  137. units: state.units,
  138. type: .boolean,
  139. label: "Add Glucose Source to Alarm",
  140. miniHint: """
  141. The source of the glucose reading will be added to the notification
  142. Default: OFF
  143. """,
  144. verboseHint: VStack {
  145. Text("Default: OFF").bold()
  146. Text("""
  147. The source of the glucose reading will be added to the notification.
  148. """)
  149. }
  150. )
  151. Section {
  152. HStack {
  153. Text("Low Glucose Alarm Limit")
  154. Spacer()
  155. TextFieldWithToolBar(text: $state.lowGlucose, placeholder: "0", numberFormatter: glucoseFormatter)
  156. Text(state.units.rawValue).foregroundColor(.secondary)
  157. }.padding(.top)
  158. HStack {
  159. Text("High Glucose Alarm Limit")
  160. Spacer()
  161. TextFieldWithToolBar(text: $state.highGlucose, placeholder: "0", numberFormatter: glucoseFormatter)
  162. Text(state.units.rawValue).foregroundColor(.secondary)
  163. }
  164. HStack(alignment: .top) {
  165. Text("""
  166. Set the glucose alarm limits
  167. Tap hint icon for details
  168. """)
  169. .font(.footnote)
  170. .foregroundColor(.secondary)
  171. .lineLimit(nil)
  172. Spacer()
  173. Button(
  174. action: {
  175. hintLabel = "Low and High Glucose Alarm Limits"
  176. selectedVerboseHint =
  177. AnyView(VStack {
  178. Text("Low Default: 72 mg/dL").bold()
  179. Text("High Default: 270 mg/dL").bold()
  180. Text("""
  181. These two settings determine the range outside of which you will be notified via push notifications.
  182. If your CGM readings are below the Low value or above the High value, you will receive a glucose alarm.
  183. """)
  184. })
  185. shouldDisplayHint.toggle()
  186. },
  187. label: {
  188. HStack {
  189. Image(systemName: "questionmark.circle")
  190. }
  191. }
  192. ).buttonStyle(BorderlessButtonStyle())
  193. }.padding(.vertical)
  194. }
  195. .listRowBackground(Color.chart)
  196. }
  197. .sheet(isPresented: $shouldDisplayHint) {
  198. SettingInputHintView(
  199. hintDetent: $hintDetent,
  200. shouldDisplayHint: $shouldDisplayHint,
  201. hintLabel: hintLabel ?? "",
  202. hintText: selectedVerboseHint ?? AnyView(EmptyView()),
  203. sheetTitle: "Help"
  204. )
  205. }
  206. .scrollContentBackground(.hidden).background(color)
  207. .onAppear(perform: configureView)
  208. .navigationBarTitle("Glucose Notifications")
  209. .navigationBarTitleDisplayMode(.automatic)
  210. }
  211. }
  212. }