NightscoutConfigRootView.swift 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import CoreData
  2. import SwiftUI
  3. import Swinject
  4. extension NightscoutConfig {
  5. struct RootView: BaseView {
  6. let resolver: Resolver
  7. let displayClose: Bool
  8. @StateObject var state = StateModel()
  9. @State var hintDetent = PresentationDetent.large
  10. @State private var hintPayload: HintPayload?
  11. @State private var decimalPlaceholder: Decimal = 0.0
  12. @State private var booleanPlaceholder: Bool = false
  13. @State var backfillAlert: Alert?
  14. @State var isBackfillAlertPresented = false
  15. private struct HintPayload: Identifiable {
  16. let id = UUID()
  17. let label: String
  18. let content: AnyView
  19. }
  20. private var shouldDisplayHintBinding: Binding<Bool> {
  21. Binding(
  22. get: { hintPayload != nil },
  23. set: { newValue in if !newValue { hintPayload = nil } }
  24. )
  25. }
  26. @Environment(\.colorScheme) var colorScheme
  27. @Environment(AppState.self) var appState
  28. var body: some View {
  29. ZStack {
  30. List {
  31. Section(
  32. header: Text("Nightscout Integration"),
  33. content: {
  34. NavigationLink(destination: NightscoutConnectView(state: state), label: {
  35. HStack {
  36. Text("Connect")
  37. ZStack {
  38. if state.isConnectedToNS {
  39. Image(systemName: "network")
  40. Image(systemName: "checkmark.circle.fill").foregroundColor(.green).font(.caption2)
  41. .offset(x: 9, y: 6)
  42. } else {
  43. Image(systemName: "network.slash")
  44. }
  45. }
  46. }
  47. })
  48. NavigationLink("Upload", destination: NightscoutUploadView(state: state))
  49. NavigationLink("Fetch", destination: NightscoutFetchView(state: state))
  50. }
  51. ).listRowBackground(Color.chart)
  52. Section(
  53. content:
  54. {
  55. VStack {
  56. Button {
  57. Task {
  58. await state.backfillGlucose()
  59. if !state.message.isEmpty && state.message.hasPrefix("Error:") {
  60. DispatchQueue.main.async {
  61. backfillAlert = Alert(
  62. title: Text("Backfill Failed"),
  63. message: Text(state.message),
  64. dismissButton: .default(Text("OK"))
  65. )
  66. isBackfillAlertPresented = true
  67. }
  68. }
  69. }
  70. } label: {
  71. Text("Backfill Glucose")
  72. .font(.title3) }
  73. .frame(maxWidth: .infinity, alignment: .center)
  74. .buttonStyle(.bordered)
  75. .disabled(state.url.isEmpty || state.connecting || state.backfilling)
  76. HStack(alignment: .center) {
  77. Text(
  78. "Backfill missing glucose data from Nightscout."
  79. )
  80. .font(.footnote)
  81. .foregroundColor(.secondary)
  82. .lineLimit(nil)
  83. Spacer()
  84. Button(
  85. action: {
  86. hintPayload = HintPayload(
  87. label: String(localized: "Backfill Glucose from Nightscout"),
  88. content: AnyView(
  89. Text(
  90. "This will backfill 24 hours of glucose data from your connected Nightscout URL to Trio"
  91. )
  92. )
  93. )
  94. },
  95. label: {
  96. HStack {
  97. Image(systemName: "questionmark.circle")
  98. }
  99. }
  100. ).buttonStyle(BorderlessButtonStyle())
  101. .alert(isPresented: $isBackfillAlertPresented) {
  102. backfillAlert ?? Alert(title: Text("Unknown Error"))
  103. }
  104. }.padding(.top)
  105. }.padding(.vertical)
  106. }
  107. ).listRowBackground(Color.chart)
  108. }
  109. .listSectionSpacing(sectionSpacing)
  110. }
  111. .sheet(item: $hintPayload) { payload in
  112. SettingInputHintView(
  113. hintDetent: $hintDetent,
  114. shouldDisplayHint: shouldDisplayHintBinding,
  115. hintLabel: payload.label,
  116. hintText: payload.content,
  117. sheetTitle: String(localized: "Help", comment: "Help sheet title")
  118. )
  119. }
  120. .navigationBarTitle("Nightscout")
  121. .navigationBarTitleDisplayMode(.automatic)
  122. .scrollContentBackground(.hidden).background(appState.trioBackgroundColor(for: colorScheme))
  123. .onAppear(perform: configureView)
  124. }
  125. }
  126. }