diff --git a/PadelClub/Data/DataStore.swift b/PadelClub/Data/DataStore.swift index 2bbf3a6..8dfc8ba 100644 --- a/PadelClub/Data/DataStore.swift +++ b/PadelClub/Data/DataStore.swift @@ -46,25 +46,10 @@ class DataStore: ObservableObject { fileprivate(set) var userStorage: StoredSingleton // fileprivate var _userStorage: OptionalStorage = OptionalStorage(fileName: "user.json") - fileprivate var _appSettingsStorage: MicroStorage = MicroStorage() + fileprivate(set) var appSettingsStorage: MicroStorage = MicroStorage() var appSettings: AppSettings { - _appSettingsStorage.item - } - - func updateSettings() { - _appSettingsStorage.update { settings in - settings.lastDataSource = appSettings.lastDataSource - settings.callMessageBody = appSettings.callMessageBody - settings.callDisplayFormat = appSettings.callDisplayFormat - settings.callMessageSignature = appSettings.callMessageSignature - settings.callDisplayEntryFee = appSettings.callDisplayEntryFee - settings.callUseFullCustomMessage = appSettings.callUseFullCustomMessage - settings.matchFormatsDefaultDuration = appSettings.matchFormatsDefaultDuration - settings.bracketMatchFormatPreference = appSettings.bracketMatchFormatPreference - settings.groupStageMatchFormatPreference = appSettings.groupStageMatchFormatPreference - settings.loserBracketMatchFormatPreference = appSettings.loserBracketMatchFormatPreference - } + appSettingsStorage.item } init() { diff --git a/PadelClub/Data/User.swift b/PadelClub/Data/User.swift index f6c36de..c3dfa46 100644 --- a/PadelClub/Data/User.swift +++ b/PadelClub/Data/User.swift @@ -32,6 +32,16 @@ class User: UserBase, Storable { var phone: String? var country: String? + var callMessageBody : String? = nil + var callMessageSignature: String? = nil + var callDisplayFormat: Bool = false + var callDisplayEntryFee: Bool = false + var callUseFullCustomMessage: Bool = false + var matchFormatsDefaultDuration: [MatchFormat: Int]? = nil + var bracketMatchFormatPreference: MatchFormat? + var groupStageMatchFormatPreference: MatchFormat? + var loserBracketMatchFormatPreference: MatchFormat? + init(username: String, email: String, firstName: String, lastName: String, phone: String?, country: String?) { self.username = username self.firstName = firstName @@ -73,6 +83,15 @@ class User: UserBase, Storable { return Store.main.filter(isIncluded: { (includeCreated && $0.creator == id) || clubs.contains($0.id) }) } + func saveMatchFormatsDefaultDuration(_ matchFormat: MatchFormat, estimatedDuration: Int) { + if estimatedDuration == matchFormat.defaultEstimatedDuration { + matchFormatsDefaultDuration?.removeValue(forKey: matchFormat) + } else { + matchFormatsDefaultDuration = matchFormatsDefaultDuration ?? [MatchFormat: Int]() + matchFormatsDefaultDuration?[matchFormat] = estimatedDuration + } + } + enum CodingKeys: String, CodingKey { case _id = "id" case _username = "username" @@ -84,6 +103,16 @@ class User: UserBase, Storable { case _lastName = "lastName" case _phone = "phone" case _country = "country" + case _callMessageBody = "callMessageBody" + case _callMessageSignature = "callMessageSignature" + case _callDisplayFormat = "callDisplayFormat" + case _callDisplayEntryFee = "callDisplayEntryFee" + case _callUseFullCustomMessage = "callUseFullCustomMessage" + case _matchFormatsDefaultDuration = "matchFormatsDefaultDuration" + case _bracketMatchFormatPreference = "bracketMatchFormatPreference" + case _groupStageMatchFormatPreference = "groupStageMatchFormatPreference" + case _loserBracketMatchFormatPreference = "loserBracketMatchFormatPreference" + } static func placeHolder() -> User { diff --git a/PadelClub/Utils/ContactManager.swift b/PadelClub/Utils/ContactManager.swift index 56cb08f..8bfd478 100644 --- a/PadelClub/Utils/ContactManager.swift +++ b/PadelClub/Utils/ContactManager.swift @@ -34,7 +34,7 @@ extension ContactType { static let defaultSignature = "" static func callingGroupStageCustomMessage(tournament: Tournament?, startDate: Date?, roundLabel: String) -> String { - let tournamentCustomMessage = DataStore.shared.appSettings.callMessageBody ?? defaultCustomMessage + let tournamentCustomMessage = DataStore.shared.user.callMessageBody ?? defaultCustomMessage let clubName = tournament?.clubName ?? "" var text = tournamentCustomMessage @@ -49,7 +49,7 @@ extension ContactType { text = text.replacingOccurrences(of: "#jour", with: "\(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide)))") text = text.replacingOccurrences(of: "#horaire", with: "\(date.formatted(Date.FormatStyle().hour().minute()))") - let signature = DataStore.shared.appSettings.callMessageSignature ?? defaultSignature + let signature = DataStore.shared.user.callMessageSignature ?? defaultSignature text = text.replacingOccurrences(of: "#signature", with: signature) return text @@ -57,7 +57,7 @@ extension ContactType { static func callingGroupStageMessage(tournament: Tournament?, startDate: Date?, roundLabel: String, matchFormat: MatchFormat?) -> String { - let useFullCustomMessage = DataStore.shared.appSettings.callUseFullCustomMessage + let useFullCustomMessage = DataStore.shared.user.callUseFullCustomMessage if useFullCustomMessage { return callingGroupStageCustomMessage(tournament: tournament, startDate: startDate, roundLabel: roundLabel) @@ -66,17 +66,17 @@ extension ContactType { let date = startDate ?? tournament?.startDate ?? Date() let clubName = tournament?.clubName ?? "" - let message = DataStore.shared.appSettings.callMessageBody ?? defaultCustomMessage - let signature = DataStore.shared.appSettings.callMessageSignature ?? defaultSignature + let message = DataStore.shared.user.callMessageBody ?? defaultCustomMessage + let signature = DataStore.shared.user.callMessageSignature ?? defaultSignature let localizedCalled = "convoqué" + (tournament?.tournamentCategory == .women ? "e" : "") + "s" var formatMessage: String? { - (DataStore.shared.appSettings.callDisplayFormat) ? matchFormat?.computedLongLabel.appending(".") : nil + (DataStore.shared.user.callDisplayFormat) ? matchFormat?.computedLongLabel.appending(".") : nil } var entryFeeMessage: String? { - (DataStore.shared.appSettings.callDisplayEntryFee) ? tournament?.entryFeeMessage : nil + (DataStore.shared.user.callDisplayEntryFee) ? tournament?.entryFeeMessage : nil } var computedMessage: String { diff --git a/PadelClub/Utils/PadelRule.swift b/PadelClub/Utils/PadelRule.swift index fa1bad3..6151765 100644 --- a/PadelClub/Utils/PadelRule.swift +++ b/PadelClub/Utils/PadelRule.swift @@ -1075,11 +1075,11 @@ enum MatchFormat: Int, Hashable, Codable, CaseIterable { static func defaultFormatForMatchType(_ matchType: MatchType) -> MatchFormat { switch matchType { case .bracket: - DataStore.shared.appSettings.bracketMatchFormatPreference ?? .nineGamesDecisivePoint + DataStore.shared.user.bracketMatchFormatPreference ?? .nineGamesDecisivePoint case .groupStage: - DataStore.shared.appSettings.groupStageMatchFormatPreference ?? .nineGamesDecisivePoint + DataStore.shared.user.groupStageMatchFormatPreference ?? .nineGamesDecisivePoint case .loserBracket: - DataStore.shared.appSettings.loserBracketMatchFormatPreference ?? .nineGamesDecisivePoint + DataStore.shared.user.loserBracketMatchFormatPreference ?? .nineGamesDecisivePoint } } @@ -1109,7 +1109,7 @@ enum MatchFormat: Int, Hashable, Codable, CaseIterable { } private var estimatedDuration: Int { - DataStore.shared.appSettings.matchFormatsDefaultDuration?[self] ?? defaultEstimatedDuration + DataStore.shared.user.matchFormatsDefaultDuration?[self] ?? defaultEstimatedDuration } func formattedEstimatedDuration(_ additionalDuration: Int = 0) -> String { diff --git a/PadelClub/Views/Calling/CallMessageCustomizationView.swift b/PadelClub/Views/Calling/CallMessageCustomizationView.swift index 0a8a43e..a803f93 100644 --- a/PadelClub/Views/Calling/CallMessageCustomizationView.swift +++ b/PadelClub/Views/Calling/CallMessageCustomizationView.swift @@ -19,8 +19,8 @@ struct CallMessageCustomizationView: View { init(tournament: Tournament) { self.tournament = tournament - _customCallMessageBody = State(wrappedValue: DataStore.shared.appSettings.callMessageBody ?? "") - _customCallMessageSignature = State(wrappedValue: DataStore.shared.appSettings.callMessageSignature ?? "") + _customCallMessageBody = State(wrappedValue: DataStore.shared.user.callMessageBody ?? "") + _customCallMessageSignature = State(wrappedValue: DataStore.shared.user.callMessageSignature ?? "") _customClubName = State(wrappedValue: tournament.clubName ?? "") } @@ -29,11 +29,11 @@ struct CallMessageCustomizationView: View { } var formatMessage: String? { - dataStore.appSettings.callDisplayFormat ? tournament.matchFormat.computedLongLabel + "." : nil + dataStore.user.callDisplayFormat ? tournament.matchFormat.computedLongLabel + "." : nil } var entryFeeMessage: String? { - dataStore.appSettings.callDisplayEntryFee ? tournament.entryFeeMessage : nil + dataStore.user.callDisplayEntryFee ? tournament.entryFeeMessage : nil } var computedMessage: String { @@ -46,7 +46,7 @@ struct CallMessageCustomizationView: View { } var body: some View { - @Bindable var appSettings = dataStore.appSettings + @Bindable var user = dataStore.user List { Section { ZStack { @@ -74,7 +74,7 @@ struct CallMessageCustomizationView: View { _clubNameView() Section { - if appSettings.callUseFullCustomMessage { + if user.callUseFullCustomMessage { Text(self.computedFullCustomMessage()) .contextMenu { Button("Coller dans le presse-papier") { @@ -96,7 +96,7 @@ struct CallMessageCustomizationView: View { Section { LabeledContent { - Toggle(isOn: $appSettings.callUseFullCustomMessage) { + Toggle(isOn: $user.callUseFullCustomMessage) { } } label: { @@ -112,13 +112,13 @@ struct CallMessageCustomizationView: View { .toolbar { ToolbarItem(placement: .topBarTrailing) { Menu { - Picker(selection: $appSettings.callDisplayFormat) { + Picker(selection: $user.callDisplayFormat) { Text("Afficher le format").tag(true) Text("Masquer le format").tag(false) } label: { } - Picker(selection: $appSettings.callDisplayEntryFee) { + Picker(selection: $user.callDisplayEntryFee) { Text("Afficher le prix d'inscription").tag(true) Text("Masquer le prix d'inscription").tag(false) } label: { @@ -139,30 +139,34 @@ struct CallMessageCustomizationView: View { } } } - .onChange(of: appSettings.callUseFullCustomMessage) { - if appSettings.callUseFullCustomMessage == false { - appSettings.callMessageBody = ContactType.defaultCustomMessage + .onChange(of: user.callUseFullCustomMessage) { + if user.callUseFullCustomMessage == false { + user.callMessageBody = ContactType.defaultCustomMessage } _save() } .onChange(of: customCallMessageBody) { - appSettings.callMessageBody = customCallMessageBody + user.callMessageBody = customCallMessageBody _save() } .onChange(of: customCallMessageSignature) { - appSettings.callMessageSignature = customCallMessageSignature + user.callMessageSignature = customCallMessageSignature _save() } - .onChange(of: appSettings.callDisplayEntryFee) { + .onChange(of: user.callDisplayEntryFee) { _save() } - .onChange(of: appSettings.callDisplayFormat) { + .onChange(of: user.callDisplayFormat) { _save() } } private func _save() { - dataStore.updateSettings() + do { + try dataStore.userStorage.update() + } catch { + Logger.error(error) + } } @ViewBuilder diff --git a/PadelClub/Views/Navigation/MainView.swift b/PadelClub/Views/Navigation/MainView.swift index 4e0af40..2338077 100644 --- a/PadelClub/Views/Navigation/MainView.swift +++ b/PadelClub/Views/Navigation/MainView.swift @@ -126,7 +126,11 @@ struct MainView: View { Task { let lastDataSource = await FileImportManager.shared.importDataFromFFT() dataStore.appSettings.lastDataSource = lastDataSource - dataStore.updateSettings() + do { + try dataStore.appSettingsStorage.write() + } catch { + Logger.error(error) + } if let lastDataSource, let mostRecentDate = URL.importDateFormatter.date(from: lastDataSource) { await MonthData.calculateCurrentUnrankedValues(mostRecentDateAvailable: mostRecentDate) } diff --git a/PadelClub/Views/Navigation/Toolbox/GlobalSettingsView.swift b/PadelClub/Views/Navigation/Toolbox/GlobalSettingsView.swift index 05479be..7731072 100644 --- a/PadelClub/Views/Navigation/Toolbox/GlobalSettingsView.swift +++ b/PadelClub/Views/Navigation/Toolbox/GlobalSettingsView.swift @@ -6,15 +6,16 @@ // import SwiftUI +import LeStorage struct GlobalSettingsView: View { @EnvironmentObject var dataStore : DataStore var body: some View { - @Bindable var appSettings = dataStore.appSettings + @Bindable var user = dataStore.user List { Section { - Picker(selection: $appSettings.groupStageMatchFormatPreference) { + Picker(selection: $user.groupStageMatchFormatPreference) { Text("Automatique").tag(nil as MatchFormat?) ForEach(MatchFormat.allCases, id: \.self) { format in Text(format.format).tag(format as MatchFormat?) @@ -25,7 +26,7 @@ struct GlobalSettingsView: View { Spacer() } } - Picker(selection: $appSettings.bracketMatchFormatPreference) { + Picker(selection: $user.bracketMatchFormatPreference) { Text("Automatique").tag(nil as MatchFormat?) ForEach(MatchFormat.allCases, id: \.self) { format in Text(format.format).tag(format as MatchFormat?) @@ -36,7 +37,7 @@ struct GlobalSettingsView: View { Spacer() } } - Picker(selection: $appSettings.loserBracketMatchFormatPreference) { + Picker(selection: $user.loserBracketMatchFormatPreference) { Text("Automatique").tag(nil as MatchFormat?) ForEach(MatchFormat.allCases, id: \.self) { format in Text(format.format).tag(format as MatchFormat?) @@ -54,11 +55,15 @@ struct GlobalSettingsView: View { } } .onChange(of: [ - appSettings.bracketMatchFormatPreference, - appSettings.groupStageMatchFormatPreference, - appSettings.loserBracketMatchFormatPreference + user.bracketMatchFormatPreference, + user.groupStageMatchFormatPreference, + user.loserBracketMatchFormatPreference ]) { - dataStore.updateSettings() + do { + try dataStore.userStorage.update() + } catch { + Logger.error(error) + } } .navigationTitle("Formats par défaut") .navigationBarTitleDisplayMode(.inline) diff --git a/PadelClub/Views/Navigation/Toolbox/MatchFormatStorageView.swift b/PadelClub/Views/Navigation/Toolbox/MatchFormatStorageView.swift index 717c440..a8f5b60 100644 --- a/PadelClub/Views/Navigation/Toolbox/MatchFormatStorageView.swift +++ b/PadelClub/Views/Navigation/Toolbox/MatchFormatStorageView.swift @@ -6,6 +6,7 @@ // import SwiftUI +import LeStorage struct MatchFormatStorageView: View { @State private var estimatedDuration: Int @@ -42,8 +43,12 @@ struct MatchFormatStorageView: View { } } .onChange(of: estimatedDuration) { - dataStore.appSettings.saveMatchFormatsDefaultDuration(matchFormat, estimatedDuration: estimatedDuration) - dataStore.updateSettings() + dataStore.user.saveMatchFormatsDefaultDuration(matchFormat, estimatedDuration: estimatedDuration) + do { + try dataStore.userStorage.update() + } catch { + Logger.error(error) + } } } } diff --git a/PadelClub/Views/Navigation/Toolbox/PadelClubView.swift b/PadelClub/Views/Navigation/Toolbox/PadelClubView.swift index 40d0b8f..3cd3c7a 100644 --- a/PadelClub/Views/Navigation/Toolbox/PadelClubView.swift +++ b/PadelClub/Views/Navigation/Toolbox/PadelClubView.swift @@ -6,7 +6,7 @@ // import SwiftUI -import SwiftData +import LeStorage struct PadelClubView: View { @State private var checkingFilesAttempt: Int = 0 @@ -130,7 +130,11 @@ struct PadelClubView: View { Task { let lastDataSource = await FileImportManager.shared.importDataFromFFT() dataStore.appSettings.lastDataSource = lastDataSource - dataStore.updateSettings() + do { + try dataStore.appSettingsStorage.write() + } catch { + Logger.error(error) + } if let lastDataSource, let mostRecentDate = URL.importDateFormatter.date(from: lastDataSource) { await MonthData.calculateCurrentUnrankedValues(mostRecentDateAvailable: mostRecentDate) } diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift index ede4593..0a254ab 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift @@ -55,7 +55,7 @@ struct TournamentMatchFormatsSettingsView: View { .onChange(of: tournament.additionalEstimationDuration) { _save() } - .onChange(of: dataStore.appSettings.matchFormatsDefaultDuration) { + .onChange(of: dataStore.user.matchFormatsDefaultDuration) { _confirmOrSave() } .overlay(alignment: .bottom) {