import StoreKit import UIKit final class ReviewPromptService { static let shared = ReviewPromptService() private let lastPromptKey = "reviewPromptLastDate" private let checkInCountKey = "reviewPromptCheckinCount" private let minCheckInsBetweenPrompts = 3 private let minDaysBetweenPrompts = 90 private let userDefaults: UserDefaults private let dateProvider: () -> Date private let reviewRequestHandler: () -> Void private init() { userDefaults = .standard dateProvider = Date.init reviewRequestHandler = ReviewPromptService.defaultReviewRequestHandler } init( userDefaults: UserDefaults, dateProvider: @escaping () -> Date, reviewRequestHandler: @escaping () -> Void ) { self.userDefaults = userDefaults self.dateProvider = dateProvider self.reviewRequestHandler = reviewRequestHandler } func recordMonthlyCheckInCompleted() { let currentCount = userDefaults.integer(forKey: checkInCountKey) userDefaults.set(currentCount + 1, forKey: checkInCountKey) requestReviewIfEligible() } private func requestReviewIfEligible() { let now = dateProvider() if let lastPrompt = userDefaults.object(forKey: lastPromptKey) as? Date { let daysSince = now.timeIntervalSince(lastPrompt) / 86_400 if daysSince < Double(minDaysBetweenPrompts) { return } } let count = userDefaults.integer(forKey: checkInCountKey) guard count >= minCheckInsBetweenPrompts else { return } requestReview() } private func requestReview() { reviewRequestHandler() userDefaults.set(dateProvider(), forKey: lastPromptKey) userDefaults.set(0, forKey: checkInCountKey) } private static func defaultReviewRequestHandler() { guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return } if #available(iOS 18.0, *) { AppStore.requestReview(in: scene) } else { SKStoreReviewController.requestReview(in: scene) } } }