multistore
Laurent 2 years ago
parent 1356ecf71d
commit a25dadf1b8
  1. 10
      PadelClub/Data/Tournament.swift
  2. 97
      PadelClub/Views/Subscription/Guard.swift
  3. 2
      PadelClub/Views/Subscription/StoreItem.swift
  4. 9
      PadelClub/Views/Subscription/StoreManager.swift

@ -84,6 +84,16 @@ class Tournament : ModelObject, Storable {
enum TournamentPayment: Int {
case free, unit, subscriptionUnit, unlimited
var isSubscription: Bool {
switch self {
case .subscriptionUnit, .unlimited:
return true
default:
return false
}
}
}
enum State {

@ -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 {
let tournaments = DataStore.shared.tournaments.filter { $0.creationDate > purchaseDate }
if tournaments.count < 5 {
return Tournament.TournamentPayment.subscriptionUnit
case .fivePerMonth:
if let purchaseDate = self.currentBestPlan?.originalPurchaseDate {
let tournaments = DataStore.shared.tournaments.filter { $0.creationDate > purchaseDate }
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 {
return Tournament.TournamentPayment.free
}
let tournamentCreditCount = self._purchasedTournamentCount()
if tournamentCreditCount > tournamentCount {
return Tournament.TournamentPayment.unit
let unitlyPayed = DataStore.shared.tournaments.count - subscriptionPayed.count
if unitlyPayed == 0 {
return Tournament.TournamentPayment.free
}
let tournamentCreditCount = self._purchasedTournamentCount()
if tournamentCreditCount > unitlyPayed {
return Tournament.TournamentPayment.unit
}
return nil
}
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,

@ -12,6 +12,8 @@ enum StoreItem: String, Identifiable, CaseIterable {
case fivePerMonth = "app.padelclub.tournament.subscription.five.per.month"
case unit = "app.padelclub.tournament.unit"
static let five: Int = 5
var id: String { return self.rawValue }
// var title: String { return "Tournoi illimités" }

@ -11,6 +11,7 @@ import LeStorage
public enum StoreManagerError: Error {
case failedVerification
case missingPlan
}
protocol StoreDelegate {
@ -25,8 +26,6 @@ extension Notification.Name {
@available(iOS 15, *)
class StoreManager {
// @Published private(set) var products: [Product] = []
@Published private(set) var purchasedTransactions = Set<StoreKit.Transaction>()
var delegate: StoreDelegate? = nil
@ -48,10 +47,6 @@ class StoreManager {
self.updateListenerTask?.cancel()
}
// func indexOf(identifier: String) -> Int? {
// return self.products.map { $0.id }.firstIndex(of: identifier)
// }
@MainActor
func requestProducts() async {
do {
@ -95,7 +90,7 @@ class StoreManager {
Logger.log("Store purchase started...")
var options: Set<Product.PurchaseOption> = []
let uuid: UUID = try Store.main.currentUserUUID()
let uuid: UUID = Store.main.currentUserUUID()
let tokenOption = Product.PurchaseOption.appAccountToken(uuid)
options.insert(tokenOption)

Loading…
Cancel
Save