SettingsRootView.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. import HealthKit
  2. import LoopKit
  3. import LoopKitUI
  4. import SwiftUI
  5. import Swinject
  6. extension Settings {
  7. struct RootView: BaseView {
  8. let resolver: Resolver
  9. @StateObject var state = StateModel()
  10. @State private var showShareSheet = false
  11. @StateObject private var viewModel = SettingsRootViewModel()
  12. @Environment(\.colorScheme) var colorScheme
  13. private var color: LinearGradient {
  14. colorScheme == .dark ? LinearGradient(
  15. gradient: Gradient(colors: [
  16. Color.bgDarkBlue,
  17. Color.bgDarkerDarkBlue
  18. ]),
  19. startPoint: .top,
  20. endPoint: .bottom
  21. )
  22. :
  23. LinearGradient(
  24. gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
  25. startPoint: .top,
  26. endPoint: .bottom
  27. )
  28. }
  29. var body: some View {
  30. Form {
  31. Section {
  32. <<<<<<< HEAD
  33. HStack(spacing: 15) {
  34. Image(systemName: "circle")
  35. .imageScale(.small)
  36. .font(.system(size: 32))
  37. .foregroundColor(Color.green)
  38. Toggle("Closed loop", isOn: $state.closedLoop)
  39. .font(.subheadline)
  40. .foregroundStyle(.primary)
  41. }
  42. } header: {
  43. Text(
  44. "iAPS v\(state.versionNumber) (\(state.buildNumber))\nBranch: \(state.branch) \(state.copyrightNotice)\nBuild Expires: \(Bundle.main.profileExpiration)"
  45. )
  46. .textCase(nil)
  47. }.listRowBackground(Color.chart)
  48. Section {
  49. SettingsRowView(imageName: "chart.xyaxis.line", title: "Statistics", tint: Color.green, spacing: 10)
  50. .navigationLink(to: .statistics, from: self)
  51. } header: { Text("Statistics") }.listRowBackground(Color.chart)
  52. Section {
  53. SettingsRowViewCustomImage(imageName: "pod", title: "Pump")
  54. .navigationLink(to: .pumpConfig, from: self)
  55. SettingsRowViewCustomImage(imageName: "g6", title: "CGM")
  56. .navigationLink(to: .cgm, from: self)
  57. SettingsRowView(imageName: "applewatch.watchface", title: "Watch", tint: Color.primary, spacing: 18)
  58. .navigationLink(to: .watch, from: self)
  59. } header: { Text("Select Devices") }.listRowBackground(Color.chart)
  60. Section {
  61. SettingsRowViewCustomImage(imageName: "owl", title: "Nightscout", frame: 32)
  62. .navigationLink(to: .nighscoutConfig, from: self)
  63. if HKHealthStore.isHealthDataAvailable() {
  64. SettingsRowView(imageName: "heart.circle.fill", title: "Apple Health", tint: Color.red)
  65. .navigationLink(to: .healthkit, from: self)
  66. }
  67. SettingsRowView(imageName: "message.circle.fill", title: "Notifications", tint: Color.blue)
  68. .navigationLink(to: .notificationsConfig, from: self)
  69. } header: { Text("Services") }.listRowBackground(Color.chart)
  70. Section {
  71. SettingsRowViewCustomImage(imageName: "pod", title: "Pump Settings")
  72. .navigationLink(to: .pumpSettingsEditor, from: self)
  73. SettingsRowView(imageName: "chart.bar.xaxis", title: "Basal Profile", tint: Color.insulin, spacing: 10)
  74. .navigationLink(to: .basalProfileEditor, from: self)
  75. SettingsRowView(imageName: "drop.fill", title: "Insulin Sensitivities", tint: Color.insulin, spacing: 22)
  76. .navigationLink(to: .isfEditor, from: self)
  77. SettingsRowView(imageName: "fork.knife.circle", title: "Carb Ratios", tint: Color.orange, spacing: 14)
  78. .navigationLink(to: .crEditor, from: self)
  79. SettingsRowView(imageName: "target", title: "Target Glucose", tint: Color.green, spacing: 14)
  80. .navigationLink(to: .targetsEditor, from: self)
  81. } header: { Text("Configuration") }.listRowBackground(Color.chart)
  82. Section {
  83. Text("OpenAPS").navigationLink(to: .preferencesEditor, from: self)
  84. Text("Autotune").navigationLink(to: .autotuneConfig, from: self)
  85. } header: { Text("OpenAPS") }.listRowBackground(Color.chart)
  86. Section {
  87. Text("UI/UX").navigationLink(to: .statisticsConfig, from: self)
  88. Text("App Icons").navigationLink(to: .iconConfig, from: self)
  89. Text("Bolus Calculator").navigationLink(to: .bolusCalculatorConfig, from: self)
  90. Text("Fat And Protein Conversion").navigationLink(to: .fpuConfig, from: self)
  91. Text("Dynamic ISF").navigationLink(to: .dynamicISF, from: self)
  92. } header: { Text("Extra Features") }.listRowBackground(Color.chart)
  93. Section {
  94. =======
  95. Toggle("Closed loop", isOn: $state.closedLoop)
  96. }
  97. header: {
  98. Text(viewModel.headerText).textCase(nil)
  99. }
  100. Section {
  101. Text("Pump").navigationLink(to: .pumpConfig, from: self)
  102. Text("CGM").navigationLink(to: .cgm, from: self)
  103. Text("Watch").navigationLink(to: .watch, from: self)
  104. } header: { Text("Devices") }
  105. Section {
  106. Text("Nightscout").navigationLink(to: .nighscoutConfig, from: self)
  107. NavigationLink(destination: TidepoolStartView(state: state)) {
  108. Text("Tidepool")
  109. }
  110. if HKHealthStore.isHealthDataAvailable() {
  111. Text("Apple Health").navigationLink(to: .healthkit, from: self)
  112. }
  113. Text("Notifications").navigationLink(to: .notificationsConfig, from: self)
  114. Text("App Icons").navigationLink(to: .iconConfig, from: self)
  115. Text("Statistics and Home View").navigationLink(to: .statisticsConfig, from: self)
  116. } header: { Text("Services") }
  117. Section {
  118. Text("Preferences").navigationLink(to: .preferencesEditor, from: self)
  119. Text("Pump Settings").navigationLink(to: .pumpSettingsEditor, from: self)
  120. Text("Meal Settings").navigationLink(to: .fpuConfig, from: self)
  121. Text("Basal Profile").navigationLink(to: .basalProfileEditor, from: self)
  122. Text("Insulin Sensitivities").navigationLink(to: .isfEditor, from: self)
  123. Text("Carb Ratios").navigationLink(to: .crEditor, from: self)
  124. Text("Target Glucose").navigationLink(to: .targetsEditor, from: self)
  125. Text("Autotune").navigationLink(to: .autotuneConfig, from: self)
  126. } header: { Text("Configuration") }
  127. Section {
  128. >>>>>>> 9672da256c317a314acc76d6e4f6e82cc174d133
  129. Toggle("Debug options", isOn: $state.debugOptions)
  130. if state.debugOptions {
  131. Group {
  132. HStack {
  133. Text("NS Upload Profile and Settings")
  134. Button("Upload") { state.uploadProfileAndSettings(true) }
  135. .frame(maxWidth: .infinity, alignment: .trailing)
  136. .buttonStyle(.borderedProminent)
  137. }
  138. <<<<<<< HEAD
  139. =======
  140. // Commenting this out for now, as not needed and possibly dangerous for users to be able to nuke their pump pairing informations via the debug menu
  141. // Leaving it in here, as it may be a handy functionality for further testing or developers.
  142. // See https://github.com/nightscout/Trio/pull/277 for more information
  143. //
  144. // HStack {
  145. // Text("Delete Stored Pump State Binary Files")
  146. // Button("Delete") { state.resetLoopDocuments() }
  147. // .frame(maxWidth: .infinity, alignment: .trailing)
  148. // .buttonStyle(.borderedProminent)
  149. // }
  150. >>>>>>> 9672da256c317a314acc76d6e4f6e82cc174d133
  151. }
  152. Group {
  153. Text("Preferences")
  154. .navigationLink(to: .configEditor(file: OpenAPS.Settings.preferences), from: self)
  155. Text("Pump Settings")
  156. .navigationLink(to: .configEditor(file: OpenAPS.Settings.settings), from: self)
  157. Text("Autosense")
  158. .navigationLink(to: .configEditor(file: OpenAPS.Settings.autosense), from: self)
  159. Text("Pump History")
  160. .navigationLink(to: .configEditor(file: OpenAPS.Monitor.pumpHistory), from: self)
  161. Text("Basal profile")
  162. .navigationLink(to: .configEditor(file: OpenAPS.Settings.basalProfile), from: self)
  163. Text("Targets ranges")
  164. .navigationLink(to: .configEditor(file: OpenAPS.Settings.bgTargets), from: self)
  165. Text("Temp targets")
  166. .navigationLink(to: .configEditor(file: OpenAPS.Settings.tempTargets), from: self)
  167. }
  168. Group {
  169. Text("Pump profile")
  170. .navigationLink(to: .configEditor(file: OpenAPS.Settings.pumpProfile), from: self)
  171. Text("Profile")
  172. .navigationLink(to: .configEditor(file: OpenAPS.Settings.profile), from: self)
  173. Text("Carbs")
  174. .navigationLink(to: .configEditor(file: OpenAPS.Monitor.carbHistory), from: self)
  175. Text("Announcements")
  176. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcements), from: self)
  177. Text("Enacted announcements")
  178. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcementsEnacted), from: self)
  179. Text("Autotune")
  180. .navigationLink(to: .configEditor(file: OpenAPS.Settings.autotune), from: self)
  181. }
  182. Group {
  183. Text("Target presets")
  184. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.tempTargetsPresets), from: self)
  185. Text("Calibrations")
  186. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.calibrations), from: self)
  187. Text("Middleware")
  188. .navigationLink(to: .configEditor(file: OpenAPS.Middleware.determineBasal), from: self)
  189. Text("Statistics")
  190. .navigationLink(to: .configEditor(file: OpenAPS.Monitor.statistics), from: self)
  191. Text("Edit settings json")
  192. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.settings), from: self)
  193. }
  194. }
  195. <<<<<<< HEAD
  196. } header: { Text("Developer") }.listRowBackground(Color.chart)
  197. =======
  198. } header: { Text("Developer") }
  199. >>>>>>> 9672da256c317a314acc76d6e4f6e82cc174d133
  200. Section {
  201. Toggle("Animated Background", isOn: $state.animatedBackground)
  202. }.listRowBackground(Color.chart)
  203. Section {
  204. Text("Share logs")
  205. .onTapGesture {
  206. showShareSheet = true
  207. }
  208. }.listRowBackground(Color.chart)
  209. }.scrollContentBackground(.hidden).background(color)
  210. .sheet(isPresented: $showShareSheet) {
  211. ShareSheet(activityItems: state.logItems())
  212. }
  213. <<<<<<< HEAD
  214. .onAppear(perform: configureView)
  215. .navigationTitle("Settings")
  216. .navigationBarTitleDisplayMode(.large)
  217. .onDisappear(perform: { state.uploadProfileAndSettings(false) })
  218. .screenNavigation(self)
  219. =======
  220. }
  221. .sheet(isPresented: $showShareSheet) {
  222. ShareSheet(activityItems: state.logItems())
  223. }
  224. .onAppear(perform: configureView)
  225. .navigationTitle("Settings")
  226. .navigationBarItems(leading: Button("Close", action: state.hideSettingsModal))
  227. .navigationBarTitleDisplayMode(.automatic)
  228. .onDisappear(perform: { state.uploadProfileAndSettings(false) })
  229. >>>>>>> 9672da256c317a314acc76d6e4f6e82cc174d133
  230. }
  231. }
  232. }