|
|
|
|
@ -10,7 +10,7 @@ import StoreKit |
|
|
|
|
import LeStorage |
|
|
|
|
|
|
|
|
|
@available(iOS 15, *) |
|
|
|
|
@objc class Guard : NSObject { |
|
|
|
|
@objc class Guard: NSObject { |
|
|
|
|
|
|
|
|
|
static var main: Guard = Guard() |
|
|
|
|
|
|
|
|
|
@ -20,17 +20,18 @@ import LeStorage |
|
|
|
|
|
|
|
|
|
var updateListenerTask: Task<Void, Error>? = nil |
|
|
|
|
|
|
|
|
|
fileprivate var _userPurchases: [Purchase] = [] |
|
|
|
|
fileprivate var _purchases: StoredCollection<Purchase> |
|
|
|
|
|
|
|
|
|
override init() { |
|
|
|
|
|
|
|
|
|
self._purchases = Store.main.registerCollection(synchronized: true, inMemory: true) |
|
|
|
|
|
|
|
|
|
super.init() |
|
|
|
|
|
|
|
|
|
self.updateListenerTask = self.listenForTransactions() |
|
|
|
|
|
|
|
|
|
Task { |
|
|
|
|
do { |
|
|
|
|
try await self._retrievePrivateServerPurchases() |
|
|
|
|
try await self.refreshPurchasedAppleProducts() |
|
|
|
|
} catch { |
|
|
|
|
Logger.error(error) |
|
|
|
|
@ -38,23 +39,6 @@ import LeStorage |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _uploadTransaction(_ transaction: StoreKit.Transaction) async throws { |
|
|
|
|
|
|
|
|
|
let service = try Store.main.service() |
|
|
|
|
var purchase = try transaction.purchase() |
|
|
|
|
|
|
|
|
|
// if let apiCall = try self._callForInstance(purchase, method: Method.post) { |
|
|
|
|
// |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _retrievePrivateServerPurchases() async throws { |
|
|
|
|
let service = try Store.main.service() |
|
|
|
|
self._userPurchases = try await service.get() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func refreshPurchasedAppleProducts() async throws { |
|
|
|
|
|
|
|
|
|
// Iterate through the user's purchased products. |
|
|
|
|
@ -105,8 +89,10 @@ import LeStorage |
|
|
|
|
if transaction.revocationDate == nil { |
|
|
|
|
// If the App Store has not revoked the transaction, add it to the list of `purchasedIdentifiers`. |
|
|
|
|
purchasedTransactions.insert(transaction) |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
try await self._uploadTransaction(transaction) |
|
|
|
|
let purchase: Purchase = transaction.purchase() |
|
|
|
|
try self._purchases.addOrUpdate(instance: purchase) |
|
|
|
|
} catch { |
|
|
|
|
Logger.error(error) |
|
|
|
|
} |
|
|
|
|
@ -146,7 +132,7 @@ import LeStorage |
|
|
|
|
|
|
|
|
|
fileprivate func _userFilteredPurchases() -> [StoreKit.Transaction] { |
|
|
|
|
return self.purchasedTransactions.filter { transaction in |
|
|
|
|
return self._userPurchases.contains(where: { $0.identifier == transaction.id } ) |
|
|
|
|
return self._purchases.contains(where: { $0.identifier == transaction.id } ) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -171,42 +157,61 @@ import LeStorage |
|
|
|
|
return units.reduce(0) { $0 + $1.purchasedQuantity } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func canAddTournament() -> Bool { |
|
|
|
|
if self.currentPlan == .monthlyUnlimited { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
let tournamentCount = DataStore.shared.tournaments.count |
|
|
|
|
let tournamentCreditCount = self._purchasedTournamentCount() |
|
|
|
|
return tournamentCreditCount > tournamentCount |
|
|
|
|
} |
|
|
|
|
// func canAddTournament() -> Bool { |
|
|
|
|
// switch self.currentPlan { |
|
|
|
|
// case .monthlyUnlimited: return true |
|
|
|
|
// case .fivePerMonth: |
|
|
|
|
// if let date = self.currentBestPlan?.originalPurchaseDate { |
|
|
|
|
// let tournaments = DataStore.shared.tournaments.filter { $0.creationDate > date } |
|
|
|
|
// return tournaments.count < StoreItem.five |
|
|
|
|
// } else { |
|
|
|
|
// Logger.error(StoreManagerError.missingPlan) |
|
|
|
|
// return false |
|
|
|
|
// } |
|
|
|
|
// case .unit: |
|
|
|
|
// let tournamentCount = DataStore.shared.tournaments.count |
|
|
|
|
// let tournamentCreditCount = self._purchasedTournamentCount() |
|
|
|
|
// return tournamentCreditCount > tournamentCount |
|
|
|
|
// case nil: |
|
|
|
|
// return DataStore.shared.tournaments.count == 0 |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
func paymentForNewTournament() -> Tournament.TournamentPayment? { |
|
|
|
|
if self.currentPlan == .monthlyUnlimited { |
|
|
|
|
|
|
|
|
|
switch self.currentPlan { |
|
|
|
|
case .monthlyUnlimited: |
|
|
|
|
return Tournament.TournamentPayment.unlimited |
|
|
|
|
} else if self.currentPlan == .fivePerMonth, let purchaseDate = self.currentBestPlan?.originalPurchaseDate { |
|
|
|
|
case .fivePerMonth: |
|
|
|
|
if let purchaseDate = self.currentBestPlan?.originalPurchaseDate { |
|
|
|
|
let tournaments = DataStore.shared.tournaments.filter { $0.creationDate > purchaseDate } |
|
|
|
|
if tournaments.count < 5 { |
|
|
|
|
if tournaments.count < StoreItem.five { |
|
|
|
|
return Tournament.TournamentPayment.subscriptionUnit |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
default: |
|
|
|
|
let subscriptionPayed = DataStore.shared.tournaments.filter { $0.payment.isSubscription } |
|
|
|
|
|
|
|
|
|
let tournamentCount = DataStore.shared.tournaments.count |
|
|
|
|
if tournamentCount == 0 { |
|
|
|
|
let unitlyPayed = DataStore.shared.tournaments.count - subscriptionPayed.count |
|
|
|
|
if unitlyPayed == 0 { |
|
|
|
|
return Tournament.TournamentPayment.free |
|
|
|
|
} |
|
|
|
|
let tournamentCreditCount = self._purchasedTournamentCount() |
|
|
|
|
if tournamentCreditCount > tournamentCount { |
|
|
|
|
if tournamentCreditCount > unitlyPayed { |
|
|
|
|
return Tournament.TournamentPayment.unit |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate extension StoreKit.Transaction { |
|
|
|
|
|
|
|
|
|
func purchase() throws -> Purchase { |
|
|
|
|
let userId = try Store.main.currentUserUUID().uuidString |
|
|
|
|
func purchase() -> Purchase { |
|
|
|
|
let userId = Store.main.currentUserUUID().uuidString |
|
|
|
|
return Purchase(user: userId, |
|
|
|
|
identifier: self.id, |
|
|
|
|
purchaseDate: self.purchaseDate, |
|
|
|
|
|