CGMRootView.swift 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import LoopKitUI
  2. import SwiftUI
  3. import Swinject
  4. extension CGM {
  5. struct RootView: BaseView {
  6. let resolver: Resolver
  7. let displayClose: Bool
  8. @StateObject var state = StateModel()
  9. @State private var setupCGM = false
  10. // @AppStorage(UserDefaults.BTKey.cgmTransmitterDeviceAddress.rawValue) private var cgmTransmitterDeviceAddress: String? = nil
  11. var body: some View {
  12. NavigationView {
  13. Form {
  14. Section(header: Text("CGM")) {
  15. Picker("Type", selection: $state.cgmCurrent) {
  16. ForEach(state.listOfCGM) { type in
  17. VStack(alignment: .leading) {
  18. Text(type.displayName)
  19. Text(type.subtitle).font(.caption).foregroundColor(.secondary)
  20. }.tag(type)
  21. }
  22. }
  23. if let link = state.cgmCurrent.type.externalLink {
  24. Button("About this source") {
  25. UIApplication.shared.open(link, options: [:], completionHandler: nil)
  26. }
  27. }
  28. }
  29. if let appURL = state.urlOfApp()
  30. {
  31. Section {
  32. Button {
  33. UIApplication.shared.open(appURL, options: [:]) { success in
  34. if !success {
  35. self.router.alertMessage
  36. .send(MessageContent(content: "Unable to open the app", type: .warning))
  37. }
  38. }
  39. }
  40. label: {
  41. Label(state.displayNameOfApp() ?? "-", systemImage: "waveform.path.ecg.rectangle").font(.title3) }
  42. .frame(maxWidth: .infinity, alignment: .center)
  43. .buttonStyle(.bordered)
  44. }
  45. .listRowBackground(Color.clear)
  46. } else if state.cgmCurrent.type == .nightscout {
  47. if let url = state.url {
  48. Section {
  49. Button {
  50. UIApplication.shared.open(url, options: [:]) { success in
  51. if !success {
  52. self.router.alertMessage
  53. .send(MessageContent(content: "No URL available", type: .warning))
  54. }
  55. }
  56. }
  57. label: { Label("Open URL", systemImage: "waveform.path.ecg.rectangle").font(.title3) }
  58. .frame(maxWidth: .infinity, alignment: .center)
  59. .buttonStyle(.bordered)
  60. }
  61. .listRowBackground(Color.clear)
  62. } else {
  63. Section {
  64. Button {
  65. state.showModal(for: .nighscoutConfigDirect)
  66. // router.mainSecondaryModalView.send(router.view(for: .nighscoutConfigDirect))
  67. }
  68. label: { Label("Config Nightscout", systemImage: "waveform.path.ecg.rectangle").font(.title3)
  69. }
  70. .frame(maxWidth: .infinity, alignment: .center)
  71. .buttonStyle(.bordered)
  72. }
  73. .listRowBackground(Color.clear)
  74. }
  75. }
  76. if state.cgmCurrent.type == .plugin {
  77. Section {
  78. Button("CGM Configuration") {
  79. setupCGM.toggle()
  80. }
  81. }
  82. }
  83. if state.cgmCurrent.type == .xdrip {
  84. Section(header: Text("Heartbeat")) {
  85. VStack(alignment: .leading) {
  86. if let cgmTransmitterDeviceAddress = state.cgmTransmitterDeviceAddress {
  87. Text("CGM address :")
  88. Text(cgmTransmitterDeviceAddress)
  89. } else {
  90. Text("CGM is not used as heartbeat.")
  91. }
  92. }
  93. }
  94. }
  95. if state.cgmCurrent.type == .plugin && state.cgmCurrent.id.contains("Libre") {
  96. Section(header: Text("Calibrations")) {
  97. Text("Calibrations").navigationLink(to: .calibrations, from: self)
  98. }
  99. }
  100. // }
  101. Section(header: Text("Calendar")) {
  102. Toggle("Create events in calendar", isOn: $state.createCalendarEvents)
  103. if state.calendarIDs.isNotEmpty {
  104. Picker("Calendar", selection: $state.currentCalendarID) {
  105. ForEach(state.calendarIDs, id: \.self) {
  106. Text($0).tag($0)
  107. }
  108. }
  109. }
  110. }
  111. Section(header: Text("Experimental")) {
  112. Toggle("Smooth Glucose Value", isOn: $state.smoothGlucose)
  113. }
  114. }
  115. .onAppear(perform: configureView)
  116. .navigationTitle("CGM")
  117. .navigationBarTitleDisplayMode(.automatic)
  118. .navigationBarItems(leading: displayClose ? Button("Close", action: state.hideModal) : nil)
  119. .sheet(isPresented: $setupCGM) {
  120. if let cgmFetchManager = state.cgmManager,
  121. let cgmManager = cgmFetchManager.cgmManager,
  122. state.cgmCurrent.type == cgmFetchManager.cgmGlucoseSourceType,
  123. state.cgmCurrent.id == cgmFetchManager.cgmGlucosePluginId
  124. {
  125. CGMSettingsView(
  126. cgmManager: cgmManager,
  127. bluetoothManager: state.provider.apsManager.bluetoothManager!,
  128. unit: state.settingsManager.settings.units,
  129. completionDelegate: state
  130. )
  131. } else {
  132. CGMSetupView(
  133. CGMType: state.cgmCurrent,
  134. bluetoothManager: state.provider.apsManager.bluetoothManager!,
  135. unit: state.settingsManager.settings.units,
  136. completionDelegate: state,
  137. setupDelegate: state,
  138. pluginCGMManager: self.state.pluginCGMManager
  139. )
  140. }
  141. }
  142. .onChange(of: setupCGM) { setupCGM in
  143. state.setupCGM = setupCGM
  144. }
  145. .onChange(of: state.setupCGM) { setupCGM in
  146. self.setupCGM = setupCGM
  147. }
  148. }
  149. }
  150. }
  151. }