clean matchviewstyle to make it environment variable

fix lag due to court used calculation on each match cell
paca_championship
Raz 12 months ago
parent 17e0c85e0b
commit e852999739
  1. 8
      PadelClub.xcodeproj/project.pbxproj
  2. 15
      PadelClub/Data/Match.swift
  3. 4
      PadelClub/Data/PlayerRegistration.swift
  4. 26
      PadelClub/Utils/DisplayContext.swift
  5. 51
      PadelClub/ViewModel/MatchViewStyle.swift
  6. 4
      PadelClub/Views/Components/MatchListView.swift
  7. 10
      PadelClub/Views/GroupStage/GroupStagesView.swift
  8. 3
      PadelClub/Views/GroupStage/LoserBracketFromGroupStageView.swift
  9. 8
      PadelClub/Views/Match/Components/MatchDateView.swift
  10. 23
      PadelClub/Views/Match/Components/PlayerBlockView.swift
  11. 8
      PadelClub/Views/Match/MatchDetailView.swift
  12. 6
      PadelClub/Views/Match/MatchRowView.swift
  13. 59
      PadelClub/Views/Match/MatchSummaryView.swift
  14. 3
      PadelClub/Views/Navigation/Ongoing/OngoingView.swift
  15. 3
      PadelClub/Views/Planning/PlanningByCourtView.swift
  16. 4
      PadelClub/Views/Planning/PlanningView.swift
  17. 3
      PadelClub/Views/Round/LoserRoundView.swift
  18. 3
      PadelClub/Views/Round/RoundView.swift
  19. 3
      PadelClub/Views/Score/FollowUpMatchView.swift
  20. 3
      PadelClub/Views/Team/TeamRestingView.swift

