From 8602881562590a13fa1403cc3f0391106f3da69b Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 29 Sep 2025 11:04:09 +0200 Subject: [PATCH] fix ios 26 add tournament name in subtitle in a lot of subviews add the ability to transfer tournaments into an event fix broadcast view page to better display some sharing options --- PadelClub.xcodeproj/project.pbxproj | 16 ++++ PadelClub/Extensions/View+Extensions.swift | 22 +++++ PadelClub/Utils/Tips.swift | 15 +++ .../Cashier/Event/EventTournamentsView.swift | 31 ++++++- .../Cashier/Event/TournamentPickerView.swift | 91 +++++++++++++++++++ .../Views/Components/BarButtonView.swift | 25 ++--- .../Views/GroupStage/GroupStagesView.swift | 5 + PadelClub/Views/Match/MatchDetailView.swift | 8 +- .../Agenda/TournamentSubscriptionView.swift | 14 --- .../CourtAvailabilitySettingsView.swift | 10 +- PadelClub/Views/Round/LoserRoundsView.swift | 7 ++ PadelClub/Views/Round/RoundsView.swift | 6 ++ PadelClub/Views/Score/EditScoreView.swift | 7 ++ PadelClub/Views/Score/FollowUpMatchView.swift | 7 ++ .../Tournament/Screen/BroadcastView.swift | 55 +++++++---- .../Screen/InscriptionManagerView.swift | 5 + .../Tournament/Screen/PrintSettingsView.swift | 5 + .../Screen/RegistrationSetupView.swift | 5 + .../Screen/TableStructureView.swift | 6 ++ .../Screen/TournamentCallView.swift | 5 + .../Screen/TournamentCashierView.swift | 5 + .../Screen/TournamentRankView.swift | 5 + .../Screen/TournamentScheduleView.swift | 6 ++ .../Screen/TournamentSettingsView.swift | 6 ++ .../Views/Tournament/TournamentView.swift | 20 +++- 25 files changed, 330 insertions(+), 57 deletions(-) create mode 100644 PadelClub/Extensions/View+Extensions.swift create mode 100644 PadelClub/Views/Cashier/Event/TournamentPickerView.swift diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 6c74e32..16a1d4f 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -711,6 +711,12 @@ FFA252B62CDD2C6C0074E63F /* OngoingDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA252B42CDD2C630074E63F /* OngoingDestination.swift */; }; FFA252B72CDD2C6C0074E63F /* OngoingDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA252B42CDD2C630074E63F /* OngoingDestination.swift */; }; FFA6D7852BB0B795003A31F3 /* FileImportManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */; }; + FFA97C8D2E8A59D00089EA22 /* TournamentPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA97C8C2E8A59D00089EA22 /* TournamentPickerView.swift */; }; + FFA97C8E2E8A59D00089EA22 /* TournamentPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA97C8C2E8A59D00089EA22 /* TournamentPickerView.swift */; }; + FFA97C8F2E8A59D00089EA22 /* TournamentPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA97C8C2E8A59D00089EA22 /* TournamentPickerView.swift */; }; + FFA97C9E2E8A7C080089EA22 /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA97C9D2E8A7C080089EA22 /* View+Extensions.swift */; }; + FFA97C9F2E8A7C080089EA22 /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA97C9D2E8A7C080089EA22 /* View+Extensions.swift */; }; + FFA97CA02E8A7C080089EA22 /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA97C9D2E8A7C080089EA22 /* View+Extensions.swift */; }; FFB0FF672E81B671009EDEAC /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB0FF662E81B671009EDEAC /* OnboardingView.swift */; }; FFB0FF682E81B671009EDEAC /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB0FF662E81B671009EDEAC /* OnboardingView.swift */; }; FFB0FF692E81B671009EDEAC /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB0FF662E81B671009EDEAC /* OnboardingView.swift */; }; @@ -1118,6 +1124,8 @@ FFA252B42CDD2C630074E63F /* OngoingDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OngoingDestination.swift; sourceTree = ""; }; FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileImportManager.swift; sourceTree = ""; }; FFA6D78A2BB0BEB3003A31F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + FFA97C8C2E8A59D00089EA22 /* TournamentPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentPickerView.swift; sourceTree = ""; }; + FFA97C9D2E8A7C080089EA22 /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = ""; }; FFB0FF662E81B671009EDEAC /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = ""; }; FFB0FF722E841042009EDEAC /* WeekdaySelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeekdaySelectionView.swift; sourceTree = ""; }; FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentBroadcastRowView.swift; sourceTree = ""; }; @@ -1341,6 +1349,7 @@ C49771DE2DC25F04005CD239 /* Badge+Extensions.swift */, C49771DF2DC25F04005CD239 /* SpinDrawable+Extensions.swift */, C49772022DC260D3005CD239 /* Round+Extensions.swift */, + FFA97C9D2E8A7C080089EA22 /* View+Extensions.swift */, ); path = Extensions; sourceTree = ""; @@ -1866,6 +1875,7 @@ FFE103072C353B7600684FC9 /* EventClubSettingsView.swift */, FF8F263C2BAD627A00650388 /* TournamentConfiguratorView.swift */, FF8E52332DF01D6100099B75 /* EventStatusView.swift */, + FFA97C8C2E8A59D00089EA22 /* TournamentPickerView.swift */, ); name = Event; path = Cashier/Event; @@ -2346,6 +2356,7 @@ FF5BAF6E2BE0B3C8008B4B7E /* FederalDataViewModel.swift in Sources */, FF3F74FF2B91A2D4004CFE0E /* AgendaDestination.swift in Sources */, FF3795622B9396D0004EA093 /* PadelClubApp.xcdatamodeld in Sources */, + FFA97CA02E8A7C080089EA22 /* View+Extensions.swift in Sources */, FFCFC0162BBC5A4C00B82851 /* SetInputView.swift in Sources */, FFF03C942BD91D0C00B516FC /* ButtonValidateView.swift in Sources */, FF5D0D892BB4935C005CB568 /* ClubRowView.swift in Sources */, @@ -2434,6 +2445,7 @@ FFF527D62BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift in Sources */, FFC91AF92BD6A09100B29808 /* FortuneWheelView.swift in Sources */, FFE8B5C82DAA390900BDE966 /* StripeValidationService.swift in Sources */, + FFA97C8D2E8A59D00089EA22 /* TournamentPickerView.swift in Sources */, C493B37E2C10AD3600862481 /* LoadingViewModifier.swift in Sources */, FF089EBD2BB0287D00F0AEC7 /* PlayerView.swift in Sources */, FF967D032BAEF0C000A9A3BD /* MatchDetailView.swift in Sources */, @@ -2613,6 +2625,7 @@ FF4CBFBF2C996C0600151637 /* SetInputView.swift in Sources */, FF4CBFC02C996C0600151637 /* ButtonValidateView.swift in Sources */, FF4CBFC12C996C0600151637 /* ClubRowView.swift in Sources */, + FFA97C9E2E8A7C080089EA22 /* View+Extensions.swift in Sources */, FF4CBFC22C996C0600151637 /* ClubDetailView.swift in Sources */, FF4CBFC32C996C0600151637 /* GroupStageCallingView.swift in Sources */, FF4CBFC52C996C0600151637 /* CashierSettingsView.swift in Sources */, @@ -2701,6 +2714,7 @@ FF4CC0102C996C0600151637 /* LoadingViewModifier.swift in Sources */, FF4CC0112C996C0600151637 /* PlayerView.swift in Sources */, FF4CC0122C996C0600151637 /* MatchDetailView.swift in Sources */, + FFA97C8F2E8A59D00089EA22 /* TournamentPickerView.swift in Sources */, FF4CC0142C996C0600151637 /* PlayerBlockView.swift in Sources */, FF4CC0172C996C0600151637 /* PointView.swift in Sources */, FF4CC0182C996C0600151637 /* ClubHolder.swift in Sources */, @@ -2858,6 +2872,7 @@ FF70FB3E2C90584900129CC2 /* SetInputView.swift in Sources */, FF70FB3F2C90584900129CC2 /* ButtonValidateView.swift in Sources */, FF70FB402C90584900129CC2 /* ClubRowView.swift in Sources */, + FFA97C9F2E8A7C080089EA22 /* View+Extensions.swift in Sources */, FF70FB412C90584900129CC2 /* ClubDetailView.swift in Sources */, FF70FB422C90584900129CC2 /* GroupStageCallingView.swift in Sources */, FF70FB442C90584900129CC2 /* CashierSettingsView.swift in Sources */, @@ -2946,6 +2961,7 @@ FF70FB8F2C90584900129CC2 /* LoadingViewModifier.swift in Sources */, FF70FB902C90584900129CC2 /* PlayerView.swift in Sources */, FF70FB912C90584900129CC2 /* MatchDetailView.swift in Sources */, + FFA97C8E2E8A59D00089EA22 /* TournamentPickerView.swift in Sources */, FF70FB932C90584900129CC2 /* PlayerBlockView.swift in Sources */, FF70FB962C90584900129CC2 /* PointView.swift in Sources */, FF70FB972C90584900129CC2 /* ClubHolder.swift in Sources */, diff --git a/PadelClub/Extensions/View+Extensions.swift b/PadelClub/Extensions/View+Extensions.swift new file mode 100644 index 0000000..d24a949 --- /dev/null +++ b/PadelClub/Extensions/View+Extensions.swift @@ -0,0 +1,22 @@ +// +// View+Extensions.swift +// PadelClub +// +// Created by Razmig Sarkissian on 29/09/2025. +// + +import SwiftUI + +extension View { + /// Runs a transform only on iOS 26+, otherwise returns self + @ViewBuilder + func ifAvailableiOS26( + @ViewBuilder transform: (Self) -> Content + ) -> some View { + if #available(iOS 26.0, *) { + transform(self) + } else { + self + } + } +} diff --git a/PadelClub/Utils/Tips.swift b/PadelClub/Utils/Tips.swift index 1b0cb6c..befc086 100644 --- a/PadelClub/Utils/Tips.swift +++ b/PadelClub/Utils/Tips.swift @@ -660,6 +660,21 @@ struct UpdatePlannedDatesTip: Tip { } } +struct MergeTournamentTip: Tip { + var title: Text { + Text("Transfert de tournois") + } + + var message: Text? { + Text("Vous pouvez transferer des tournois d'un autre événement dans celui-ci.") + } + + var image: Image? { + Image(systemName: "square.and.arrow.down") + } +} + + struct TipStyleModifier: ViewModifier { @Environment(\.colorScheme) var colorScheme var tint: Color? diff --git a/PadelClub/Views/Cashier/Event/EventTournamentsView.swift b/PadelClub/Views/Cashier/Event/EventTournamentsView.swift index 2d554fc..e80f3bb 100644 --- a/PadelClub/Views/Cashier/Event/EventTournamentsView.swift +++ b/PadelClub/Views/Cashier/Event/EventTournamentsView.swift @@ -15,7 +15,8 @@ struct EventTournamentsView: View { let event: Event @State private var newTournament: Tournament? @State private var mainTournament: Tournament? - + @State private var showTournamentPicker: Bool = false + var presentTournamentCreationView: Binding { Binding( get: { newTournament != nil }, set: { isPresented in @@ -122,13 +123,35 @@ struct EventTournamentsView: View { } .toolbar { ToolbarItem(placement: .topBarTrailing) { - BarButtonView("Ajouter un tournoi", icon: "plus.circle.fill") { - let tournament = Tournament.newEmptyInstance() - newTournament = tournament + BarButtonView("Importer un tournoi", icon: "square.and.arrow.down") { + showTournamentPicker = true + } + } + if #available(iOS 26.0, *) { + ToolbarSpacer(placement: .topBarTrailing) + } + + ToolbarItem(placement: .topBarTrailing) { + if #available(iOS 26.0, *) { + BarButtonView("Ajouter une indisponibilité", icon: "plus") { + let tournament = Tournament.newEmptyInstance() + newTournament = tournament + } + } else { + BarButtonView("Ajouter une indisponibilité", icon: "plus.circle.fill") { + let tournament = Tournament.newEmptyInstance() + newTournament = tournament + } } } } .headerProminence(.increased) + .sheet(isPresented: $showTournamentPicker, content: { + NavigationStack { + TournamentPickerView(event: event) + .environmentObject(dataStore) + } + }) .sheet(isPresented: presentTournamentCreationView) { if let newTournament { NavigationStack { diff --git a/PadelClub/Views/Cashier/Event/TournamentPickerView.swift b/PadelClub/Views/Cashier/Event/TournamentPickerView.swift new file mode 100644 index 0000000..1b265d0 --- /dev/null +++ b/PadelClub/Views/Cashier/Event/TournamentPickerView.swift @@ -0,0 +1,91 @@ +// +// TournamentPickerView.swift +// PadelClub +// +// Created by Razmig Sarkissian on 29/09/2025. +// + +import SwiftUI +import LeStorage +import PadelClubData +import TipKit + +struct TournamentPickerView: View { + @EnvironmentObject var dataStore: DataStore + @Environment(\.dismiss) private var dismiss + let mergeTournamentTip = MergeTournamentTip() + let event: Event + @State private var selectedTournamentIds: Set = Set() + @State private var shouldEraseEmptyEvents: Bool = false + + var tournaments: [Tournament] { + dataStore.tournaments.filter({ $0.isDeleted == false && $0.event?.id != event.id }).sorted(by: \.startDate, order: .descending) + } + + var body: some View { + List(selection: $selectedTournamentIds) { + Section { + TipView(mergeTournamentTip) + .tipStyle(tint: .green) + } + + Section { + Toggle(isOn: $shouldEraseEmptyEvents) { + Text("Effacer les événements vides") + Text("Les événements qui n'ont plus de tournois seront effacés automatiquement.") + } + } + + ForEach(tournaments) { tournament in + TournamentCellView(tournament: tournament).tag(tournament.id) + } + } + .environment(\.editMode, Binding.constant(EditMode.active)) + .toolbar { + ToolbarItem(placement: .topBarLeading) { + Button("Annuler") { + dismiss() + } + } + ToolbarItem(placement: .topBarTrailing) { + ButtonValidateView { + _transferTournaments() + dismiss() + } + .disabled(selectedTournamentIds.isEmpty) + } + } + .navigationTitle("Transfert de tournois") + } + + private func _transferTournaments() { + let tournaments = tournaments + var eventIdsToCheck = Set() + var tournamentsToSave = [Tournament]() + selectedTournamentIds.forEach { id in + if let tournament = tournaments.first(where: { $0.id == id }) { + if let eventId = tournament.event{ + eventIdsToCheck.insert(eventId) + } + tournament.event = event.id + tournamentsToSave.append(tournament) + } + } + + dataStore.tournaments.addOrUpdate(contentOfs: tournamentsToSave) + + if shouldEraseEmptyEvents { + + var eventsToDelete = [Event]() + eventIdsToCheck.forEach { eventId in + if let eventToCheck = dataStore.events.first(where: { $0.id == eventId }) { + if eventToCheck.tournaments.isEmpty && shouldEraseEmptyEvents { + eventsToDelete.append(eventToCheck) + } + } + } + + dataStore.events.delete(contentOfs: eventsToDelete) + } + } +} diff --git a/PadelClub/Views/Components/BarButtonView.swift b/PadelClub/Views/Components/BarButtonView.swift index b92c01e..6caf801 100644 --- a/PadelClub/Views/Components/BarButtonView.swift +++ b/PadelClub/Views/Components/BarButtonView.swift @@ -22,23 +22,14 @@ struct BarButtonView: View { Button(action: { action() }) { - Image(systemName: icon) - .resizable() - .scaledToFit() - .frame(minHeight: 28) - - /* - Label { - Text(accessibilityLabel) - } icon: { - Image(systemName: icon) - .resizable() - .scaledToFit() - .frame(minHeight: 36) - } - .labelStyle(.iconOnly) - //todo: resizing not working when label used - */ + if #available(iOS 26.0, *) { + Label(accessibilityLabel, systemImage: icon) + } else { + Image(systemName: icon) + .resizable() + .scaledToFit() + .frame(minHeight: 32) + } } } } diff --git a/PadelClub/Views/GroupStage/GroupStagesView.swift b/PadelClub/Views/GroupStage/GroupStagesView.swift index a14d4bb..cff819c 100644 --- a/PadelClub/Views/GroupStage/GroupStagesView.swift +++ b/PadelClub/Views/GroupStage/GroupStagesView.swift @@ -256,5 +256,10 @@ struct GroupStagesView: View { .environment(tournament) .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } } } diff --git a/PadelClub/Views/Match/MatchDetailView.swift b/PadelClub/Views/Match/MatchDetailView.swift index 882cc00..e6cca86 100644 --- a/PadelClub/Views/Match/MatchDetailView.swift +++ b/PadelClub/Views/Match/MatchDetailView.swift @@ -420,7 +420,13 @@ struct MatchDetailView: View { .navigationTitle(match.matchTitle()) .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) - + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + if let tournament = match.currentTournament() { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } + } } var quickLookHeader: some View { diff --git a/PadelClub/Views/Navigation/Agenda/TournamentSubscriptionView.swift b/PadelClub/Views/Navigation/Agenda/TournamentSubscriptionView.swift index 1c27a96..b60e091 100644 --- a/PadelClub/Views/Navigation/Agenda/TournamentSubscriptionView.swift +++ b/PadelClub/Views/Navigation/Agenda/TournamentSubscriptionView.swift @@ -383,17 +383,3 @@ struct TournamentSubscriptionView: View { } } - -extension View { - /// Runs a transform only on iOS 26+, otherwise returns self - @ViewBuilder - func ifAvailableiOS26( - @ViewBuilder transform: (Self) -> Content - ) -> some View { - if #available(iOS 26.0, *) { - transform(self) - } else { - self - } - } -} diff --git a/PadelClub/Views/Planning/CourtAvailabilitySettingsView.swift b/PadelClub/Views/Planning/CourtAvailabilitySettingsView.swift index 3f68a1f..28d8bd6 100644 --- a/PadelClub/Views/Planning/CourtAvailabilitySettingsView.swift +++ b/PadelClub/Views/Planning/CourtAvailabilitySettingsView.swift @@ -111,8 +111,14 @@ struct CourtAvailabilitySettingsView: View { } .toolbar { ToolbarItem(placement: .topBarTrailing) { - BarButtonView("Ajouter une indisponibilité", icon: "plus.circle.fill") { - showingPopover = true + if #available(iOS 26.0, *) { + BarButtonView("Ajouter une indisponibilité", icon: "plus") { + showingPopover = true + } + } else { + BarButtonView("Ajouter une indisponibilité", icon: "plus.circle.fill") { + showingPopover = true + } } } } diff --git a/PadelClub/Views/Round/LoserRoundsView.swift b/PadelClub/Views/Round/LoserRoundsView.swift index 53179cd..55808a5 100644 --- a/PadelClub/Views/Round/LoserRoundsView.swift +++ b/PadelClub/Views/Round/LoserRoundsView.swift @@ -297,5 +297,12 @@ struct LoserRoundsView: View { .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) .navigationTitle(upperBracketRound.correspondingLoserRoundTitle) + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + if let tournament = upperBracketRound.round.tournamentObject() { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } + } } } diff --git a/PadelClub/Views/Round/RoundsView.swift b/PadelClub/Views/Round/RoundsView.swift index 63a471e..81affa9 100644 --- a/PadelClub/Views/Round/RoundsView.swift +++ b/PadelClub/Views/Round/RoundsView.swift @@ -48,11 +48,17 @@ struct RoundsView: View { case .some(let selectedRound): RoundView(upperRound: selectedRound).id(selectedRound.id) .navigationTitle(selectedRound.round.roundTitle()) + } } .environment(\.isEditingTournamentSeed, $isEditingTournamentSeed) .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } } } diff --git a/PadelClub/Views/Score/EditScoreView.swift b/PadelClub/Views/Score/EditScoreView.swift index 49d6be6..abf53d8 100644 --- a/PadelClub/Views/Score/EditScoreView.swift +++ b/PadelClub/Views/Score/EditScoreView.swift @@ -244,6 +244,13 @@ struct EditScoreView: View { matchDescriptor.setDescriptors.removeAll() matchDescriptor.addNewSet() } + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + if let tournament = matchDescriptor.match?.currentTournament() { + $0.navigationBarTitle(tournament.tournamentTitle()) + } + } + } } func save() { diff --git a/PadelClub/Views/Score/FollowUpMatchView.swift b/PadelClub/Views/Score/FollowUpMatchView.swift index 93bb494..6134a5d 100644 --- a/PadelClub/Views/Score/FollowUpMatchView.swift +++ b/PadelClub/Views/Score/FollowUpMatchView.swift @@ -292,6 +292,13 @@ struct FollowUpMatchView: View { } } } + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + if let tournament = match?.currentTournament() { + $0.navigationBarTitle(tournament.tournamentTitle()) + } + } + } .onChange(of: readyMatches) { dismissWhenPresentFollowUpMatchIsDismissed = true if autoDismiss { diff --git a/PadelClub/Views/Tournament/Screen/BroadcastView.swift b/PadelClub/Views/Tournament/Screen/BroadcastView.swift index 33ef854..0af1148 100644 --- a/PadelClub/Views/Tournament/Screen/BroadcastView.swift +++ b/PadelClub/Views/Tournament/Screen/BroadcastView.swift @@ -84,6 +84,24 @@ struct BroadcastView: View { .tipStyle(tint: nil) } + if let shareURL = tournament.shareURL(.info) { + Section { + Link(destination: shareURL) { + Text(shareURL.absoluteString) + } + } header: { + Text("Page d'information") + } footer: { + HStack { + CopyPasteButtonView(pasteValue: shareURL.absoluteString) + Spacer() + ShareLink(item: shareURL) { + Label("Partager", systemImage: "square.and.arrow.up") + } + } + } + } + if let url = tournament.shareURL(.clubBroadcast) { Section { Link(destination: url) { @@ -113,6 +131,21 @@ struct BroadcastView: View { } } + Section { + let links : [PageLink] = [.info, .teams, .summons, .groupStages, .matches, .rankings, .broadcast, .clubBroadcast] + Picker(selection: $pageLink) { + ForEach(links) { pageLink in + Text(pageLink.localizedLabel()).tag(pageLink) + } + } label: { + Text("Page à partager") + } + .pickerStyle(.menu) + actionForURL(title: "Partager la page '" + pageLink.localizedLabel() + "'", url: tournament.shareURL(pageLink)) + } header: { + Text("Lien du tournoi à partager") + } + if tournament.isPrivate == false { Section { @@ -300,24 +333,9 @@ struct BroadcastView: View { } } .toolbar(content: { - if StoreCenter.main.userId != nil, tournament.isPrivate == false, tournament.club() != nil { + if StoreCenter.main.userId != nil, tournament.club() != nil { ToolbarItem(placement: .topBarTrailing) { Menu { - Section { - let links : [PageLink] = [.info, .teams, .summons, .groupStages, .matches, .rankings, .broadcast, .clubBroadcast] - Picker(selection: $pageLink) { - ForEach(links) { pageLink in - Text(pageLink.localizedLabel()).tag(pageLink) - } - } label: { - Text("Choisir la page à partager") - } - .pickerStyle(.menu) - actionForURL(title: "Partager la page '" + pageLink.localizedLabel() + "'", url: tournament.shareURL(pageLink)) - } header: { - Text("Lien du tournoi à partager") - } - #if DEBUG Section { actionForURL(title: "La Boutique", url: URLs.main.url.appending(path: "shop")) @@ -344,6 +362,11 @@ struct BroadcastView: View { }) .headerProminence(.increased) .navigationTitle("Publication") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) .sheet(item: $urlToShow) { urlToShow in diff --git a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift index 04a5981..a93f24b 100644 --- a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift +++ b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift @@ -485,6 +485,11 @@ struct InscriptionManagerView: View { } .toolbarBackground(.visible, for: .navigationBar) .navigationTitle("Inscriptions") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } .navigationBarTitleDisplayMode(.inline) .onChange(of: tournament.hideTeamsWeight) { _save() diff --git a/PadelClub/Views/Tournament/Screen/PrintSettingsView.swift b/PadelClub/Views/Tournament/Screen/PrintSettingsView.swift index b5fddb2..b7fc725 100644 --- a/PadelClub/Views/Tournament/Screen/PrintSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/PrintSettingsView.swift @@ -169,6 +169,11 @@ struct PrintSettingsView: View { } } .navigationTitle("Imprimer") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } .toolbarBackground(.visible, for: .navigationBar) .navigationBarTitleDisplayMode(.inline) .sheet(isPresented: $presentShareView) { diff --git a/PadelClub/Views/Tournament/Screen/RegistrationSetupView.swift b/PadelClub/Views/Tournament/Screen/RegistrationSetupView.swift index 4b51a39..53ef012 100644 --- a/PadelClub/Views/Tournament/Screen/RegistrationSetupView.swift +++ b/PadelClub/Views/Tournament/Screen/RegistrationSetupView.swift @@ -358,6 +358,11 @@ struct RegistrationSetupView: View { .toolbarRole(.editor) .headerProminence(.increased) .navigationTitle("Inscription en ligne") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) .navigationBarBackButtonHidden(hasChanges) diff --git a/PadelClub/Views/Tournament/Screen/TableStructureView.swift b/PadelClub/Views/Tournament/Screen/TableStructureView.swift index 652f4d9..1867d8f 100644 --- a/PadelClub/Views/Tournament/Screen/TableStructureView.swift +++ b/PadelClub/Views/Tournament/Screen/TableStructureView.swift @@ -412,6 +412,12 @@ struct TableStructureView: View { } .navigationTitle("Structure") .navigationBarTitleDisplayMode(.inline) + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } + } diff --git a/PadelClub/Views/Tournament/Screen/TournamentCallView.swift b/PadelClub/Views/Tournament/Screen/TournamentCallView.swift index d6eb3c1..c8a96c0 100644 --- a/PadelClub/Views/Tournament/Screen/TournamentCallView.swift +++ b/PadelClub/Views/Tournament/Screen/TournamentCallView.swift @@ -137,6 +137,11 @@ struct TournamentCallView: View { .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) .navigationTitle("Convocations") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } } } diff --git a/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift b/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift index 66b1fc5..3882b56 100644 --- a/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift +++ b/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift @@ -166,6 +166,11 @@ struct TournamentCashierView: View { .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) .navigationTitle(tournament.isFree() ? "Présence" : "Encaissement") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } } else { Text("no store") } diff --git a/PadelClub/Views/Tournament/Screen/TournamentRankView.swift b/PadelClub/Views/Tournament/Screen/TournamentRankView.swift index bb72722..afe9356 100644 --- a/PadelClub/Views/Tournament/Screen/TournamentRankView.swift +++ b/PadelClub/Views/Tournament/Screen/TournamentRankView.swift @@ -158,6 +158,11 @@ struct TournamentRankView: View { } } .navigationTitle("Classement") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) .toolbar { diff --git a/PadelClub/Views/Tournament/Screen/TournamentScheduleView.swift b/PadelClub/Views/Tournament/Screen/TournamentScheduleView.swift index 30da32a..81cdf5c 100644 --- a/PadelClub/Views/Tournament/Screen/TournamentScheduleView.swift +++ b/PadelClub/Views/Tournament/Screen/TournamentScheduleView.swift @@ -101,6 +101,12 @@ struct TournamentScheduleView: View { .toolbarRole(.editor) .toolbarBackground(.visible, for: .navigationBar) .navigationTitle("Horaires et formats") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } + } } diff --git a/PadelClub/Views/Tournament/Screen/TournamentSettingsView.swift b/PadelClub/Views/Tournament/Screen/TournamentSettingsView.swift index a9b29aa..9dcd82f 100644 --- a/PadelClub/Views/Tournament/Screen/TournamentSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/TournamentSettingsView.swift @@ -81,6 +81,12 @@ struct TournamentSettingsView: View { .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) .navigationTitle("Réglages du tournoi") + .ifAvailableiOS26 { + if #available(iOS 26.0, *) { + $0.navigationSubtitle(tournament.tournamentTitle()) + } + } + } } diff --git a/PadelClub/Views/Tournament/TournamentView.swift b/PadelClub/Views/Tournament/TournamentView.swift index 8e452f9..8539028 100644 --- a/PadelClub/Views/Tournament/TournamentView.swift +++ b/PadelClub/Views/Tournament/TournamentView.swift @@ -240,15 +240,29 @@ struct TournamentView: View { } Menu { - NavigationLink(value: Screen.event) { + Button { + navigation.path.append(Screen.event) + } label: { Text("Événement") + if let tournamentCount = tournament.eventObject()?.confirmedTournaments().count { + Text(tournamentCount.formatted() + " tournoi" + tournamentCount.pluralSuffix) + .foregroundStyle(.secondary) + } } - NavigationLink(value: Screen.settings) { + Button { + navigation.path.append(Screen.settings) + } label: { Text("Tournoi") + Text("Inscription en ligne, pistes, formats") + .foregroundStyle(.secondary) } - NavigationLink(value: Screen.structure) { + Button { + navigation.path.append(Screen.structure) + } label: { LabelStructure() + Text("Poules, tableau, qualifiés sortants") + .foregroundStyle(.secondary) } Divider()