NightscoutConfigStateModel.swift 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import Combine
  2. import SwiftDate
  3. import SwiftUI
  4. extension NightscoutConfig {
  5. final class StateModel: BaseStateModel<Provider> {
  6. @Injected() private var keychain: Keychain!
  7. @Injected() private var nightscoutManager: NightscoutManager!
  8. @Injected() private var glucoseStorage: GlucoseStorage!
  9. @Injected() private var healthKitManager: HealthKitManager!
  10. @Published var url = ""
  11. @Published var secret = ""
  12. @Published var message = ""
  13. @Published var connecting = false
  14. @Published var backfilling = false
  15. @Published var isUploadEnabled = false
  16. @Published var useLocalSource = false
  17. @Published var localPort: Decimal = 0
  18. override func subscribe() {
  19. url = keychain.getValue(String.self, forKey: Config.urlKey) ?? ""
  20. secret = keychain.getValue(String.self, forKey: Config.secretKey) ?? ""
  21. subscribeSetting(\.isUploadEnabled, on: $isUploadEnabled) { isUploadEnabled = $0 }
  22. subscribeSetting(\.useLocalGlucoseSource, on: $useLocalSource) { useLocalSource = $0 }
  23. subscribeSetting(\.localGlucosePort, on: $localPort.map(Int.init)) { localPort = Decimal($0) }
  24. }
  25. func connect() {
  26. guard let url = URL(string: url) else {
  27. message = "Invalid URL"
  28. return
  29. }
  30. connecting = true
  31. message = ""
  32. provider.checkConnection(url: url, secret: secret.isEmpty ? nil : secret)
  33. .receive(on: DispatchQueue.main)
  34. .sink { completion in
  35. switch completion {
  36. case .finished: break
  37. case let .failure(error):
  38. self.message = "Error: \(error.localizedDescription)"
  39. }
  40. self.connecting = false
  41. } receiveValue: {
  42. self.message = "Connected!"
  43. self.keychain.setValue(self.url, forKey: Config.urlKey)
  44. self.keychain.setValue(self.secret, forKey: Config.secretKey)
  45. }
  46. .store(in: &lifetime)
  47. }
  48. func backfillGlucose() {
  49. backfilling = true
  50. nightscoutManager.fetchGlucose(since: Date().addingTimeInterval(-1.days.timeInterval))
  51. .sink { [weak self] glucose in
  52. guard let self = self else { return }
  53. DispatchQueue.main.async {
  54. self.backfilling = false
  55. }
  56. guard glucose.isNotEmpty else { return }
  57. self.glucoseStorage.storeGlucose(glucose)
  58. self.healthKitManager.saveIfNeeded(bloodGlucoses: glucose)
  59. }
  60. .store(in: &lifetime)
  61. }
  62. func delete() {
  63. keychain.removeObject(forKey: Config.urlKey)
  64. keychain.removeObject(forKey: Config.secretKey)
  65. url = ""
  66. secret = ""
  67. }
  68. }
  69. }