PaywallConfigService.swift 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  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. #if DEBUG
  17. Task { await refreshFromRemote() }
  18. #endif
  19. }
  20. func refreshFromRemote() async {
  21. var request = URLRequest(url: Self.remoteConfigURL)
  22. request.cachePolicy = .reloadIgnoringLocalCacheData
  23. request.timeoutInterval = 15
  24. do {
  25. let (data, response) = try await URLSession.shared.data(for: request)
  26. guard let http = response as? HTTPURLResponse, (200 ... 299).contains(http.statusCode) else {
  27. return
  28. }
  29. let remoteConfig = try JSONDecoder().decode(PaywallConfig.self, from: data)
  30. apply(remoteConfig)
  31. } catch {
  32. NSLog("Failed to refresh paywall config: \(error.localizedDescription)")
  33. }
  34. }
  35. private func apply(_ remoteConfig: PaywallConfig) {
  36. let bundledConfig = PaywallConfig.loadBundled()
  37. let mergedConfig = bundledConfig.mergingMarketing(from: remoteConfig)
  38. guard mergedConfig != config else { return }
  39. config = mergedConfig
  40. NotificationCenter.default.post(name: .paywallConfigDidUpdate, object: nil)
  41. }
  42. }
  43. extension PaywallConfig: Equatable {
  44. static func == (lhs: PaywallConfig, rhs: PaywallConfig) -> Bool {
  45. guard let lhsData = try? JSONEncoder().encode(lhs),
  46. let rhsData = try? JSONEncoder().encode(rhs) else {
  47. return false
  48. }
  49. return lhsData == rhsData
  50. }
  51. }