Merge remote-tracking branch 'refs/remotes/origin/main'

sync_v2
Raz 7 months ago
commit 0db09bc475
  1. 29
      PadelClub/Data/DataStore.swift
  2. 29
      PadelClub/Data/Tournament.swift
  3. 23
      PadelClub/Data/TournamentStore.swift
  4. 7
      PadelClub/Utils/Patcher.swift
  5. 2
      PadelClub/Views/Navigation/Agenda/EventListView.swift
  6. 5
      PadelClub/Views/Navigation/Toolbox/DebugSettingsView.swift
  7. 106
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift
  8. 20
      PadelClub/Views/Tournament/Subscription/Guard.swift
  9. 2
      PadelClub/Views/Tournament/Subscription/Purchase.swift

@ -15,31 +15,28 @@ class DataStore: ObservableObject {
@Published var user: CustomUser = CustomUser.placeHolder() {
didSet {
let loggedUser = StoreCenter.main.userId != nil
StoreCenter.main.collectionsCanSynchronize = loggedUser
let loggedUser = StoreCenter.main.isAuthenticated
if loggedUser {
if self.user.id != self.userStorage.item()?.id {
self.userStorage.setItemNoSync(self.user)
if StoreCenter.main.collectionsCanSynchronize {
StoreCenter.main.initialSynchronization()
StoreCenter.main.initialSynchronization(clear: false)
self._fixMissingClubCreatorIfNecessary(self.clubs)
self._fixMissingEventCreatorIfNecessary(self.events)
}
}
} else {
self._temporaryLocalUser.item = self.user
}
}
}
fileprivate(set) var tournaments: StoredCollection<Tournament>
fileprivate(set) var clubs: StoredCollection<Club>
fileprivate(set) var courts: StoredCollection<Court>
fileprivate(set) var events: StoredCollection<Event>
fileprivate(set) var tournaments: SyncedCollection<Tournament>
fileprivate(set) var clubs: SyncedCollection<Club>
fileprivate(set) var courts: SyncedCollection<Court>
fileprivate(set) var events: SyncedCollection<Event>
fileprivate(set) var monthData: StoredCollection<MonthData>
fileprivate(set) var dateIntervals: StoredCollection<DateInterval>
fileprivate(set) var purchases: StoredCollection<Purchase>
fileprivate(set) var dateIntervals: SyncedCollection<DateInterval>
fileprivate(set) var purchases: SyncedCollection<Purchase>
fileprivate var userStorage: StoredSingleton<CustomUser>
@ -127,9 +124,9 @@ class DataStore: ObservableObject {
if let userSingleton: StoredSingleton<CustomUser> = notification.object as? StoredSingleton<CustomUser> {
self.user = userSingleton.item() ?? self._temporaryLocalUser.item ?? CustomUser.placeHolder()
} else if let clubsCollection: StoredCollection<Club> = notification.object as? StoredCollection<Club> {
} else if let clubsCollection: SyncedCollection<Club> = notification.object as? SyncedCollection<Club> {
self._fixMissingClubCreatorIfNecessary(clubsCollection)
} else if let eventsCollection: StoredCollection<Event> = notification.object as? StoredCollection<Event> {
} else if let eventsCollection: SyncedCollection<Event> = notification.object as? SyncedCollection<Event> {
self._fixMissingEventCreatorIfNecessary(eventsCollection)
}
@ -139,7 +136,7 @@ class DataStore: ObservableObject {
}
fileprivate func _fixMissingClubCreatorIfNecessary(_ clubsCollection: StoredCollection<Club>) {
fileprivate func _fixMissingClubCreatorIfNecessary(_ clubsCollection: SyncedCollection<Club>) {
for club in clubsCollection {
if let userId = StoreCenter.main.userId, club.creator == nil {
club.creator = userId
@ -150,7 +147,7 @@ class DataStore: ObservableObject {
}
}
fileprivate func _fixMissingEventCreatorIfNecessary(_ eventsCollection: StoredCollection<Event>) {
fileprivate func _fixMissingEventCreatorIfNecessary(_ eventsCollection: SyncedCollection<Event>) {
for event in eventsCollection {
if let userId = StoreCenter.main.userId, event.creator == nil {
event.creator = userId
@ -224,8 +221,6 @@ class DataStore: ObservableObject {
fileprivate func _localDisconnect() {
StoreCenter.main.collectionsCanSynchronize = false
let tournamendIds: [String] = self.tournaments.map { $0.id }
TournamentLibrary.shared.reset()

@ -2406,17 +2406,24 @@ defer {
func insertOnServer() throws {
// DataStore.shared.tournaments.writeChangeAndInsertOnServer(instance: self)
//
// for teamRegistration in self.tournamentStore?.teamRegistrations {
// teamRegistration.insertOnServer()
// }
// for groupStage in self.tournamentStore?.groupStages {
// groupStage.insertOnServer()
// }
// for round in self.tournamentStore.rounds {
// round.insertOnServer()
// }
DataStore.shared.tournaments.writeChangeAndInsertOnServer(instance: self)
if let teamRegistrations = self.tournamentStore?.teamRegistrations {
for teamRegistration in teamRegistrations {
teamRegistration.insertOnServer()
}
}
if let groupStages = self.tournamentStore?.groupStages {
for groupStage in groupStages {
groupStage.insertOnServer()
}
}
if let rounds = self.tournamentStore?.rounds {
for round in rounds {
round.insertOnServer()
}
}
}

@ -13,15 +13,15 @@ class TournamentStore: ObservableObject {
var store: Store
fileprivate(set) var groupStages: StoredCollection<GroupStage> = StoredCollection.placeholder()
fileprivate(set) var matches: StoredCollection<Match> = StoredCollection.placeholder()
fileprivate(set) var teamRegistrations: StoredCollection<TeamRegistration> = StoredCollection.placeholder()
fileprivate(set) var playerRegistrations: StoredCollection<PlayerRegistration> = StoredCollection.placeholder()
fileprivate(set) var rounds: StoredCollection<Round> = StoredCollection.placeholder()
fileprivate(set) var teamScores: StoredCollection<TeamScore> = StoredCollection.placeholder()
fileprivate(set) var groupStages: SyncedCollection<GroupStage> = SyncedCollection.placeholder()
fileprivate(set) var matches: SyncedCollection<Match> = SyncedCollection.placeholder()
fileprivate(set) var teamRegistrations: SyncedCollection<TeamRegistration> = SyncedCollection.placeholder()
fileprivate(set) var playerRegistrations: SyncedCollection<PlayerRegistration> = SyncedCollection.placeholder()
fileprivate(set) var rounds: SyncedCollection<Round> = SyncedCollection.placeholder()
fileprivate(set) var teamScores: SyncedCollection<TeamScore> = SyncedCollection.placeholder()
fileprivate(set) var matchSchedulers: StoredCollection<MatchScheduler> = StoredCollection.placeholder()
fileprivate(set) var drawLogs: StoredCollection<DrawLog> = StoredCollection.placeholder()
fileprivate(set) var drawLogs: SyncedCollection<DrawLog> = SyncedCollection.placeholder()
// convenience init(tournament: Tournament) {
// let store = StoreCenter.main.store(identifier: tournament.id)
@ -36,15 +36,8 @@ class TournamentStore: ObservableObject {
fileprivate func _initialize() {
var synchronized: Bool = true
let indexed: Bool = true
#if DEBUG
if let sync = PListReader.readBool(plist: "local", key: "synchronized") {
synchronized = sync
}
#endif
self.groupStages = self.store.registerSynchronizedCollection(indexed: indexed)
self.rounds = self.store.registerSynchronizedCollection(indexed: indexed)
self.teamRegistrations = self.store.registerSynchronizedCollection(indexed: indexed)
@ -52,7 +45,7 @@ class TournamentStore: ObservableObject {
self.matches = self.store.registerSynchronizedCollection(indexed: indexed)
self.teamScores = self.store.registerSynchronizedCollection(indexed: indexed)
self.matchSchedulers = self.store.registerCollection(indexed: indexed)
self.drawLogs = self.store.registerCollection(indexed: indexed)
self.drawLogs = self.store.registerSynchronizedCollection(indexed: indexed)
self.store.loadCollectionsFromServerIfNoFile()

@ -54,6 +54,7 @@ enum Patch: String, CaseIterable {
case cleanLogs
case syncUpgrade
case updateTournaments
case cleanPurchaseApiCalls
var id: String {
return "padelclub.app.patch.\(self.rawValue)"
@ -85,6 +86,7 @@ class AutomaticPatcher {
case .cleanLogs: self._cleanLogs()
case .syncUpgrade: self._syncUpgrade()
case .updateTournaments: self._updateTournaments()
case .cleanPurchaseApiCalls: self._cleanPurchaseApiCalls()
}
}
@ -133,4 +135,9 @@ class AutomaticPatcher {
fileprivate static func _updateTournaments() {
DataStore.shared.tournaments.addOrUpdate(contentOfs: DataStore.shared.tournaments)
}
fileprivate static func _cleanPurchaseApiCalls() {
StoreCenter.main.resetApiCalls(type: Purchase.self)
}
}

@ -314,7 +314,7 @@ struct EventListView: View {
TournamentCellView(tournament: tournament)
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name.CollectionDidLoad), perform: { notification in
if let store = notification.object as? StoredCollection<TeamRegistration> {
if let store = notification.object as? SyncedCollection<TeamRegistration> {
if store.storeId == tournament.id {
tournament.lastTeamRefresh = Date()
}

@ -25,7 +25,6 @@ struct DebugSettingsView: View {
LabeledContent("Token", value: self._token)
LabeledContent("Server", value: self._apiURL)
LabeledContent("Synchronized", value: self._synchronized)
LabeledContent("CollectionsCanSynchronize", value: self._canSynchronize)
}
}
}
@ -55,10 +54,6 @@ struct DebugSettingsView: View {
}
}
fileprivate var _canSynchronize: String {
return "\(StoreCenter.main.collectionsCanSynchronize)"
}
fileprivate var _wsPingStatus: String {
return "\(StoreCenter.main.websocketPingStatus)"
}

@ -1048,59 +1048,59 @@ struct InscriptionManagerView: View {
}
}
@ViewBuilder
private func _prioritizeClubMembersButton() -> some View {
@Bindable var tournament = tournament
if let federalClub = tournament.club() {
Menu {
Picker(selection: $tournament.prioritizeClubMembers) {
Text("Oui").tag(true)
Text("Non").tag(false)
} label: {
}
.labelsHidden()
Divider()
NavigationLink {
ClubsView() { club in
if let event = tournament.eventObject() {
event.club = club.id
do {
try dataStore.events.addOrUpdate(instance: event)
} catch {
Logger.error(error)
}
}
_save()
}
} label: {
Text("Changer de club")
}
} label: {
Text("Membres prioritaires")
Text(federalClub.acronym)
}
Divider()
} else {
NavigationLink {
ClubsView() { club in
if let event = tournament.eventObject() {
event.club = club.id
do {
try dataStore.events.addOrUpdate(instance: event)
} catch {
Logger.error(error)
}
}
_save()
}
} label: {
Text("Identifier le club")
}
Divider()
}
}
// @ViewBuilder
// private func _prioritizeClubMembersButton() -> some View {
// @Bindable var tournament = tournament
// if let federalClub = tournament.club() {
// Menu {
// Picker(selection: $tournament.prioritizeClubMembers) {
// Text("Oui").tag(true)
// Text("Non").tag(false)
// } label: {
//
// }
// .labelsHidden()
//
// Divider()
// NavigationLink {
// ClubsView() { club in
// if let event = tournament.eventObject() {
// event.club = club.id
// do {
// try dataStore.events.addOrUpdate(instance: event)
// } catch {
// Logger.error(error)
// }
// }
// _save()
// }
// } label: {
// Text("Changer de club")
// }
// } label: {
// Text("Membres prioritaires")
// Text(federalClub.acronym)
// }
// Divider()
// } else {
// NavigationLink {
// ClubsView() { club in
// if let event = tournament.eventObject() {
// event.club = club.id
// do {
// try dataStore.events.addOrUpdate(instance: event)
// } catch {
// Logger.error(error)
// }
// }
// _save()
// }
// } label: {
// Text("Identifier le club")
// }
// Divider()
// }
// }
private func _teamFooterView(_ team: TeamRegistration) -> some View {
HStack {

@ -187,18 +187,18 @@ import LeStorage
}
var currentPlan: StoreItem? {
#if DEBUG
return .monthlyUnlimited
#elseif TESTFLIGHT
return .monthlyUnlimited
#elseif PRODTEST
return .monthlyUnlimited
#else
// #if DEBUG
// return .monthlyUnlimited
// #elseif TESTFLIGHT
// return .monthlyUnlimited
// #elseif PRODTEST
// return .monthlyUnlimited
// #else
if let currentBestPurchase = self.currentBestPurchase, let plan = StoreItem(rawValue: currentBestPurchase.productId) {
return plan
}
return nil
#endif
// #endif
}
func userFilteredPurchases() -> [StoreKit.Transaction] {
@ -316,8 +316,8 @@ fileprivate extension StoreKit.Transaction {
throw StoreError.missingUserId
}
return Purchase(user: userId,
transactionId: self.originalID,
return Purchase(transactionId: self.originalID,
user: userId,
purchaseDate: self.purchaseDate,
productId: self.productID,
quantity: self.purchasedQuantity,

@ -24,7 +24,7 @@ class Purchase: BasePurchase {
// var revocationDate: Date? = nil
// var expirationDate: Date? = nil
init(user: String, transactionId: UInt64, purchaseDate: Date, productId: String, quantity: Int? = nil, revocationDate: Date? = nil, expirationDate: Date? = nil) {
init(transactionId: UInt64, user: String, purchaseDate: Date, productId: String, quantity: Int? = nil, revocationDate: Date? = nil, expirationDate: Date? = nil) {
super.init(id: transactionId, user: user, purchaseDate: purchaseDate, productId: productId, quantity: quantity, revocationDate: revocationDate, expirationDate: expirationDate)
// self.id = transactionId

Loading…
Cancel
Save