NightscoutConfigRootView.swift 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import CoreData
  2. import SwiftUI
  3. import Swinject
  4. extension NightscoutConfig {
  5. struct RootView: BaseView {
  6. let resolver: Resolver
  7. @StateObject var state = StateModel()
  8. @State var importAlert: Alert?
  9. @State var isImportAlertPresented = false
  10. @FetchRequest(
  11. entity: ImportError.entity(),
  12. sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)], predicate: NSPredicate(
  13. format: "date > %@", Date().addingTimeInterval(-1.minutes.timeInterval) as NSDate
  14. )
  15. ) var fetchedErrors: FetchedResults<ImportError>
  16. private var portFormater: NumberFormatter {
  17. let formatter = NumberFormatter()
  18. formatter.allowsFloats = false
  19. return formatter
  20. }
  21. var body: some View {
  22. Form {
  23. Section {
  24. TextField("URL", text: $state.url)
  25. .disableAutocorrection(true)
  26. .textContentType(.URL)
  27. .autocapitalization(.none)
  28. .keyboardType(.URL)
  29. SecureField("API secret", text: $state.secret)
  30. .disableAutocorrection(true)
  31. .autocapitalization(.none)
  32. .textContentType(.password)
  33. .keyboardType(.asciiCapable)
  34. if !state.message.isEmpty {
  35. Text(state.message)
  36. }
  37. if state.connecting {
  38. HStack {
  39. Text("Connecting...")
  40. Spacer()
  41. ProgressView()
  42. }
  43. }
  44. }
  45. Section {
  46. Button("Connect") { state.connect() }
  47. .disabled(state.url.isEmpty || state.connecting)
  48. Button("Delete") { state.delete() }.foregroundColor(.red).disabled(state.connecting)
  49. }
  50. Section {
  51. Toggle("Upload", isOn: $state.isUploadEnabled)
  52. if state.isUploadEnabled {
  53. Toggle("Statistics", isOn: $state.uploadStats)
  54. Toggle("Glucose", isOn: $state.uploadGlucose)
  55. }
  56. } header: {
  57. Text("Allow Uploads")
  58. }
  59. Section {
  60. Button("Import settings from Nightscout") {
  61. importAlert = Alert(
  62. title: Text("Import settings?"),
  63. message: Text(
  64. "\n" +
  65. NSLocalizedString(
  66. "This will replace some or all of your current pump settings. Are you sure you want to import profile settings from Nightscout?",
  67. comment: "Profile Import Alert"
  68. ) +
  69. "\n"
  70. ),
  71. primaryButton: .destructive(
  72. Text("Yes, Import"),
  73. action: {
  74. state.startImport()
  75. }
  76. ),
  77. secondaryButton: .cancel()
  78. )
  79. isImportAlertPresented.toggle()
  80. }.disabled(state.url.isEmpty || state.connecting)
  81. } header: { Text("Import from Nightscout") }
  82. .alert(isPresented: $state.importedHasRun) {
  83. Alert(
  84. title: Text("Settings imported"),
  85. message: Text(
  86. (fetchedErrors.first?.error ?? "").count < 4 ?
  87. NSLocalizedString(
  88. "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects.",
  89. comment: "Imported Profiles Alert"
  90. ) :
  91. NSLocalizedString("\nImport failed:\n\n*", comment: "Failed Profile Import Alert") +
  92. NSLocalizedString(fetchedErrors.first?.error ?? "", comment: "Import Error")
  93. ),
  94. primaryButton: .destructive(
  95. Text("OK")
  96. ),
  97. secondaryButton: .cancel()
  98. )
  99. }
  100. Section {
  101. Toggle("Use local glucose server", isOn: $state.useLocalSource)
  102. HStack {
  103. Text("Port")
  104. DecimalTextField("", value: $state.localPort, formatter: portFormater)
  105. }
  106. } header: { Text("Local glucose source") }
  107. Section {
  108. Button("Backfill glucose") { state.backfillGlucose() }
  109. .disabled(state.url.isEmpty || state.connecting || state.backfilling)
  110. }
  111. }
  112. .onAppear(perform: configureView)
  113. .navigationBarTitle("Nightscout Config")
  114. .navigationBarTitleDisplayMode(.automatic)
  115. .alert(isPresented: $isImportAlertPresented) {
  116. importAlert!
  117. }
  118. }
  119. }
  120. }