PaywallConfigService.swift 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import Combine
  2. import Foundation
  3. @MainActor
  4. final class PaywallConfigService: ObservableObject {
  5. static let shared = PaywallConfigService()
  6. private static let remoteConfigURL = URL(
  7. string: "https://git.mqldevelopment.com/MQL-Development/app_for_reddit/-/raw/main/App%20AI%20for%20Reddit/paywall.json"
  8. )!
  9. @Published private(set) var config: PaywallConfig
  10. private var hasStarted = false
  11. private init() {
  12. config = PaywallConfig.loadBundled()
  13. }
  14. func start() {
  15. guard !hasStarted else { return }
  16. hasStarted = true
  17. Task { await refreshFromRemote() }
  18. }
  19. func refreshFromRemote() async {
  20. var request = URLRequest(url: Self.remoteConfigURL)
  21. request.cachePolicy = .reloadIgnoringLocalCacheData
  22. request.timeoutInterval = 15
  23. do {
  24. let (data, response) = try await URLSession.shared.data(for: request)
  25. guard let http = response as? HTTPURLResponse, (200 ... 299).contains(http.statusCode) else {
  26. return
  27. }
  28. let remoteConfig = try JSONDecoder().decode(PaywallConfig.self, from: data)
  29. apply(remoteConfig)
  30. } catch {
  31. #if DEBUG
  32. print("Failed to refresh paywall config: \(error.localizedDescription)")
  33. #endif
  34. }
  35. }
  36. private func apply(_ remoteConfig: PaywallConfig) {
  37. let bundledConfig = PaywallConfig.loadBundled()
  38. let mergedConfig = bundledConfig.mergingMarketing(from: remoteConfig)
  39. guard mergedConfig != config else { return }
  40. config = mergedConfig
  41. NotificationCenter.default.post(name: .paywallConfigDidUpdate, object: nil)
  42. }
  43. }