@ -789,6 +789,9 @@
FFB9C8712BBADDE200A0EF4F /* Selectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB9C8702BBADDE200A0EF4F /* Selectable.swift */; }; FFB9C8712BBADDE200A0EF4F /* Selectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB9C8702BBADDE200A0EF4F /* Selectable.swift */; };
FFB9C8752BBADDF700A0EF4F /* SeedInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB9C8742BBADDF700A0EF4F /* SeedInterval.swift */; }; FFB9C8752BBADDF700A0EF4F /* SeedInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB9C8742BBADDF700A0EF4F /* SeedInterval.swift */; };
FFBA2D2D2CA2CE9E00D5BBDD /* CodingContainer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C33F752C9B1EC5006316DE /* CodingContainer+Extensions.swift */; }; FFBA2D2D2CA2CE9E00D5BBDD /* CodingContainer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C33F752C9B1EC5006316DE /* CodingContainer+Extensions.swift */; };
FFBE62052CE9DA0900815D33 /* MatchViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBE62042CE9DA0900815D33 /* MatchViewStyle.swift */; };
FFBE62062CE9DA0900815D33 /* MatchViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBE62042CE9DA0900815D33 /* MatchViewStyle.swift */; };
FFBE62072CE9DA0900815D33 /* MatchViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBE62042CE9DA0900815D33 /* MatchViewStyle.swift */; };
FFBF065C2BBD2657009D6715 /* GroupStageTeamView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065B2BBD2657009D6715 /* GroupStageTeamView.swift */; }; FFBF065C2BBD2657009D6715 /* GroupStageTeamView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065B2BBD2657009D6715 /* GroupStageTeamView.swift */; };
FFBF065E2BBD8040009D6715 /* MatchListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065D2BBD8040009D6715 /* MatchListView.swift */; }; FFBF065E2BBD8040009D6715 /* MatchListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065D2BBD8040009D6715 /* MatchListView.swift */; };
FFBF06602BBD9F6D009D6715 /* NavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065F2BBD9F6D009D6715 /* NavigationViewModel.swift */; }; FFBF06602BBD9F6D009D6715 /* NavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065F2BBD9F6D009D6715 /* NavigationViewModel.swift */; };
@ -1178,6 +1181,7 @@
FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentBroadcastRowView.swift; sourceTree = "<group>"; }; FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentBroadcastRowView.swift; sourceTree = "<group>"; };
FFB9C8702BBADDE200A0EF4F /* Selectable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Selectable.swift; sourceTree = "<group>"; }; FFB9C8702BBADDE200A0EF4F /* Selectable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Selectable.swift; sourceTree = "<group>"; };
FFB9C8742BBADDF700A0EF4F /* SeedInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedInterval.swift; sourceTree = "<group>"; }; FFB9C8742BBADDF700A0EF4F /* SeedInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedInterval.swift; sourceTree = "<group>"; };
FFBE62042CE9DA0900815D33 /* MatchViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchViewStyle.swift; sourceTree = "<group>"; };
FFBF065B2BBD2657009D6715 /* GroupStageTeamView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupStageTeamView.swift; sourceTree = "<group>"; }; FFBF065B2BBD2657009D6715 /* GroupStageTeamView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupStageTeamView.swift; sourceTree = "<group>"; };
FFBF065D2BBD8040009D6715 /* MatchListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchListView.swift; sourceTree = "<group>"; }; FFBF065D2BBD8040009D6715 /* MatchListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchListView.swift; sourceTree = "<group>"; };
FFBF065F2BBD9F6D009D6715 /* NavigationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewModel.swift; sourceTree = "<group>"; }; FFBF065F2BBD9F6D009D6715 /* NavigationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewModel.swift; sourceTree = "<group>"; };
@ -1733,6 +1737,7 @@
FFCFC01B2BBC5AAA00B82851 /* SetDescriptor.swift */, FFCFC01B2BBC5AAA00B82851 /* SetDescriptor.swift */,
FFBF065F2BBD9F6D009D6715 /* NavigationViewModel.swift */, FFBF065F2BBD9F6D009D6715 /* NavigationViewModel.swift */,
FF5BAF6D2BE0B3C8008B4B7E /* FederalDataViewModel.swift */, FF5BAF6D2BE0B3C8008B4B7E /* FederalDataViewModel.swift */,
FFBE62042CE9DA0900815D33 /* MatchViewStyle.swift */,
); );
path = ViewModel; path = ViewModel;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2321,6 +2326,7 @@
FF025AE12BD0EB9000A86CF8 /* TournamentClubSettingsView.swift in Sources */, FF025AE12BD0EB9000A86CF8 /* TournamentClubSettingsView.swift in Sources */,
FFBF065C2BBD2657009D6715 /* GroupStageTeamView.swift in Sources */, FFBF065C2BBD2657009D6715 /* GroupStageTeamView.swift in Sources */,
FF5DA1932BB9279B00A33061 /* RoundSettingsView.swift in Sources */, FF5DA1932BB9279B00A33061 /* RoundSettingsView.swift in Sources */,
FFBE62052CE9DA0900815D33 /* MatchViewStyle.swift in Sources */,
FFE2D2E22C231BEE00D0C7BE /* SupportButtonView.swift in Sources */, FFE2D2E22C231BEE00D0C7BE /* SupportButtonView.swift in Sources */,
FFB1C98B2C10255100B154A7 /* TournamentBroadcastRowView.swift in Sources */, FFB1C98B2C10255100B154A7 /* TournamentBroadcastRowView.swift in Sources */,
FF025ADF2BD0CE0A00A86CF8 /* TeamWeightView.swift in Sources */, FF025ADF2BD0CE0A00A86CF8 /* TeamWeightView.swift in Sources */,
@ -2605,6 +2611,7 @@
FF4CBF5A2C996C0600151637 /* TournamentClubSettingsView.swift in Sources */, FF4CBF5A2C996C0600151637 /* TournamentClubSettingsView.swift in Sources */,
FF4CBF5B2C996C0600151637 /* GroupStageTeamView.swift in Sources */, FF4CBF5B2C996C0600151637 /* GroupStageTeamView.swift in Sources */,
FF4CBF5C2C996C0600151637 /* RoundSettingsView.swift in Sources */, FF4CBF5C2C996C0600151637 /* RoundSettingsView.swift in Sources */,
FFBE62072CE9DA0900815D33 /* MatchViewStyle.swift in Sources */,
FF4CBF5D2C996C0600151637 /* SupportButtonView.swift in Sources */, FF4CBF5D2C996C0600151637 /* SupportButtonView.swift in Sources */,
FF4CBF5E2C996C0600151637 /* TournamentBroadcastRowView.swift in Sources */, FF4CBF5E2C996C0600151637 /* TournamentBroadcastRowView.swift in Sources */,
FF4CBF5F2C996C0600151637 /* TeamWeightView.swift in Sources */, FF4CBF5F2C996C0600151637 /* TeamWeightView.swift in Sources */,
@ -2868,6 +2875,7 @@
FF70FAD92C90584900129CC2 /* TournamentClubSettingsView.swift in Sources */, FF70FAD92C90584900129CC2 /* TournamentClubSettingsView.swift in Sources */,
FF70FADA2C90584900129CC2 /* GroupStageTeamView.swift in Sources */, FF70FADA2C90584900129CC2 /* GroupStageTeamView.swift in Sources */,
FF70FADB2C90584900129CC2 /* RoundSettingsView.swift in Sources */, FF70FADB2C90584900129CC2 /* RoundSettingsView.swift in Sources */,
FFBE62062CE9DA0900815D33 /* MatchViewStyle.swift in Sources */,
FF70FADC2C90584900129CC2 /* SupportButtonView.swift in Sources */, FF70FADC2C90584900129CC2 /* SupportButtonView.swift in Sources */,
FF70FADD2C90584900129CC2 /* TournamentBroadcastRowView.swift in Sources */, FF70FADD2C90584900129CC2 /* TournamentBroadcastRowView.swift in Sources */,
FF70FADE2C90584900129CC2 /* TeamWeightView.swift in Sources */, FF70FADE2C90584900129CC2 /* TeamWeightView.swift in Sources */,

