// // TransactionObserver.swift // Toki Trainer // // Created by Madeline Pace on 12/18/23. // import CoreData import StoreKit @MainActor final class TransactionObserver: ObservableObject { var updates: Task? = nil @Published var donationHearts: Int = 0 @Published var hasDonated = false init() { updates = newTransactionListenerTask() donationHearts = UserDefaults.standard.integer(forKey: K.UserDefaults.donationHearts) hasDonated = UserDefaults.standard.bool(forKey: K.UserDefaults.hasDonated) } deinit { updates?.cancel() } func addDonationHearts(_ amount: Int) { if hasDonated == false { hasDonated = true UserDefaults.standard.set(hasDonated, forKey: K.UserDefaults.hasDonated) } DispatchQueue.main.async { self.donationHearts += amount } UserDefaults.standard.set(donationHearts, forKey: K.UserDefaults.donationHearts) } private func newTransactionListenerTask() -> Task { Task(priority: .background) { for await verificationResult in Transaction.updates { await self.handle(updatedTransaction: verificationResult) } } } private func handle(updatedTransaction verificationResult: VerificationResult) async { guard case .verified(let transaction) = verificationResult else { return } switch transaction.productType { case Product.ProductType.consumable: processConsumable(transaction.productID) case Product.ProductType.nonRenewable, Product.ProductType.autoRenewable: processSubscription(transaction.productID) default: return } print("Finishing transaction") await transaction.finish() } func processConsumable(_ productID: String) { print("Consumable ID: \(productID)") switch productID { case K.ConsumableTransactions.TierOne: self.addDonationHearts(100) case K.ConsumableTransactions.TierTwo: self.addDonationHearts(500) case K.ConsumableTransactions.TierThree: self.addDonationHearts(1000) case K.ConsumableTransactions.TierFour: self.addDonationHearts(2000) default: return } } func processSubscription(_ productID: String) { print("Subscription ID: \(productID)") switch productID { case K.MonthlyTransactions.TierOne: self.addDonationHearts(100) case K.MonthlyTransactions.TierTwo: self.addDonationHearts(500) case K.MonthlyTransactions.TierThree: self.addDonationHearts(1000) default: return } } }