import Combine import Foundation @MainActor final class PaywallConfigService: ObservableObject { static let shared = PaywallConfigService() private static let remoteConfigURL = URL( string: "https://git.mqldevelopment.com/MQL-Development/app_for_reddit/-/raw/main/App%20AI%20for%20Reddit/paywall.json" )! @Published private(set) var config: PaywallConfig private var hasStarted = false private init() { config = PaywallConfig.loadBundled() } func start() { guard !hasStarted else { return } hasStarted = true Task { await refreshFromRemote() } } func refreshFromRemote() async { var request = URLRequest(url: Self.remoteConfigURL) request.cachePolicy = .reloadIgnoringLocalCacheData request.timeoutInterval = 15 do { let (data, response) = try await URLSession.shared.data(for: request) guard let http = response as? HTTPURLResponse, (200 ... 299).contains(http.statusCode) else { return } let remoteConfig = try JSONDecoder().decode(PaywallConfig.self, from: data) apply(remoteConfig) } catch { #if DEBUG print("Failed to refresh paywall config: \(error.localizedDescription)") #endif } } private func apply(_ remoteConfig: PaywallConfig) { let bundledConfig = PaywallConfig.loadBundled() let mergedConfig = bundledConfig.mergingMarketing(from: remoteConfig) guard mergedConfig != config else { return } config = mergedConfig NotificationCenter.default.post(name: .paywallConfigDidUpdate, object: nil) } }