PaywallConfigService.swift 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import Foundation
  2. @MainActor
  3. final class PaywallConfigService {
  4. static let shared = PaywallConfigService()
  5. private static let remoteConfigURL = URL(
  6. string: "https://git.mqldevelopment.com/ahtasham.shahzad/smart_printer/-/raw/main/smart_printer/paywall.json"
  7. )!
  8. private(set) var config: PaywallConfig
  9. private var hasStarted = false
  10. private init() {
  11. config = PaywallConfig.loadBundled()
  12. }
  13. func start() {
  14. guard !hasStarted else { return }
  15. hasStarted = true
  16. Task { await refreshFromRemote() }
  17. }
  18. func refreshFromRemote() async {
  19. var request = URLRequest(url: Self.remoteConfigURL)
  20. request.cachePolicy = .reloadIgnoringLocalCacheData
  21. request.timeoutInterval = 15
  22. do {
  23. let (data, response) = try await URLSession.shared.data(for: request)
  24. guard let http = response as? HTTPURLResponse, (200 ... 299).contains(http.statusCode) else {
  25. return
  26. }
  27. let remoteConfig = try JSONDecoder().decode(PaywallConfig.self, from: data)
  28. apply(remoteConfig)
  29. } catch {
  30. NSLog("Failed to refresh paywall config: \(error.localizedDescription)")
  31. }
  32. }
  33. private func apply(_ remoteConfig: PaywallConfig) {
  34. let bundledConfig = PaywallConfig.loadBundled()
  35. let mergedConfig = bundledConfig.mergingMarketing(from: remoteConfig)
  36. guard mergedConfig != config else { return }
  37. config = mergedConfig
  38. NotificationCenter.default.post(name: .paywallConfigDidUpdate, object: nil)
  39. }
  40. }
  41. extension PaywallConfig: Equatable {
  42. static func == (lhs: PaywallConfig, rhs: PaywallConfig) -> Bool {
  43. guard let lhsData = try? JSONEncoder().encode(lhs),
  44. let rhsData = try? JSONEncoder().encode(rhs) else {
  45. return false
  46. }
  47. return lhsData == rhsData
  48. }
  49. }