BackgroundRefreshSettingsView.swift 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. //
  2. // BackgroundRefreshSettingsView.swift
  3. // LoopFollow
  4. //
  5. import SwiftUI
  6. struct BackgroundRefreshSettingsView: View {
  7. @ObservedObject var viewModel: BackgroundRefreshSettingsViewModel
  8. @Environment(\.presentationMode) var presentationMode
  9. @ObservedObject var bleManager = BLEManager.shared
  10. @ObservedObject var selectedBLEDevice = Storage.shared.selectedBLEDevice
  11. var body: some View {
  12. NavigationView {
  13. Form {
  14. refreshTypeSection
  15. if viewModel.backgroundRefreshType.isBluetooth {
  16. selectedDeviceSection
  17. availableDevicesSection
  18. }
  19. }
  20. .navigationBarTitle("Background Refresh Settings", displayMode: .inline)
  21. .toolbar {
  22. ToolbarItem(placement: .navigationBarTrailing) {
  23. Button("Done") {
  24. presentationMode.wrappedValue.dismiss()
  25. }
  26. }
  27. }
  28. }
  29. }
  30. // MARK: - Subviews / Computed Properties
  31. private var refreshTypeSection: some View {
  32. Section {
  33. Picker("Background Refresh Type", selection: $viewModel.backgroundRefreshType) {
  34. ForEach(BackgroundRefreshType.allCases, id: \.self) { type in
  35. Text(type.rawValue).tag(type)
  36. }
  37. }
  38. .pickerStyle(MenuPickerStyle())
  39. VStack(alignment: .leading, spacing: 4) {
  40. Text("Adjust the background refresh type.")
  41. .font(.footnote)
  42. .foregroundColor(.secondary)
  43. switch viewModel.backgroundRefreshType {
  44. case .none:
  45. Text("No background refresh. Alarms and updates will not work unless the app is open in the foreground.")
  46. .font(.footnote)
  47. .foregroundColor(.secondary)
  48. case .silentTune:
  49. Text("A silent tune will play in the background, keeping the app active. May be interrupted by other apps. Allows continuous updates but consumes more battery.")
  50. .font(.footnote)
  51. .foregroundColor(.secondary)
  52. case .rileyLink:
  53. Text("Requires a RileyLink-compatible device within Bluetooth range. Provides updates once per minute and uses less battery than the silent tune method.")
  54. .font(.footnote)
  55. .foregroundColor(.secondary)
  56. case .dexcom:
  57. Text("Requires a Dexcom G6/ONE/G7/ONE+ transmitter within Bluetooth range. Provides updates every 5 minutes and uses less battery than the silent tune method.")
  58. .font(.footnote)
  59. .foregroundColor(.secondary)
  60. }
  61. }
  62. }
  63. }
  64. @ViewBuilder
  65. private var selectedDeviceSection: some View {
  66. if let storedDevice = selectedBLEDevice.value {
  67. Section(header: Text("Selected Device")) {
  68. VStack(alignment: .leading, spacing: 4) {
  69. Text(storedDevice.name ?? "Unknown Device")
  70. .font(.headline)
  71. deviceConnectionStatus(for: storedDevice)
  72. HStack {
  73. Spacer()
  74. Button(action: {
  75. bleManager.disconnect()
  76. }) {
  77. Text("Disconnect")
  78. .foregroundColor(.blue)
  79. }
  80. .buttonStyle(BorderlessButtonStyle())
  81. Spacer()
  82. }
  83. }
  84. .padding(.vertical, 8)
  85. }
  86. }
  87. }
  88. private var availableDevicesSection: some View {
  89. Section(header: Text("Available Devices")) {
  90. BLEDeviceSelectionView(
  91. bleManager: bleManager,
  92. selectedFilter: viewModel.backgroundRefreshType,
  93. onSelectDevice: { device in
  94. bleManager.connect(device: device)
  95. }
  96. )
  97. }
  98. }
  99. private func deviceConnectionStatus(for device: BLEDevice) -> some View {
  100. if device.isConnected {
  101. return Text("Connected")
  102. .foregroundColor(.green)
  103. } else if let lastConnected = device.lastConnected {
  104. let date = dateTimeUtils.formattedDate(from: lastConnected)
  105. return Text("Last connection: \(date)")
  106. .foregroundColor(.orange)
  107. } else if let item = bleManager.devices.first(where: { $0.id == device.id }) {
  108. let date = dateTimeUtils.formattedDate(from: item.lastSeen)
  109. return Text("Last seen: \(date)")
  110. .foregroundColor(.orange)
  111. } else {
  112. return Text("Not found")
  113. .foregroundColor(.red)
  114. }
  115. }
  116. }