@ -975,19 +975,18 @@ defer {
return confirmed == false && startDate.timeIntervalSinceNow < 0 return confirmed == false && startDate.timeIntervalSinceNow < 0
} }
func expectedFormattedStartDate(updatedField: Int?) -> String { func expectedFormattedStartDate(canBePlayedInSpecifiedCourt: Bool, availableCourts: [Int], estimatedStartDate: CourtIndexAndDate?, updatedField: Int?) -> String {
guard let startDate else { return "" } guard let startDate else { return "" }
guard hasEnded() == false, isRunning() == false else { return "" } guard hasEnded() == false, isRunning() == false else { return "" }
let depthReadiness = depthReadiness() let depthReadiness = depthReadiness()
if depthReadiness == 0 { if depthReadiness == 0 {
let availableCourts = availableCourts() if canBePlayedInSpecifiedCourt {
if canBePlayedInSpecifiedCourt() {
return "possible tout de suite" return "possible tout de suite"
} else if let updatedField, availableCourts.contains(updatedField) { } else if let updatedField, availableCourts.contains(updatedField) {
return "possible tout de suite \(courtName(for: updatedField))" return "possible tout de suite \(courtName(for: updatedField))"
} else if let first = availableCourts.first { } else if let first = availableCourts.first {
return "possible tout de suite \(courtName(for: first))" return "possible tout de suite \(courtName(for: first))"
} else if let estimatedStartDate = estimatedStartDate() { } else if let estimatedStartDate {
return "dans ~" + estimatedStartDate.1.timeElapsedString() + " " + courtName(for: estimatedStartDate.0) return "dans ~" + estimatedStartDate.1.timeElapsedString() + " " + courtName(for: estimatedStartDate.0)
} }
return "était prévu à " + startDate.formattedAsHourMinute() return "était prévu à " + startDate.formattedAsHourMinute()
@ -1014,10 +1013,8 @@ defer {
typealias CourtIndexAndDate = (courtIndex: Int, startDate: Date) typealias CourtIndexAndDate = (courtIndex: Int, startDate: Date)
func nextCourtsAvailable() -> [CourtIndexAndDate] { func nextCourtsAvailable(availableCourts: [Int], runningMatches: [Match]) -> [CourtIndexAndDate] {
guard let tournament = currentTournament() else { return [] } guard let tournament = currentTournament() else { return [] }
let availableCourts = availableCourts()
let runningMatches = Tournament.runningMatches(tournament.allMatches())
let startDate = Date().withoutSeconds() let startDate = Date().withoutSeconds()
if runningMatches.isEmpty { if runningMatches.isEmpty {
return availableCourts.map { return availableCourts.map {
@ -1041,10 +1038,10 @@ defer {
return dates return dates
} }
func estimatedStartDate() -> CourtIndexAndDate? { func estimatedStartDate(availableCourts: [Int], runningMatches: [Match]) -> CourtIndexAndDate? {
guard isReady() else { return nil } guard isReady() else { return nil }
guard let tournament = currentTournament() else { return nil } guard let tournament = currentTournament() else { return nil }
let availableCourts = nextCourtsAvailable() let availableCourts = nextCourtsAvailable(availableCourts: availableCourts, runningMatches: runningMatches)
return availableCourts.first(where: { (courtIndex, startDate) in return availableCourts.first(where: { (courtIndex, startDate) in
let endDate = startDate.addingTimeInterval(TimeInterval(matchFormat.getEstimatedDuration(tournament.additionalEstimationDuration)) * 60) let endDate = startDate.addingTimeInterval(TimeInterval(matchFormat.getEstimatedDuration(tournament.additionalEstimationDuration)) * 60)
if tournament.courtUnavailable(courtIndex: courtIndex, from: startDate, to: endDate) == false { if tournament.courtUnavailable(courtIndex: courtIndex, from: startDate, to: endDate) == false {

@ -188,6 +188,10 @@ final class PlayerRegistration: ModelObject, Storable {
return self.tournamentStore.teamRegistrations.findById(teamRegistration) return self.tournamentStore.teamRegistrations.findById(teamRegistration)
} }
func isHere() -> Bool {
hasArrived
}
func hasPaid() -> Bool { func hasPaid() -> Bool {
paymentType != nil paymentType != nil
} }

@ -26,32 +26,6 @@ enum SummoningDisplayContext {
case menu case menu
} }
enum MatchViewStyle {
case standardStyle // vue normal
case sectionedStandardStyle // vue normal avec des sections indiquant déjà la manche
case feedStyle // vue programmation
case plainStyle // vue detail
case tournamentResultStyle //vue resultat tournoi
case followUpStyle // vue normal
func displayRestingTime() -> Bool {
switch self {
case .standardStyle:
return false
case .sectionedStandardStyle:
return false
case .feedStyle:
return false
case .plainStyle:
return false
case .tournamentResultStyle:
return false
case .followUpStyle:
return true
}
}
}
struct DeviceHelper { struct DeviceHelper {
static func isBigScreen() -> Bool { static func isBigScreen() -> Bool {
switch UIDevice.current.userInterfaceIdiom { switch UIDevice.current.userInterfaceIdiom {

@ -0,0 +1,51 @@
//
// MatchViewStyle.swift
// PadelClub
//
// Created by razmig on 17/11/2024.
//
import SwiftUI
enum MatchViewStyle {
case standardStyle // vue normal
case sectionedStandardStyle // vue normal avec des sections indiquant déjà la manche
case feedStyle // vue programmation
case plainStyle // vue detail
//case tournamentResultStyle //vue resultat tournoi
case followUpStyle // vue normal
func displayRestingTime() -> Bool {
switch self {
case .standardStyle:
return false
case .sectionedStandardStyle:
return false
case .feedStyle:
return false
case .plainStyle:
return false
// case .tournamentResultStyle:
// return false
case .followUpStyle:
return true
}
}
}
struct MatchViewStyleKey: EnvironmentKey {
static let defaultValue: MatchViewStyle = .standardStyle
}
extension EnvironmentValues {
var matchViewStyle: MatchViewStyle {
get { self[MatchViewStyleKey.self] }
set { self[MatchViewStyleKey.self] = newValue }
}
}
extension View {
func matchViewStyle(_ style: MatchViewStyle) -> some View {
environment(\.matchViewStyle, style)
}
}

@ -10,10 +10,10 @@ import SwiftUI
struct MatchListView: View { struct MatchListView: View {
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@Environment(\.matchViewStyle) private var matchViewStyle
let section: String let section: String
let matches: [Match]? let matches: [Match]?
var matchViewStyle: MatchViewStyle = .standardStyle
var hideWhenEmpty: Bool = false var hideWhenEmpty: Bool = false
@State var isExpanded: Bool = true @State var isExpanded: Bool = true
@ -32,7 +32,7 @@ struct MatchListView: View {
DisclosureGroup(isExpanded: $isExpanded) { DisclosureGroup(isExpanded: $isExpanded) {
if let matches { if let matches {
ForEach(matches) { match in ForEach(matches) { match in
MatchRowView(match: match, matchViewStyle: matchViewStyle) MatchRowView(match: match)
.listRowInsets(EdgeInsets(top: 0, leading: -2, bottom: 0, trailing: 8)) .listRowInsets(EdgeInsets(top: 0, leading: -2, bottom: 0, trailing: 8))
} }
} }

@ -146,23 +146,25 @@ struct GroupStagesView: View {
let runningMatches = Tournament.runningMatches(allMatches) let runningMatches = Tournament.runningMatches(allMatches)
Section { Section {
MatchListView(section: "en cours", matches: runningMatches, matchViewStyle: .standardStyle, isExpanded: false) MatchListView(section: "en cours", matches: runningMatches, isExpanded: false)
} }
Section { Section {
MatchListView(section: "prêt à démarrer", matches: Tournament.availableToStart(allMatches, in: runningMatches), matchViewStyle: .standardStyle, isExpanded: false) MatchListView(section: "prêt à démarrer", matches: Tournament.availableToStart(allMatches, in: runningMatches), isExpanded: false)
} }
Section { Section {
MatchListView(section: "à lancer", matches: Tournament.readyMatches(allMatches), matchViewStyle: .standardStyle, isExpanded: false) MatchListView(section: "à lancer", matches: Tournament.readyMatches(allMatches), isExpanded: false)
} }
Section { Section {
MatchListView(section: "terminés", matches: finishedMatches, matchViewStyle: .standardStyle, isExpanded: false) MatchListView(section: "terminés", matches: finishedMatches, isExpanded: false)
} }
} }
.matchViewStyle(.standardStyle)
.navigationTitle("Toutes les poules") .navigationTitle("Toutes les poules")
case .groupStage(let groupStage): case .groupStage(let groupStage):
GroupStageView(groupStage: groupStage).id(groupStage.id) GroupStageView(groupStage: groupStage).id(groupStage.id)

@ -45,7 +45,8 @@ struct LoserBracketFromGroupStageView: View {
ForEach(displayableMatches) { match in ForEach(displayableMatches) { match in
Section { Section {
MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle) MatchRowView(match: match)
.matchViewStyle(.sectionedStandardStyle)
.environment(\.isEditingTournamentSeed, $isEditingLoserBracketGroupStage) .environment(\.isEditingTournamentSeed, $isEditingLoserBracketGroupStage)
} header: { } header: {
let tournamentTeamCount = tournament.teamCount let tournamentTeamCount = tournament.teamCount

@ -26,13 +26,7 @@ struct MatchDateView: View {
self.isReady = match.isReady() self.isReady = match.isReady()
self.hasWalkoutTeam = match.hasWalkoutTeam() self.hasWalkoutTeam = match.hasWalkoutTeam()
self.hasEnded = match.hasEnded() self.hasEnded = match.hasEnded()
if updatedField == nil, match.canBePlayedInSpecifiedCourt() { self.updatedField = updatedField
self.updatedField = match.courtIndex
} else if let updatedField {
self.updatedField = updatedField
} else {
self.updatedField = match.availableCourts().first
}
} }
var currentDate: Date { var currentDate: Date {

@ -8,26 +8,29 @@
import SwiftUI import SwiftUI
struct PlayerBlockView: View { struct PlayerBlockView: View {
@Environment(\.matchViewStyle) private var matchViewStyle
@State var match: Match @State var match: Match
let teamPosition: TeamPosition let teamPosition: TeamPosition
let team: TeamRegistration? let team: TeamRegistration?
let color: Color
let width: CGFloat
let teamScore: TeamScore? let teamScore: TeamScore?
let isWalkOut: Bool let isWalkOut: Bool
let displayRestingTime: Bool
init(match: Match, teamPosition: TeamPosition, color: Color, width: CGFloat, displayRestingTime: Bool) { var displayRestingTime: Bool {
matchViewStyle.displayRestingTime()
}
var width: CGFloat {
matchViewStyle == .plainStyle ? 1 : 2
}
init(match: Match, teamPosition: TeamPosition) {
self.match = match self.match = match
self.teamPosition = teamPosition self.teamPosition = teamPosition
let theTeam = match.team(teamPosition) let theTeam = match.team(teamPosition)
self.team = theTeam self.team = theTeam
self.color = color
self.width = width
let theTeamScore = match.teamScore(ofTeam: theTeam) let theTeamScore = match.teamScore(ofTeam: theTeam)
self.teamScore = theTeamScore self.teamScore = theTeamScore
self.isWalkOut = theTeamScore?.isWalkOut() == true self.isWalkOut = theTeamScore?.isWalkOut() == true
self.displayRestingTime = displayRestingTime
} }
var names: [String]? { var names: [String]? {
@ -81,8 +84,8 @@ struct PlayerBlockView: View {
} }
ForEach(team.players()) { player in ForEach(team.players()) { player in
Text(player.playerLabel()).lineLimit(1) Text(player.playerLabel()).lineLimit(1)
.italic(player.hasArrived == false) .italic(player.isHere() == false)
.foregroundStyle(player.hasArrived == false ? .secondary : .primary) .foregroundStyle(player.isHere() == false ? .secondary : .primary)
} }
} else { } else {
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
@ -122,7 +125,7 @@ struct PlayerBlockView: View {
if width == 1 { if width == 1 {
Divider() Divider()
} else { } else {
Divider().frame(width: width).overlay(color) Divider().frame(width: width).overlay(Color(white: 0.9))
} }
Text(string) Text(string)
.font(.title3) .font(.title3)

@ -14,7 +14,7 @@ struct MatchDetailView: View {
@EnvironmentObject var networkMonitor: NetworkMonitor @EnvironmentObject var networkMonitor: NetworkMonitor
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
let matchViewStyle: MatchViewStyle @Environment(\.matchViewStyle) private var matchViewStyle
@State private var showLiveScore: Bool = false @State private var showLiveScore: Bool = false
@State private var editScore: Bool = false @State private var editScore: Bool = false
@ -54,9 +54,8 @@ struct MatchDetailView: View {
var match: Match var match: Match
init(match: Match, matchViewStyle: MatchViewStyle = .standardStyle, updatedField: Int? = nil) { init(match: Match, updatedField: Int? = nil) {
self.match = match self.match = match
self.matchViewStyle = matchViewStyle
if match.hasStarted() == false && (match.startDate == nil || match.courtIndex == nil) { if match.hasStarted() == false && (match.startDate == nil || match.courtIndex == nil) {
_isEditing = State(wrappedValue: true) _isEditing = State(wrappedValue: true)
@ -89,7 +88,8 @@ struct MatchDetailView: View {
} }
Section { Section {
MatchSummaryView(match: match, matchViewStyle: .plainStyle) MatchSummaryView(match: match)
.matchViewStyle(.plainStyle)
} footer: { } footer: {
if match.isEmpty() == false { if match.isEmpty() == false {
HStack { HStack {

@ -11,8 +11,8 @@ import LeStorage
struct MatchRowView: View { struct MatchRowView: View {
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@Environment(\.matchViewStyle) private var matchViewStyle
@State var match: Match @State var match: Match
let matchViewStyle: MatchViewStyle
var title: String? = nil var title: String? = nil
var updatedField: Int? = nil var updatedField: Int? = nil
@ -60,9 +60,9 @@ struct MatchRowView: View {
// }) // })
NavigationLink { NavigationLink {
MatchDetailView(match: match, matchViewStyle: matchViewStyle, updatedField: updatedField) MatchDetailView(match: match, updatedField: updatedField)
} label: { } label: {
MatchSummaryView(match: match, matchViewStyle: matchViewStyle, title: title, updatedField: updatedField) MatchSummaryView(match: match, title: title, updatedField: updatedField)
.contextMenu { .contextMenu {
Section { Section {
ForEach(match.teams().flatMap({ $0.players() })) { player in ForEach(match.teams().flatMap({ $0.players() })) { player in

@ -10,30 +10,25 @@ import SwiftUI
struct MatchSummaryView: View { struct MatchSummaryView: View {
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@State var match: Match @State var match: Match
let matchViewStyle: MatchViewStyle @Environment(\.matchViewStyle) private var matchViewStyle
let matchTitle: String let matchTitle: String
let roundTitle: String? let roundTitle: String?
let courtName: String? let courtName: String?
let spacing: CGFloat
let padding: CGFloat
let color: Color
let width: CGFloat
let updatedField: Int? let updatedField: Int?
let estimatedStartDate: Match.CourtIndexAndDate? let estimatedStartDate: Match.CourtIndexAndDate?
let availableCourts: [Int]
let canBePlayedInSpecifiedCourt: Bool
init(match: Match, matchViewStyle: MatchViewStyle, title: String? = nil, updatedField: Int? = nil) { init(match: Match, title: String? = nil, updatedField: Int? = nil) {
self.match = match self.match = match
self.matchViewStyle = matchViewStyle
self.padding = matchViewStyle == .plainStyle ? 0 : 8
self.spacing = matchViewStyle == .plainStyle ? 8 : 0
self.width = matchViewStyle == .plainStyle ? 1 : 2
self.color = Color(white: 0.9)
self.updatedField = updatedField self.updatedField = updatedField
let currentAvailableCourts = match.availableCourts()
self.availableCourts = currentAvailableCourts
if let groupStage = match.groupStageObject { if let groupStage = match.groupStageObject {
self.roundTitle = groupStage.groupStageTitle(.title) self.roundTitle = groupStage.groupStageTitle(.title)
} else if let round = match.roundObject { } else if let round = match.roundObject {
self.roundTitle = round.roundTitle(matchViewStyle == .feedStyle ? .wide : .short) self.roundTitle = round.roundTitle(.short)
} else { } else {
self.roundTitle = nil self.roundTitle = nil
} }
@ -45,8 +40,21 @@ struct MatchSummaryView: View {
} else { } else {
self.courtName = nil self.courtName = nil
} }
let runningMatches = Tournament.runningMatches(match.currentTournament()?.allMatches() ?? [])
self.estimatedStartDate = match.estimatedStartDate(availableCourts: currentAvailableCourts, runningMatches: runningMatches)
self.canBePlayedInSpecifiedCourt = match.canBePlayedInSpecifiedCourt()
}
var spacing: CGFloat {
matchViewStyle == .plainStyle ? 8 : 0
}
self.estimatedStartDate = match.estimatedStartDate() var padding: CGFloat {
matchViewStyle == .plainStyle ? 0 : 8
}
var width: CGFloat {
matchViewStyle == .plainStyle ? 1 : 2
} }
var body: some View { var body: some View {
@ -76,33 +84,35 @@ struct MatchSummaryView: View {
HStack(spacing: 0) { HStack(spacing: 0) {
VStack(alignment: .leading, spacing: spacing) { VStack(alignment: .leading, spacing: spacing) {
PlayerBlockView(match: match, teamPosition: .one, color: color, width: width, displayRestingTime: matchViewStyle.displayRestingTime()) PlayerBlockView(match: match, teamPosition: .one)
.padding(padding) .padding(padding)
if width == 1 { if width == 1 {
Divider() Divider()
} else { } else {
Divider().frame(height: width).overlay(color) Divider().frame(height: width).overlay(Color(white: 0.9))
} }
PlayerBlockView(match: match, teamPosition: .two, color: color, width: width, displayRestingTime: matchViewStyle.displayRestingTime()) PlayerBlockView(match: match, teamPosition: .two)
.padding(padding) .padding(padding)
} }
} }
.overlay { .overlay {
if matchViewStyle != .plainStyle { if matchViewStyle != .plainStyle {
RoundedRectangle(cornerRadius: 8) RoundedRectangle(cornerRadius: 8)
.stroke(color, lineWidth: 2) .stroke(Color(white: 0.9), lineWidth: 2)
} }
} }
if matchViewStyle != .plainStyle { if matchViewStyle != .plainStyle {
HStack { HStack {
if match.expectedToBeRunning() { if matchViewStyle == .followUpStyle {
Text(match.expectedFormattedStartDate(updatedField: updatedField)) if match.expectedToBeRunning() {
.font(.footnote) Text(match.expectedFormattedStartDate(canBePlayedInSpecifiedCourt: canBePlayedInSpecifiedCourt, availableCourts: availableCourts, estimatedStartDate: estimatedStartDate, updatedField: updatedField))
.foregroundStyle(.secondary) .font(.footnote)
.foregroundStyle(.secondary)
}
} }
Spacer() Spacer()
MatchDateView(match: match, showPrefix: matchViewStyle == .tournamentResultStyle, updatedField: possibleCourtIndex) MatchDateView(match: match, showPrefix: false, updatedField: possibleCourtIndex)
} }
} }
} }
@ -111,8 +121,7 @@ struct MatchSummaryView: View {
} }
var possibleCourtIndex: Int? { var possibleCourtIndex: Int? {
let availableCourts = match.availableCourts() if canBePlayedInSpecifiedCourt {
if match.canBePlayedInSpecifiedCourt() {
return nil return nil
} else if let updatedField, availableCourts.contains(updatedField) { } else if let updatedField, availableCourts.contains(updatedField) {
return updatedField return updatedField
@ -133,7 +142,7 @@ struct MatchSummaryView: View {
return false return false
} }
if match.canBePlayedInSpecifiedCourt() { if canBePlayedInSpecifiedCourt {
return false return false
} }

@ -32,7 +32,8 @@ struct OngoingView: View {
ForEach(filteredMatches) { match in ForEach(filteredMatches) { match in
let tournament = match.currentTournament() let tournament = match.currentTournament()
Section { Section {
MatchRowView(match: match, matchViewStyle: .standardStyle) MatchRowView(match: match)
.matchViewStyle(.followUpStyle)
} header: { } header: {
if let tournament { if let tournament {
HStack { HStack {

@ -112,7 +112,8 @@ struct PlanningByCourtView: View {
ForEach(_sortedMatches.indices, id: \.self) { index in ForEach(_sortedMatches.indices, id: \.self) { index in
let match = _sortedMatches[index] let match = _sortedMatches[index]
Section { Section {
MatchRowView(match: match, matchViewStyle: .feedStyle) MatchRowView(match: match)
.matchViewStyle(.feedStyle)
} header: { } header: {
if let startDate = match.startDate { if let startDate = match.startDate {
if index > 0 { if index > 0 {

@ -158,7 +158,9 @@ struct PlanningView: View {
DisclosureGroup { DisclosureGroup {
ForEach(_matches) { match in ForEach(_matches) { match in
NavigationLink { NavigationLink {
MatchDetailView(match: match, matchViewStyle: .sectionedStandardStyle) MatchDetailView(match: match)
.matchViewStyle(.sectionedStandardStyle)
} label: { } label: {
LabeledContent { LabeledContent {
if let courtName = match.courtName() { if let courtName = match.courtName() {

@ -40,7 +40,8 @@ struct LoserRoundView: View {
if matches.isEmpty == false { if matches.isEmpty == false {
Section { Section {
ForEach(matches) { match in ForEach(matches) { match in
MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle) MatchRowView(match: match)
.matchViewStyle(.sectionedStandardStyle)
.overlay { .overlay {
if match.disabled && isEditingTournamentSeed.wrappedValue == true { if match.disabled && isEditingTournamentSeed.wrappedValue == true {
Image(systemName: "xmark") Image(systemName: "xmark")

@ -215,7 +215,8 @@ struct RoundView: View {
ForEach(displayableMatches) { match in ForEach(displayableMatches) { match in
let matchTitle = match.matchTitle(.short, inMatches: displayableMatches) let matchTitle = match.matchTitle(.short, inMatches: displayableMatches)
Section { Section {
MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle, title: matchTitle) MatchRowView(match: match, title: matchTitle)
.matchViewStyle(.sectionedStandardStyle)
} header: { } header: {
HStack { HStack {
Text(upperRound.round.roundTitle(.wide)) Text(upperRound.round.roundTitle(.wide))

@ -198,7 +198,8 @@ struct FollowUpMatchView: View {
ForEach(sortedMatches) { match in ForEach(sortedMatches) { match in
let tournament = match.currentTournament() let tournament = match.currentTournament()
Section { Section {
MatchRowView(match: match, matchViewStyle: .followUpStyle, updatedField: selectedCourt) MatchRowView(match: match, updatedField: selectedCourt)
.matchViewStyle(.followUpStyle)
} header: { } header: {
if let tournament { if let tournament {
HStack { HStack {

@ -62,7 +62,8 @@ struct TeamRestingView: View {
case .restingTime: case .restingTime:
if sortedMatches.isEmpty == false { if sortedMatches.isEmpty == false {
ForEach(sortedMatches) { match in ForEach(sortedMatches) { match in
MatchRowView(match: match, matchViewStyle: .followUpStyle, updatedField: selectedCourt) MatchRowView(match: match, updatedField: selectedCourt)
.matchViewStyle(.followUpStyle)
} }
} else { } else {
ContentUnavailableView("Aucun match à venir", systemImage: "xmark.circle", description: Text(contentUnavailableDescriptionLabel())) ContentUnavailableView("Aucun match à venir", systemImage: "xmark.circle", description: Text(contentUnavailableDescriptionLabel()))

Loading…
Cancel
Save