Fix memory issue when going in federal players search

sync2
Laurent 8 months ago
parent 2b856fcde4
commit 6334648efd
  1. 380
      PadelClub/Views/Tournament/Screen/AddTeamView.swift

@ -372,20 +372,20 @@ struct AddTeamView: View {
self.tournamentStore?.teamRegistrations.addOrUpdate(instance: team) self.tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
self.tournamentStore?.playerRegistrations.addOrUpdate(contentOfs: players) self.tournamentStore?.playerRegistrations.addOrUpdate(contentOfs: players)
pasteString = nil pasteString = nil
editableTextField = "" editableTextField = ""
createdPlayers.removeAll() createdPlayers.removeAll()
createdPlayerIds.removeAll() createdPlayerIds.removeAll()
if team.players().count > 1 { if team.players().count > 1 {
dismiss() dismiss()
} else { } else {
editedTeam = team editedTeam = team
team.unsortedPlayers().forEach { player in team.unsortedPlayers().forEach { player in
createdPlayers.insert(player) createdPlayers.insert(player)
createdPlayerIds.insert(player.id) createdPlayerIds.insert(player.id)
} }
} }
} }
private func _updateTeam(checkDuplicates: Bool) { private func _updateTeam(checkDuplicates: Bool) {
@ -421,22 +421,14 @@ struct AddTeamView: View {
return max(boundingRect.height + 20, 40) // Add some padding and set a minimum height return max(boundingRect.height + 20, 40) // Add some padding and set a minimum height
} }
struct PasteStringSection: View { @ViewBuilder
private func _buildingTeamView() -> some View {
let pasteString: String?
@Binding var editableTextField: String
@Binding var textHeight: CGFloat
@FocusState var focusedField: AddTeamView.FocusField?
var handlePasteString: (String) -> Void
@Binding var displayWarningNotEnoughCharacter: Bool
var body: some View {
if let pasteString { if let pasteString {
Section { Section {
TextEditor(text: $editableTextField) TextEditor(text: $editableTextField)
.frame(height: textHeight) .frame(height: textHeight)
.onChange(of: editableTextField) { .onChange(of: editableTextField) {
textHeight = AddTeamView._calculateHeight(text: pasteString) textHeight = Self._calculateHeight(text: pasteString)
} }
.focused($focusedField, equals: .pasteField) .focused($focusedField, equals: .pasteField)
.toolbar { .toolbar {
@ -468,104 +460,121 @@ struct AddTeamView: View {
FooterButtonView("effacer le texte") { FooterButtonView("effacer le texte") {
self.focusedField = nil self.focusedField = nil
self.editableTextField = "" self.editableTextField = ""
self.handlePasteString("") self.pasteString = nil
} }
} }
} }
} }
}
}
Section {
ForEach(createdPlayerIds.sorted(), id: \.self) { id in
if let p = createdPlayers.first(where: { $0.id == id }) {
VStack(alignment: .leading, spacing: 0) {
if let player = unsortedPlayers.first(where: { ($0.licenceId == p.licenceId && $0.licenceId != nil) }), editedTeam?.includes(player: player) == false {
Text("Déjà inscrit !").foregroundStyle(.logoRed).bold()
}
if tournament.isPlayerAgeInadequate(player: p) {
Text("Âge invalide !").foregroundStyle(.logoRed).bold()
}
if tournament.isPlayerRankInadequate(player: p) {
Text("Trop bien classé !").foregroundStyle(.logoRed).bold()
}
PlayerView(player: p).tag(p.id)
.environment(tournament)
}
}
if let p = fetchPlayers.first(where: { $0.license == id }) {
VStack(alignment: .leading, spacing: 0) {
if let pasteString, pasteString.isEmpty == false, unsortedPlayers.first(where: { $0.licenceId == p.license }) != nil {
Text("Déjà inscrit !").foregroundStyle(.logoRed).bold()
}
if tournament.isPlayerAgeInadequate(player: p) {
Text("Âge invalide !").foregroundStyle(.logoRed).bold()
}
if tournament.isPlayerRankInadequate(player: p) {
Text("Trop bien classé !").foregroundStyle(.logoRed).bold()
}
ImportedPlayerView(player: p).tag(p.license!)
}
}
}
if editedTeam == nil {
if createdPlayerIds.isEmpty {
RowButtonView("Bloquer une place") {
_createTeam(checkDuplicates: false, checkHomonym: false)
}
} else {
RowButtonView("Ajouter l'équipe") {
_createTeam(checkDuplicates: true, checkHomonym: true)
}
}
} else {
RowButtonView("Confirmer") {
_updateTeam(checkDuplicates: false)
dismiss()
}
}
} header: {
let _currentSelection = _currentSelection()
let selectedSortedTeams = tournament.selectedSortedTeams()
let rank = _currentSelection.map {
$0.computedRank
}.reduce(0, +)
let teamIndex = selectedSortedTeams.firstIndex(where: { $0.weight >= rank }) ?? selectedSortedTeams.count
if _currentSelection.isEmpty == false, tournament.hideWeight() == false, rank > 0 {
HStack(spacing: 16.0) {
VStack(alignment: .leading, spacing: 0) {
Text("Rang").font(.caption)
Text("#" + (teamIndex + 1).formatted())
}
@ViewBuilder VStack(alignment: .leading, spacing: 0) {
private func _buildingTeamView() -> some View { Text("Poids").font(.caption)
Text(rank.formatted())
PasteStringSection( }
pasteString: pasteString, Spacer()
editableTextField: $editableTextField, VStack(alignment: .trailing, spacing: 0) {
textHeight: $textHeight, Text("").font(.caption)
focusedField: _focusedField, Text(tournament.cutLabel(index: teamIndex, teamCount: selectedSortedTeams.count))
handlePasteString: handlePasteString, }
displayWarningNotEnoughCharacter: $displayWarningNotEnoughCharacter }
) // } else {
// Text("Préparation de l'équipe")
}
}
TeamSelectionSection(
createdPlayerIds: createdPlayerIds,
createdPlayers: createdPlayers,
unsortedPlayers: unsortedPlayers,
fetchPlayers: fetchPlayers,
editedTeam: editedTeam,
pasteString: pasteString,
tournament: tournament,
_createTeam: _createTeam,
_updateTeam: _updateTeam,
dismiss: dismiss,
_currentSelection: _currentSelection
)
if let pasteString, pasteString.isEmpty == false { if let pasteString, pasteString.isEmpty == false {
let sortedPlayers = _searchFilteredPlayers() let sortedPlayers = _searchFilteredPlayers()
if sortedPlayers.isEmpty { if sortedPlayers.isEmpty {
ContentUnavailableView { ContentUnavailableView {
Label("Aucun résultat", systemImage: "person.2.slash") Label("Aucun résultat", systemImage: "person.2.slash")
} description: { } description: {
Text("Aucun joueur classé n'a été trouvé dans ce message. Attention, si un joueur n'a pas joué de tournoi dans les 12 derniers, Padel Club ne pourra pas le trouver.") Text("Aucun joueur classé n'a été trouvé dans ce message. Attention, si un joueur n'a pas joué de tournoi dans les 12 derniers, Padel Club ne pourra pas le trouver.")
} actions: { } actions: {
RowButtonView("Créer un joueur non classé") { RowButtonView("Créer un joueur non classé") {
selectionSearchField = pasteString selectionSearchField = pasteString
} }
RowButtonView("Chercher dans la base") { RowButtonView("Chercher dans la base") {
presentPlayerSearch = true presentPlayerSearch = true
} }
RowButtonView("Effacer cette recherche") { RowButtonView("Effacer cette recherche") {
self.pasteString = nil self.pasteString = nil
self.editableTextField = "" self.editableTextField = ""
}
} }
}
} else {
_listOfPlayers(searchFilteredPlayers: sortedPlayers, pasteString: pasteString)
}
} else { } else {
_listOfPlayers(searchFilteredPlayers: sortedPlayers, pasteString: pasteString) _managementView()
} }
} else {
_managementView()
}
} }
//
// if let pasteString, pasteString.isEmpty == false {
// let sortedPlayers = _searchFilteredPlayers()
//
// if sortedPlayers.isEmpty {
// ContentUnavailableView {
// Label("Aucun résultat", systemImage: "person.2.slash")
// } description: {
// Text("Aucun joueur classé n'a été trouvé dans ce message. Attention, si un joueur n'a pas joué de tournoi dans les 12 derniers, Padel Club ne pourra pas le trouver.")
// } actions: {
// RowButtonView("Créer un joueur non classé") {
// selectionSearchField = pasteString
// }
//
// RowButtonView("Chercher dans la base") {
// presentPlayerSearch = true
// }
//
// RowButtonView("Effacer cette recherche") {
// self.pasteString = nil
// self.editableTextField = ""
// }
// }
//
// } else {
// _listOfPlayers(searchFilteredPlayers: sortedPlayers, pasteString: pasteString)
// }
// } else {
// _managementView()
// }
// }
@MainActor @MainActor
func hitForSearch(_ ip: ImportedPlayer, _ pasteString: String?) -> Int { func hitForSearch(_ ip: ImportedPlayer, _ pasteString: String?) -> Int {
guard let pasteString else { return 0 } guard let pasteString else { return 0 }
@ -642,165 +651,6 @@ struct AddTeamView: View {
} }
} }
struct TeamSelectionSection: View {
let createdPlayerIds: Set<String>
let createdPlayers: Set<PlayerRegistration>
let unsortedPlayers: [PlayerRegistration]
let fetchPlayers: FetchedResults<ImportedPlayer>
let editedTeam: TeamRegistration?
let pasteString: String?
let tournament: Tournament
let _createTeam: (Bool, Bool) -> Void
let _updateTeam: (Bool) -> Void
let dismiss: DismissAction
let _currentSelection: () -> Set<PlayerRegistration>
var body: some View {
Section {
PlayerListView(createdPlayerIds: createdPlayerIds,
createdPlayers: createdPlayers,
unsortedPlayers: unsortedPlayers,
fetchPlayers: fetchPlayers,
editedTeam: editedTeam,
pasteString: pasteString,
tournament: tournament)
ActionButton(editedTeam: editedTeam,
createdPlayerIds: createdPlayerIds,
_createTeam: _createTeam,
_updateTeam: _updateTeam,
dismiss: dismiss)
} header: {
TeamHeader(tournament: tournament,
_currentSelection: _currentSelection)
}
}
}
struct PlayerListView: View {
let createdPlayerIds: Set<String>
let createdPlayers: Set<PlayerRegistration>
let unsortedPlayers: [PlayerRegistration]
let fetchPlayers: FetchedResults<ImportedPlayer>
let editedTeam: TeamRegistration?
let pasteString: String?
let tournament: Tournament
var body: some View {
ForEach(createdPlayerIds.sorted(), id: \.self) { id in
if let p = createdPlayers.first(where: { $0.id == id }) {
CreatedPlayerView(player: p, unsortedPlayers: unsortedPlayers, editedTeam: editedTeam, tournament: tournament)
}
if let p = fetchPlayers.first(where: { $0.license == id }) {
FetchedPlayerView(player: p, unsortedPlayers: unsortedPlayers, pasteString: pasteString, tournament: tournament)
}
}
}
}
struct CreatedPlayerView: View {
let player: PlayerRegistration
let unsortedPlayers: [PlayerRegistration]
let editedTeam: TeamRegistration?
let tournament: Tournament
var body: some View {
VStack(alignment: .leading, spacing: 0) {
if let existingPlayer = unsortedPlayers.first(where: { ($0.licenceId == player.licenceId && $0.licenceId != nil) }), editedTeam?.includes(player: existingPlayer) == false {
Text("Déjà inscrit !").foregroundStyle(.logoRed).bold()
}
if tournament.isPlayerAgeInadequate(player: player) {
Text("Âge invalide !").foregroundStyle(.logoRed).bold()
}
if tournament.isPlayerRankInadequate(player: player) {
Text("Trop bien classé !").foregroundStyle(.logoRed).bold()
}
PlayerView(player: player).tag(player.id)
.environment(tournament)
}
}
}
struct FetchedPlayerView: View {
let player: ImportedPlayer
let unsortedPlayers: [PlayerRegistration]
let pasteString: String?
let tournament: Tournament
var body: some View {
VStack(alignment: .leading, spacing: 0) {
if let pasteString, pasteString.isEmpty == false, unsortedPlayers.first(where: { $0.licenceId == player.license }) != nil {
Text("Déjà inscrit !").foregroundStyle(.logoRed).bold()
}
if tournament.isPlayerAgeInadequate(player: player) {
Text("Âge invalide !").foregroundStyle(.logoRed).bold()
}
if tournament.isPlayerRankInadequate(player: player) {
Text("Trop bien classé !").foregroundStyle(.logoRed).bold()
}
ImportedPlayerView(player: player).tag(player.license!)
}
}
}
struct ActionButton: View {
let editedTeam: TeamRegistration?
let createdPlayerIds: Set<String>
let _createTeam: (Bool, Bool) -> Void
let _updateTeam: (Bool) -> Void
let dismiss: DismissAction
var body: some View {
if editedTeam == nil {
if createdPlayerIds.isEmpty {
RowButtonView("Bloquer une place") {
_createTeam(false, false)
}
} else {
RowButtonView("Ajouter l'équipe") {
_createTeam(true, true)
}
}
} else {
RowButtonView("Confirmer") {
_updateTeam(false)
dismiss()
}
}
}
}
struct TeamHeader: View {
let tournament: Tournament
let _currentSelection: () -> Set<PlayerRegistration>
var body: some View {
let currentSelection = _currentSelection()
let selectedSortedTeams = tournament.selectedSortedTeams()
let rank = currentSelection.map { $0.computedRank }.reduce(0, +)
let teamIndex = selectedSortedTeams.firstIndex(where: { $0.weight >= rank }) ?? selectedSortedTeams.count
if !currentSelection.isEmpty, !tournament.hideWeight(), rank > 0 {
HStack(spacing: 16.0) {
VStack(alignment: .leading, spacing: 0) {
Text("Rang").font(.caption)
Text("#" + (teamIndex + 1).formatted())
}
VStack(alignment: .leading, spacing: 0) {
Text("Poids").font(.caption)
Text(rank.formatted())
}
Spacer()
VStack(alignment: .trailing, spacing: 0) {
Text("").font(.caption)
Text(tournament.cutLabel(index: teamIndex, teamCount: selectedSortedTeams.count))
}
}
}
}
}
let testMessages = [ let testMessages = [
"Anthony dovetta ( 3620578 K )et christophe capeau ( 4666443v)", "Anthony dovetta ( 3620578 K )et christophe capeau ( 4666443v)",
""" """

Loading…
Cancel
Save