Live Activities, nudging, unit tests
This commit is contained in:
@@ -29,12 +29,60 @@ enum PurchaseResult: Equatable {
|
||||
"donateanthology"
|
||||
]
|
||||
|
||||
// MARK: - Nudge / Supporter tracking keys
|
||||
private static let firstLaunchKey = "ma_firstLaunchDate"
|
||||
private static let lastKeyDateKey = "ma_lastNudgeOrPurchaseDate"
|
||||
private static let hasEverSupportedKey = "ma_hasEverSupported"
|
||||
private let defaults = UserDefaults.standard
|
||||
|
||||
private var updateListenerTask: Task<Void, Never>?
|
||||
|
||||
init() {
|
||||
// Persist first-launch date on very first run
|
||||
_ = firstLaunchDate
|
||||
updateListenerTask = listenForTransactions()
|
||||
}
|
||||
|
||||
// MARK: - Supporter state
|
||||
|
||||
/// True once the user has completed at least one donation.
|
||||
var hasEverSupported: Bool {
|
||||
defaults.bool(forKey: Self.hasEverSupportedKey)
|
||||
}
|
||||
|
||||
// MARK: - Nudge logic
|
||||
|
||||
/// The date the app was first launched (written once, then read-only).
|
||||
var firstLaunchDate: Date {
|
||||
if let date = defaults.object(forKey: Self.firstLaunchKey) as? Date { return date }
|
||||
let now = Date()
|
||||
defaults.set(now, forKey: Self.firstLaunchKey)
|
||||
return now
|
||||
}
|
||||
|
||||
/// True when the nudge sheet should be presented.
|
||||
/// Rules:
|
||||
/// - First show: ≥ 3 days after install and never shown/purchased before.
|
||||
/// - Repeat: ≥ 6 months since last nudge dismissal OR last purchase.
|
||||
var shouldShowNudge: Bool {
|
||||
let threeDays: TimeInterval = 3 * 24 * 3600
|
||||
let sixMonths: TimeInterval = 6 * 30 * 24 * 3600
|
||||
guard Date().timeIntervalSince(firstLaunchDate) >= threeDays else { return false }
|
||||
guard let last = defaults.object(forKey: Self.lastKeyDateKey) as? Date else { return true }
|
||||
return Date().timeIntervalSince(last) >= sixMonths
|
||||
}
|
||||
|
||||
/// Call when the nudge sheet is dismissed (regardless of purchase outcome).
|
||||
func recordNudgeShown() {
|
||||
defaults.set(Date(), forKey: Self.lastKeyDateKey)
|
||||
}
|
||||
|
||||
/// Records a successful purchase: sets supporter flag and resets the nudge clock.
|
||||
private func recordPurchase() {
|
||||
defaults.set(true, forKey: Self.hasEverSupportedKey)
|
||||
defaults.set(Date(), forKey: Self.lastKeyDateKey)
|
||||
}
|
||||
|
||||
func loadProducts() async {
|
||||
loadError = nil
|
||||
do {
|
||||
@@ -60,6 +108,7 @@ enum PurchaseResult: Equatable {
|
||||
case .success(let verification):
|
||||
let transaction = try checkVerified(verification)
|
||||
await transaction.finish()
|
||||
recordPurchase()
|
||||
purchaseResult = .success(product)
|
||||
case .userCancelled:
|
||||
purchaseResult = .cancelled
|
||||
|
||||
Reference in New Issue
Block a user