SettingsRootView.swift 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. var body: some View {
  12. Form {
  13. Section {
  14. Toggle("Closed loop", isOn: $state.closedLoop)
  15. }
  16. header: {
  17. if let expirationDate = Bundle.main.profileExpiration {
  18. Text(
  19. "Open-iAPS v\(state.versionNumber) (\(state.buildNumber))\nBranch: \(state.branch) \(state.copyrightNotice)" +
  20. "\nBuild Expires: " + expirationDate
  21. ).textCase(nil)
  22. } else {
  23. Text(
  24. "Open-iAPS v\(state.versionNumber) (\(state.buildNumber))\nBranch: \(state.branch) \(state.copyrightNotice)"
  25. )
  26. }
  27. }
  28. Section {
  29. Text("Pump").navigationLink(to: .pumpConfig, from: self)
  30. Text("CGM").navigationLink(to: .cgm, from: self)
  31. Text("Watch").navigationLink(to: .watch, from: self)
  32. } header: { Text("Devices") }
  33. Section {
  34. Text("Nightscout").navigationLink(to: .nighscoutConfig, from: self)
  35. Text("TidePool")
  36. .onTapGesture {
  37. state.setupTidePool = true
  38. }
  39. if HKHealthStore.isHealthDataAvailable() {
  40. Text("Apple Health").navigationLink(to: .healthkit, from: self)
  41. }
  42. Text("Notifications").navigationLink(to: .notificationsConfig, from: self)
  43. Text("Fat And Protein Conversion").navigationLink(to: .fpuConfig, from: self)
  44. Text("App Icons").navigationLink(to: .iconConfig, from: self)
  45. Text("Statistics and Home View").navigationLink(to: .statisticsConfig, from: self)
  46. } header: { Text("Services") }
  47. Section {
  48. Text("Preferences").navigationLink(to: .preferencesEditor, from: self)
  49. Text("Pump Settings").navigationLink(to: .pumpSettingsEditor, from: self)
  50. Text("Basal Profile").navigationLink(to: .basalProfileEditor, from: self)
  51. Text("Insulin Sensitivities").navigationLink(to: .isfEditor, from: self)
  52. Text("Carb Ratios").navigationLink(to: .crEditor, from: self)
  53. Text("Target Glucose").navigationLink(to: .targetsEditor, from: self)
  54. Text("Autotune").navigationLink(to: .autotuneConfig, from: self)
  55. } header: { Text("Configuration") }
  56. Section {
  57. Toggle("Debug options", isOn: $state.debugOptions)
  58. if state.debugOptions {
  59. Group {
  60. HStack {
  61. Text("NS Upload Profile and Settings")
  62. Button("Upload") { state.uploadProfileAndSettings(true) }
  63. .frame(maxWidth: .infinity, alignment: .trailing)
  64. .buttonStyle(.borderedProminent)
  65. }
  66. }
  67. Group {
  68. Text("Preferences")
  69. .navigationLink(to: .configEditor(file: OpenAPS.Settings.preferences), from: self)
  70. Text("Pump Settings")
  71. .navigationLink(to: .configEditor(file: OpenAPS.Settings.settings), from: self)
  72. Text("Autosense")
  73. .navigationLink(to: .configEditor(file: OpenAPS.Settings.autosense), from: self)
  74. Text("Pump History")
  75. .navigationLink(to: .configEditor(file: OpenAPS.Monitor.pumpHistory), from: self)
  76. Text("Basal profile")
  77. .navigationLink(to: .configEditor(file: OpenAPS.Settings.basalProfile), from: self)
  78. Text("Targets ranges")
  79. .navigationLink(to: .configEditor(file: OpenAPS.Settings.bgTargets), from: self)
  80. Text("Temp targets")
  81. .navigationLink(to: .configEditor(file: OpenAPS.Settings.tempTargets), from: self)
  82. Text("Meal")
  83. .navigationLink(to: .configEditor(file: OpenAPS.Monitor.meal), from: self)
  84. }
  85. Group {
  86. Text("Pump profile")
  87. .navigationLink(to: .configEditor(file: OpenAPS.Settings.pumpProfile), from: self)
  88. Text("Profile")
  89. .navigationLink(to: .configEditor(file: OpenAPS.Settings.profile), from: self)
  90. Text("Carbs")
  91. .navigationLink(to: .configEditor(file: OpenAPS.Monitor.carbHistory), from: self)
  92. Text("Enacted")
  93. .navigationLink(to: .configEditor(file: OpenAPS.Enact.enacted), from: self)
  94. Text("Announcements")
  95. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcements), from: self)
  96. Text("Enacted announcements")
  97. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcementsEnacted), from: self)
  98. Text("Autotune")
  99. .navigationLink(to: .configEditor(file: OpenAPS.Settings.autotune), from: self)
  100. Text("Glucose")
  101. .navigationLink(to: .configEditor(file: OpenAPS.Monitor.glucose), from: self)
  102. }
  103. Group {
  104. Text("Target presets")
  105. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.tempTargetsPresets), from: self)
  106. Text("Calibrations")
  107. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.calibrations), from: self)
  108. Text("Middleware")
  109. .navigationLink(to: .configEditor(file: OpenAPS.Middleware.determineBasal), from: self)
  110. Text("Statistics")
  111. .navigationLink(to: .configEditor(file: OpenAPS.Monitor.statistics), from: self)
  112. Text("Edit settings json")
  113. .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.settings), from: self)
  114. }
  115. }
  116. } header: { Text("Developer") }
  117. Section {
  118. Toggle("Animated Background", isOn: $state.animatedBackground)
  119. }
  120. Section {
  121. Text("Share logs")
  122. .onTapGesture {
  123. showShareSheet = true
  124. }
  125. }
  126. }
  127. .sheet(isPresented: $showShareSheet) {
  128. ShareSheet(activityItems: state.logItems())
  129. }
  130. .sheet(isPresented: $state.setupTidePool) {
  131. if let serviceUIType = state.serviceUIType,
  132. let pluginHost = state.provider.tidePoolManager.getTidePoolPluginHost()
  133. {
  134. if let serviceUI = state.provider.tidePoolManager.getTidePoolServiceUI() {
  135. TidePoolSettingsView(
  136. serviceUI: serviceUI,
  137. serviceOnBoardDelegate: self.state,
  138. serviceDelegate: self.state
  139. )
  140. } else {
  141. TidePoolSetupView(
  142. serviceUIType: serviceUIType,
  143. pluginHost: pluginHost,
  144. serviceOnBoardDelegate: self.state,
  145. serviceDelegate: self.state
  146. )
  147. }
  148. }
  149. }
  150. .onAppear(perform: configureView)
  151. .navigationTitle("Settings")
  152. .navigationBarItems(leading: Button("Close", action: state.hideSettingsModal))
  153. .navigationBarTitleDisplayMode(.automatic)
  154. .onDisappear(perform: { state.uploadProfileAndSettings(false) })
  155. }
  156. }
  157. }