TokiTrainer/Toki Trainer/Models/TransactionObserver.swift

98 lines
2.8 KiB
Swift

//
// TransactionObserver.swift
// Toki Trainer
//
// Created by Madeline Pace on 12/18/23.
//
import CoreData
import StoreKit
@MainActor
final class TransactionObserver: ObservableObject {
var updates: Task<Void, Never>? = 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<Void, Never> {
Task(priority: .background) {
for await verificationResult in Transaction.updates {
await self.handle(updatedTransaction: verificationResult)
}
}
}
private func handle(updatedTransaction verificationResult: VerificationResult<Transaction>) 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
}
}
}