From 186a9d6e35b17fd50fafabd099515c01d1dd47de Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 24 Mar 2025 15:31:00 +0100 Subject: [PATCH 1/9] update readme --- PadelClub/Data/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PadelClub/Data/README.md b/PadelClub/Data/README.md index c61a0b2..c2a71e8 100644 --- a/PadelClub/Data/README.md +++ b/PadelClub/Data/README.md @@ -29,5 +29,6 @@ Dans Django: - L'ajouter aussi dans admin.py si nécéssaire - Faire le *makemigrations* + *migrate* +Note: Les nouvelles classes de model doivent étendre BaseModel ou SideStoreModel Enfin, revenir dans Xcode, ouvrir ServerDataTests et lancer le test mis à jour From f77cd9d2c964247c9846b239ea94e7897f1f20b9 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 25 Mar 2025 11:59:48 +0100 Subject: [PATCH 2/9] update readme --- PadelClub/Data/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PadelClub/Data/README.md b/PadelClub/Data/README.md index c2a71e8..d72ad3a 100644 --- a/PadelClub/Data/README.md +++ b/PadelClub/Data/README.md @@ -3,6 +3,7 @@ Dans Swift: - Dans Data > Gen > créer un nouveau fichier json pour la classe - Le paramètre "foreignKey" permet de générer une méthode qui récupère l'objet parent. Ajouter une étoile permet d'indiquer que l'on cherche l'objet dans le Store de l'objet et non le Store.main. - Pour générer les fichiers, on se place dans le répertoire de generator.py et on lance la commande : python generator.py -i . -o . +- il faut avoir inflect: pip install inflect Dans Django: - Les modèles de base doivent étendre BaseModel From f892a0585117ebb65708eed454a1cb90b653ae95 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 25 Mar 2025 15:19:42 +0100 Subject: [PATCH 3/9] Improve download view --- PadelClub/PadelClubApp.swift | 43 +++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/PadelClub/PadelClubApp.swift b/PadelClub/PadelClubApp.swift index aed4326..8ac2503 100644 --- a/PadelClub/PadelClubApp.swift +++ b/PadelClub/PadelClubApp.swift @@ -19,7 +19,7 @@ struct PadelClubApp: App { @State private var importObserverViewModel = ImportObserver() @Environment(\.horizontalSizeClass) var horizontalSizeClass - @State var blockApp = false + @State var requiredVersion: String? = nil @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @@ -65,8 +65,8 @@ struct PadelClubApp: App { var body: some Scene { WindowGroup { - if self.blockApp { - DownloadNewVersionView() + if let requiredVersion { + DownloadNewVersionView(version: requiredVersion) } else { MainView() .environment(\.horizontalSizeClass, .compact) @@ -125,7 +125,9 @@ struct PadelClubApp: App { Logger.log(">>> REQUIRED VERSION = \(requiredVersion)") if let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { await MainActor.run { - self.blockApp = VersionComparator.compare(cleanedRequired, currentVersion) == 1 + if VersionComparator.compare(cleanedRequired, currentVersion) == 1 { + self.requiredVersion = cleanedRequired + } } } } @@ -211,22 +213,40 @@ struct PadelClubApp: App { struct DownloadNewVersionView: View { + var version: String + var body: some View { VStack { // AngledStripesBackground() Spacer() - Text("Veuillez télécharger la nouvelle version de Padel Club pour continuer à vous servir de l'app !") - .padding(32.0) - .background(.logoYellow) - .clipShape(.buttonBorder) + VStack(spacing: 20.0) { + Text("Veuillez télécharger la nouvelle version de Padel Club pour continuer à vous servir de l'app !") + .fontWeight(.semibold) + .foregroundStyle(.white) + .padding() + .background(.logoRed) + .clipShape(.buttonBorder) +// .padding(32.0) + + VStack(alignment: .center, spacing: 0.0 + ) { + Text("Version \(self.version)") + .fontWeight(.bold) + + Image(systemName: "square.and.arrow.down").font(.title) + }.padding().background(.logoYellow) + .clipShape(.buttonBorder) + + }.frame(maxWidth: .infinity) .foregroundStyle(.logoBackground) .fontWeight(.medium) .multilineTextAlignment(.center) - .padding(.horizontal, 64.0) + .padding(.horizontal, 36.0) Image("logo").padding(.vertical, 50.0) Spacer() - }.background(.logoBackground) + } + .background(.logoBackground) .onTapGesture { UIApplication.shared.open(URLs.appStore.url) } @@ -235,3 +255,6 @@ struct DownloadNewVersionView: View { } +#Preview { + DownloadNewVersionView(version: "1.2") +} From 5708c9a9d8cc0b3ce6ca58b67a93b2f0ea8aa4ad Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 25 Mar 2025 16:13:31 +0100 Subject: [PATCH 4/9] disconnect users + remove websocket connection --- PadelClub/Data/DataStore.swift | 2 +- PadelClub/PadelClubApp.swift | 14 ++++++++++++ PadelClub/Utils/Patcher.swift | 40 +++++++++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/PadelClub/Data/DataStore.swift b/PadelClub/Data/DataStore.swift index d98db75..164d6c9 100644 --- a/PadelClub/Data/DataStore.swift +++ b/PadelClub/Data/DataStore.swift @@ -134,7 +134,7 @@ class DataStore: ObservableObject { } if Store.main.fileCollectionsAllLoaded() { - Patcher.applyAllWhenApplicable() + AutomaticPatcher.applyAllWhenApplicable() } } diff --git a/PadelClub/PadelClubApp.swift b/PadelClub/PadelClubApp.swift index 8ac2503..5033f08 100644 --- a/PadelClub/PadelClubApp.swift +++ b/PadelClub/PadelClubApp.swift @@ -17,6 +17,7 @@ struct PadelClubApp: App { @StateObject var dataStore = DataStore.shared @State private var registrationError: RegistrationError? = nil @State private var importObserverViewModel = ImportObserver() + @State private var showDisconnectionAlert: Bool = false @Environment(\.horizontalSizeClass) var horizontalSizeClass @State var requiredVersion: String? = nil @@ -91,6 +92,10 @@ struct PadelClubApp: App { .accentColor(.master) .onAppear { self._checkVersion() + + if ManualPatcher.patchIfPossible(.disconnect) == true { + self.showDisconnectionAlert = true + } #if DEBUG print("Running in Debug mode") #elseif TESTFLIGHT @@ -104,6 +109,9 @@ struct PadelClubApp: App { self._onAppear() print(PersistenceController.getModelVersion()) } + .alert(isPresented: self.$showDisconnectionAlert, content: { + Alert(title: Text("Vous avez été déconnecté. Veuillez vous reconnecter pour récupérer vos données.")) + }) .task { // try? Tips.resetDatastore() @@ -255,6 +263,12 @@ struct DownloadNewVersionView: View { } +struct DisconnectionAlertView: View { + var body: some View { + Text("Vous avez été déconnecté. Veuillez vous reconnecter pour récupérer vos données.").multilineTextAlignment(.center).padding() + } +} + #Preview { DownloadNewVersionView(version: "1.2") } diff --git a/PadelClub/Utils/Patcher.swift b/PadelClub/Utils/Patcher.swift index 4b76f79..94e4447 100644 --- a/PadelClub/Utils/Patcher.swift +++ b/PadelClub/Utils/Patcher.swift @@ -8,6 +8,44 @@ import Foundation import LeStorage +enum ManualPatch: String { + case disconnect + + var id: String { + return "padelclub.app.manual.patch.\(self.rawValue)" + } +} + +class ManualPatcher { + + static func patchIfPossible(_ patch: ManualPatch) -> Bool { + if UserDefaults.standard.value(forKey: patch.id) == nil { + do { + Logger.log(">>> Patches \(patch.rawValue)...") + let result = try self._applyPatch(patch) + UserDefaults.standard.setValue(true, forKey: patch.id) + return result + } catch { + Logger.error(error) + } + } + return false + } + + fileprivate static func _applyPatch(_ patch: ManualPatch) throws -> Bool { + switch patch { + case .disconnect: + let rawToken = try? StoreCenter.main.rawTokenShouldNotBeUsed() + if StoreCenter.main.userName != nil || StoreCenter.main.userId != nil || rawToken != nil { + DataStore.shared.disconnect() + return true + } else { + return false + } + } + } +} + enum PatchError: Error { case patchError(message: String) } @@ -21,7 +59,7 @@ enum Patch: String, CaseIterable { } } -class Patcher { +class AutomaticPatcher { static func applyAllWhenApplicable() { for patch in Patch.allCases { From c60ddb772a237020d7eb6c967d7b24e8628bd68c Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 25 Mar 2025 16:14:39 +0100 Subject: [PATCH 5/9] Bumps to 1.2.1 --- PadelClub.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 5a809bf..b2c6495 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -3658,7 +3658,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2; + MARKETING_VERSION = 1.2.1; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3703,7 +3703,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2; + MARKETING_VERSION = 1.2.1; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; From fbd730eae69f5c4da129d7bf9b5d96763f36d9e0 Mon Sep 17 00:00:00 2001 From: Raz Date: Wed, 26 Mar 2025 06:21:28 +0100 Subject: [PATCH 6/9] fix issue with ts setup --- PadelClub/Data/Tournament.swift | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index cd458bf..63c88ed 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -489,9 +489,20 @@ defer { }) { return seedGroupAvailable(atRoundIndex: roundIndex, availableSeedGroup: chunk) } else if fullLeftSeeds.count > 1, targetSpots > 1, fullLeftSeeds.count >= targetSpots { - let seeds = seeds() - if let firstIndex = seeds.firstIndex(where: { $0.isSeedable() }) { - return seedGroupAvailable(atRoundIndex: roundIndex, availableSeedGroup: SeedInterval(first: firstIndex + 1, last: firstIndex + targetSpots)) + let currentSeeds = seeds() + if let firstIndex = currentSeeds.firstIndex(where: { $0.isSeedable() }) { + + if firstIndex < seededTeamsCount { + return nil + } else { + let sg = SeedInterval(first: seededTeamsCount + 1, last: seededTeamsCount + targetSpots) + let futureAvailableSeeds = self.seeds(inSeedGroup: sg) + if futureAvailableSeeds.count >= targetSpots { + return seedGroupAvailable(atRoundIndex: roundIndex, availableSeedGroup: sg) + } else { + return nil + } + } } } } From fc094e56031855b40381b3178d61f215c555eb4e Mon Sep 17 00:00:00 2001 From: Raz Date: Wed, 26 Mar 2025 06:22:19 +0100 Subject: [PATCH 7/9] v1.2.2 --- PadelClub.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index b2c6495..d465514 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -3658,7 +3658,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.1; + MARKETING_VERSION = 1.2.2; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3703,7 +3703,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.1; + MARKETING_VERSION = 1.2.2; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; From 093d67f46998dbca3e3042f23e59c424f2a32f3e Mon Sep 17 00:00:00 2001 From: Raz Date: Wed, 26 Mar 2025 06:26:05 +0100 Subject: [PATCH 8/9] fix --- PadelClub/Data/Tournament.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 63c88ed..a0c5c80 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -497,7 +497,7 @@ defer { } else { let sg = SeedInterval(first: seededTeamsCount + 1, last: seededTeamsCount + targetSpots) let futureAvailableSeeds = self.seeds(inSeedGroup: sg) - if futureAvailableSeeds.count >= targetSpots { + if futureAvailableSeeds.count == targetSpots { return seedGroupAvailable(atRoundIndex: roundIndex, availableSeedGroup: sg) } else { return nil From 081749cc4e2e165996325f705d5206cf90353dea Mon Sep 17 00:00:00 2001 From: Raz Date: Wed, 26 Mar 2025 08:12:37 +0100 Subject: [PATCH 9/9] remove unused slow umpire stat view fix a bit of loading time --- PadelClub.xcodeproj/project.pbxproj | 16 ++++++------- PadelClub/Data/Tournament.swift | 23 +++++++++---------- .../Views/Navigation/Umpire/UmpireView.swift | 16 ++++++------- PadelClub/Views/Player/PlayerDetailView.swift | 14 +++++------ 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index d465514..ed25363 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -3632,7 +3632,7 @@ CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; @@ -3658,7 +3658,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.1; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3678,7 +3678,7 @@ CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -3703,7 +3703,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.1; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3795,7 +3795,7 @@ CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; @@ -3821,7 +3821,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.1; + MARKETING_VERSION = 1.2.1; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3841,7 +3841,7 @@ CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -3866,7 +3866,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.1; + MARKETING_VERSION = 1.2.1; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index a0c5c80..2925f8f 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -19,7 +19,7 @@ final class Tournament: BaseTournament { func shouldRefreshTeams() -> Bool { guard let lastTeamRefresh else { return true } - return lastTeamRefresh.timeIntervalSinceNow < -60 + return lastTeamRefresh.timeIntervalSinceNow < -600 } @ObservationIgnored @@ -2337,6 +2337,10 @@ defer { // MARK: - Status func shouldTournamentBeOver() async -> Bool { + return false + if tournamentStore?.store.fileCollectionsAllLoaded() == false { + return false + } #if _DEBUGING_TIME //DEBUGING TIME let start = Date() defer { @@ -2378,24 +2382,19 @@ defer { func refreshTeamList() async { guard StoreCenter.main.isAuthenticated else { return } + guard tournamentStore?.store.fileCollectionsAllLoaded() == true else { return } guard shouldRefreshTeams(), refreshInProgress == false, enableOnlineRegistration, hasEnded() == false else { return } - await MainActor.run { - refreshInProgress = true - } + refreshInProgress = true do { try await self.tournamentStore?.playerRegistrations.loadDataFromServerIfAllowed(clear: true) try await self.tournamentStore?.teamScores.loadDataFromServerIfAllowed(clear: true) try await self.tournamentStore?.teamRegistrations.loadDataFromServerIfAllowed(clear: true) - await MainActor.run { - refreshInProgress = false - lastTeamRefresh = Date() - } + refreshInProgress = false + lastTeamRefresh = Date() } catch { Logger.error(error) - await MainActor.run { - refreshInProgress = false - lastTeamRefresh = Date() - } + refreshInProgress = false + lastTeamRefresh = Date() } } diff --git a/PadelClub/Views/Navigation/Umpire/UmpireView.swift b/PadelClub/Views/Navigation/Umpire/UmpireView.swift index 78adfb1..c6d5b5b 100644 --- a/PadelClub/Views/Navigation/Umpire/UmpireView.swift +++ b/PadelClub/Views/Navigation/Umpire/UmpireView.swift @@ -121,14 +121,14 @@ struct UmpireView: View { Text("Il s'agit des clubs qui sont utilisés pour récupérer les tournois tenup.") } - Section { - NavigationLink { - UmpireStatisticView() - } label: { - Text("Statistiques de participations") - } - } - +// Section { +// NavigationLink { +// UmpireStatisticView() +// } label: { +// Text("Statistiques de participations") +// } +// } +// Section { @Bindable var user = dataStore.user diff --git a/PadelClub/Views/Player/PlayerDetailView.swift b/PadelClub/Views/Player/PlayerDetailView.swift index 52036ae..9905c45 100644 --- a/PadelClub/Views/Player/PlayerDetailView.swift +++ b/PadelClub/Views/Player/PlayerDetailView.swift @@ -220,13 +220,13 @@ struct PlayerDetailView: View { } } - Section { - NavigationLink { - PlayerStatisticView(player: player) - } label: { - Text("Statistiques de participations") - } - } +// Section { +// NavigationLink { +// PlayerStatisticView(player: player) +// } label: { +// Text("Statistiques de participations") +// } +// } } .onChange(of: [player.hasArrived, player.captain, player.coach]) { _save()