diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index ff3dbf5..2f0fc7c 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -27,9 +27,6 @@ C4A47D5A2B6D383C00ADC637 /* Tournament.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D592B6D383C00ADC637 /* Tournament.swift */; }; C4A47D5E2B6D38EC00ADC637 /* DataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D5D2B6D38EC00ADC637 /* DataStore.swift */; }; C4A47D632B6D3D6500ADC637 /* Club.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D622B6D3D6500ADC637 /* Club.swift */; }; - C4A47D772B73789100ADC637 /* TournamentV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D762B73789100ADC637 /* TournamentV1.swift */; }; - C4A47D7B2B73C0F900ADC637 /* TournamentV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D7A2B73C0F900ADC637 /* TournamentV2.swift */; }; - C4A47D7D2B73CDC300ADC637 /* ClubV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D7C2B73CDC300ADC637 /* ClubV1.swift */; }; C4A47D872B7BA36D00ADC637 /* UserCreationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D862B7BA36D00ADC637 /* UserCreationView.swift */; }; C4A47D8A2B7BBB6500ADC637 /* SubscriptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D892B7BBB6500ADC637 /* SubscriptionView.swift */; }; C4A47D902B7BBBEC00ADC637 /* StoreManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D8D2B7BBBEC00ADC637 /* StoreManager.swift */; }; @@ -323,9 +320,6 @@ C4A47D592B6D383C00ADC637 /* Tournament.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tournament.swift; sourceTree = ""; }; C4A47D5D2B6D38EC00ADC637 /* DataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStore.swift; sourceTree = ""; }; C4A47D622B6D3D6500ADC637 /* Club.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Club.swift; sourceTree = ""; }; - C4A47D762B73789100ADC637 /* TournamentV1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentV1.swift; sourceTree = ""; }; - C4A47D7A2B73C0F900ADC637 /* TournamentV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentV2.swift; sourceTree = ""; }; - C4A47D7C2B73CDC300ADC637 /* ClubV1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClubV1.swift; sourceTree = ""; }; C4A47D862B7BA36D00ADC637 /* UserCreationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserCreationView.swift; sourceTree = ""; }; C4A47D892B7BBB6500ADC637 /* SubscriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionView.swift; sourceTree = ""; }; C4A47D8D2B7BBBEC00ADC637 /* StoreManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreManager.swift; sourceTree = ""; }; @@ -670,7 +664,6 @@ C4A47D5F2B6D3B2D00ADC637 /* Data */ = { isa = PBXGroup; children = ( - C4A47D752B73787D00ADC637 /* Migration */, C4A47D5D2B6D38EC00ADC637 /* DataStore.swift */, C4A47DAC2B85FCCD00ADC637 /* User.swift */, C4A47D592B6D383C00ADC637 /* Tournament.swift */, @@ -718,16 +711,6 @@ path = Views; sourceTree = ""; }; - C4A47D752B73787D00ADC637 /* Migration */ = { - isa = PBXGroup; - children = ( - C4A47D762B73789100ADC637 /* TournamentV1.swift */, - C4A47D7A2B73C0F900ADC637 /* TournamentV2.swift */, - C4A47D7C2B73CDC300ADC637 /* ClubV1.swift */, - ); - path = Migration; - sourceTree = ""; - }; C4A47D852B7BA33F00ADC637 /* User */ = { isa = PBXGroup; children = ( @@ -1320,7 +1303,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1520; - LastUpgradeCheck = 1520; + LastUpgradeCheck = 1530; TargetAttributes = { C425D3FC2B6D249D002A7B48 = { CreatedOnToolsVersion = 15.2; @@ -1510,7 +1493,6 @@ FF1162872BD004AD000C4809 /* EditingTeamView.swift in Sources */, FF6EC9062B947A1000EA7F5A /* NetworkManagerError.swift in Sources */, C4A47D5A2B6D383C00ADC637 /* Tournament.swift in Sources */, - C4A47D7B2B73C0F900ADC637 /* TournamentV2.swift in Sources */, FF3795662B9399AA004EA093 /* Persistence.swift in Sources */, FF1DF49B2BD8D23900822FA0 /* BarButtonView.swift in Sources */, FFF964502BC25E3700EEF017 /* PlanningView.swift in Sources */, @@ -1523,7 +1505,6 @@ FF82CFC52B911F5B00B0CAF2 /* OrganizedTournamentView.swift in Sources */, FFF964572BC26B3400EEF017 /* RoundScheduleEditorView.swift in Sources */, FF59FFB32B90EFAC0061EFF9 /* EventListView.swift in Sources */, - C4A47D7D2B73CDC300ADC637 /* ClubV1.swift in Sources */, FF8F263D2BAD627A00650388 /* TournamentConfiguratorView.swift in Sources */, FFC1E10C2BAC7FB0008D6F59 /* ClubImportView.swift in Sources */, FF3B60A32BC49BBC008C2E66 /* MatchScheduler.swift in Sources */, @@ -1593,7 +1574,6 @@ FF0E0B6D2BC254C6005F00A9 /* TournamentScheduleView.swift in Sources */, FF025AF12BD1AEBD00A86CF8 /* MatchFormatStorageView.swift in Sources */, FF3F74F62B919E45004CFE0E /* UmpireView.swift in Sources */, - C4A47D772B73789100ADC637 /* TournamentV1.swift in Sources */, C4A47DAD2B85FCCD00ADC637 /* User.swift in Sources */, FF967D012BAEF0B400A9A3BD /* MatchSummaryView.swift in Sources */, FF8F26452BAE0A3400650388 /* TournamentDurationManagerView.swift in Sources */, @@ -1806,6 +1786,7 @@ DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; + ENABLE_MODULE_VERIFIER = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PadelClub/Info.plist; @@ -1823,6 +1804,8 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 0.1; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + OTHER_SWIFT_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1841,6 +1824,7 @@ DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; + ENABLE_MODULE_VERIFIER = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PadelClub/Info.plist; @@ -1858,6 +1842,8 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 0.1; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + OTHER_SWIFT_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/PadelClub.xcodeproj/xcshareddata/xcschemes/PadelClub Raw.xcscheme b/PadelClub.xcodeproj/xcshareddata/xcschemes/PadelClub Raw.xcscheme index 414b382..c2b6b23 100644 --- a/PadelClub.xcodeproj/xcshareddata/xcschemes/PadelClub Raw.xcscheme +++ b/PadelClub.xcodeproj/xcshareddata/xcschemes/PadelClub Raw.xcscheme @@ -1,6 +1,6 @@ Bool { - DataStore.shared.user?.clubs?.contains(where: { $0 == id }) == true + DataStore.shared.user.clubs?.contains(where: { $0 == id }) == true } static func findOrCreate(name: String, code: String?, city: String? = nil, zipCode: String? = nil) -> Club { @@ -146,7 +146,7 @@ extension Club { if clubs.isEmpty == false { return clubs.first! } else { - return Club(creator: DataStore.shared.user?.id, name: name, code: code) + return Club(creator: DataStore.shared.user.id, name: name, code: code) } } } diff --git a/PadelClub/Data/DataStore.swift b/PadelClub/Data/DataStore.swift index 3782be2..fe586b6 100644 --- a/PadelClub/Data/DataStore.swift +++ b/PadelClub/Data/DataStore.swift @@ -14,6 +14,21 @@ class DataStore: ObservableObject { // fileprivate var _store: Store static let shared = DataStore() + @Published var user: User = User.placeHolder() { + didSet { + Store.main.collectionsCanSynchronize = (user.username.count > 0) + do { + if self.user.id != self.userStorage.item()?.id { + try self.userStorage.setItemNoSync(self.user) + if Store.main.collectionsCanSynchronize { + Store.main.loadCollectionFromServer() + } + } + } catch { + Logger.error(error) + } + } + } fileprivate(set) var tournaments: StoredCollection fileprivate(set) var clubs: StoredCollection @@ -28,7 +43,7 @@ class DataStore: ObservableObject { fileprivate(set) var monthData: StoredCollection fileprivate(set) var dateIntervals: StoredCollection - fileprivate(set) var userStorage: StoredObject + fileprivate(set) var userStorage: StoredSingleton // fileprivate var _userStorage: OptionalStorage = OptionalStorage(fileName: "user.json") fileprivate var _appSettingsStorage: MicroStorage = MicroStorage() @@ -52,22 +67,6 @@ class DataStore: ObservableObject { } } - var user: User? { - return self.userStorage.item() -// return self._userStorage.item - } - - func setUser(_ user: User) { - do { - try self.userStorage.setItem(user) - Store.main.collectionsCanSynchronize = true - self._loadCollections() - } catch { - Logger.error(error) - } -// self._userStorage.item = user - } - init() { let store = Store.main store.synchronizationApiURL = "http://127.0.0.1:8000/api/" @@ -92,26 +91,58 @@ class DataStore: ObservableObject { self.monthData = store.registerCollection(synchronized: false, indexed: indexed) self.dateIntervals = store.registerCollection(synchronized: synchronized, indexed: indexed) - self.userStorage = store.registerObject(synchronized: false) + self.userStorage = store.registerObject(synchronized: synchronized) + + NotificationCenter.default.addObserver(self, selector: #selector(collectionDidLoad), name: NSNotification.Name.CollectionDidLoad, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(collectionDidUpdate), name: NSNotification.Name.CollectionDidChange, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(collectionWasUpdated), name: NSNotification.Name.CollectionDidLoad, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(collectionWasUpdated), name: NSNotification.Name.CollectionDidChange, object: nil) } - @objc func collectionWasUpdated(notification: Notification) { + @objc func collectionDidLoad(notification: Notification) { self.objectWillChange.send() - - if let object = notification.object as? StoredObject { - Logger.log("StoredObject loaded with user = \(object.item())") - Store.main.collectionsCanSynchronize = object.item() != nil + if let object: StoredSingleton = notification.object as? StoredSingleton { + Logger.log("StoredObject loaded with user = \(String(describing: object.item()))") + + if let user = object.item() { + self.user = user + } } } + @objc func collectionDidUpdate(notification: Notification) { + self.objectWillChange.send() + } + +// var user: User { +// if let user = self.userStorage.item() { +// return user +// } else { +// let user = User(username: "", email: "", firstName: "", lastName: "", phone: nil, country: "") +// do { +// try self.userStorage.setItem(user) +// } catch { +// Logger.error(error) +// } +// return user +// } +// } + +// func setUser(_ user: User) { +// do { +// try self.userStorage.setItem(user) +// Store.main.collectionsCanSynchronize = user.username.count > 0 +// self._loadCollections() +// } catch { +// Logger.error(error) +// } +//// self._userStorage.item = user +// } + var globalRights: UserRight { if let _ = Guard.main.currentPlan { return .creation } - if let user = self.user, user.clubs != nil { + if self.user.clubs != nil { if user.umpireCode != nil { return .creation } else { @@ -132,7 +163,7 @@ class DataStore: ObservableObject { } fileprivate func _loadCollections() { - Store.main.loadCollections() + Store.main.loadCollectionFromServer() } } diff --git a/PadelClub/Data/Federal/FederalTournament.swift b/PadelClub/Data/Federal/FederalTournament.swift index 338ed0f..5437c25 100644 --- a/PadelClub/Data/Federal/FederalTournament.swift +++ b/PadelClub/Data/Federal/FederalTournament.swift @@ -29,7 +29,7 @@ struct FederalTournament: Identifiable, Codable { var event = DataStore.shared.events.first(where: { $0.tenupId == id.string }) if event == nil { - event = Event(creator: DataStore.shared.user?.id, club: club?.id, name: libelle, tenupId: id.string) + event = Event(creator: DataStore.shared.user.id, club: club?.id, name: libelle, tenupId: id.string) do { try DataStore.shared.events.addOrUpdate(instance: event!) } catch { diff --git a/PadelClub/Data/Migration/ClubV1.swift b/PadelClub/Data/Migration/ClubV1.swift deleted file mode 100644 index 22a253e..0000000 --- a/PadelClub/Data/Migration/ClubV1.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// ClubV1.swift -// PadelClub -// -// Created by Laurent Morvillier on 07/02/2024. -// - -import Foundation -import LeStorage - -class ClubV1 : ModelObject, Storable, MigrationSource { - - static func resourceName() -> String { return "clubs" } - - var id: String = Store.randomId() - var name: String - - init(name: String) { - self.name = name - } - - var tournaments: [Tournament] { - return [] - } - - override func deleteDependencies() throws { - try Store.main.deleteDependencies(items: self.tournaments) - } - - // MARK: - MigrationSource - - typealias Destination = Club - - func migrate() -> Club { - return Club(name: self.name, acronym: "test", address: "3 impasse des chevreuils") -// return Club(name: self.name, address: "3 impasse des chevreuils") - } - -} diff --git a/PadelClub/Data/Migration/TournamentV1.swift b/PadelClub/Data/Migration/TournamentV1.swift deleted file mode 100644 index de24809..0000000 --- a/PadelClub/Data/Migration/TournamentV1.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// Tournament_v1.swift -// PadelClub -// -// Created by Laurent Morvillier on 07/02/2024. -// - -import Foundation -import LeStorage - -class TournamentV1 : ModelObject, Storable, MigrationSource { - - static func resourceName() -> String { "tournaments" } - - var id: String = Store.randomId() - var name: String - var club_id: String - - init(name: String, club_id: String) { - self.name = name - self.club_id = club_id - } - - var club: Club? { return self.findById(self.club_id) } - - // MARK: - MigrationSource - - typealias Destination = TournamentV2 - - func migrate() -> TournamentV2 { - return TournamentV2(name: self.name, club_id: self.club_id, category: 0) - } - -} diff --git a/PadelClub/Data/Migration/TournamentV2.swift b/PadelClub/Data/Migration/TournamentV2.swift deleted file mode 100644 index 3abd316..0000000 --- a/PadelClub/Data/Migration/TournamentV2.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// TournamentV2.swift -// PadelClub -// -// Created by Laurent Morvillier on 07/02/2024. -// - -import Foundation -import LeStorage - -class TournamentV2 : ModelObject, Storable, MigrationSource { - - static func resourceName() -> String { "tournaments" } - - var id: String = Store.randomId() - var name: String - var club_id: String - var category: Int - - init(name: String, club_id: String, category: Int) { - self.name = name - self.club_id = club_id - self.category = category - } - - var club: Club? { return self.findById(self.club_id) } - - // MARK: - MigrationSource - - typealias Destination = Tournament - - func migrate() -> Tournament { - return Tournament.mock() - } - -} diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 18e8e1f..2753a40 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -950,11 +950,7 @@ class Tournament : ModelObject, Storable { } func umpireMail() -> [String]? { - if let email = DataStore.shared.user?.email { - return [email] - } else { - return nil - } + return [DataStore.shared.user.email] } func earnings() -> Double { diff --git a/PadelClub/Data/User.swift b/PadelClub/Data/User.swift index 51571b4..a7c9f96 100644 --- a/PadelClub/Data/User.swift +++ b/PadelClub/Data/User.swift @@ -91,6 +91,10 @@ class User: UserBase, Storable { case _country = "country" } + static func placeHolder() -> User { + return User(username: "", email: "", firstName: "", lastName: "", phone: nil, country: nil) + } + } class UserCreationForm: User, UserPasswordBase { diff --git a/PadelClub/Views/Calling/CallMessageCustomizationView.swift b/PadelClub/Views/Calling/CallMessageCustomizationView.swift index d6626af..0a8a43e 100644 --- a/PadelClub/Views/Calling/CallMessageCustomizationView.swift +++ b/PadelClub/Views/Calling/CallMessageCustomizationView.swift @@ -168,7 +168,7 @@ struct CallMessageCustomizationView: View { @ViewBuilder private func _clubNameView() -> some View { if let eventClub = tournament.eventObject()?.clubObject() { - let hasBeenCreated: Bool = eventClub.hasBeenCreated(by: dataStore.user?.id) + let hasBeenCreated: Bool = eventClub.hasBeenCreated(by: dataStore.user.id) Section { TextField("Nom du club", text: $customClubName) .autocorrectionDisabled() diff --git a/PadelClub/Views/Club/ClubDetailView.swift b/PadelClub/Views/Club/ClubDetailView.swift index 73b3a30..4c62c10 100644 --- a/PadelClub/Views/Club/ClubDetailView.swift +++ b/PadelClub/Views/Club/ClubDetailView.swift @@ -153,7 +153,7 @@ struct ClubDetailView: View { RowButtonView("Supprimer ce club", role: .destructive) { do { try dataStore.clubs.deleteById(club.id) - dataStore.user?.clubs?.removeAll(where: { $0 == club.id }) + dataStore.user.clubs?.removeAll(where: { $0 == club.id }) try dataStore.userStorage.update() } catch { Logger.error(error) @@ -176,9 +176,9 @@ struct ClubDetailView: View { BarButtonView("Favori", icon: isFavorite ? "star.fill" : "star") { do { if isFavorite { - dataStore.user?.clubs?.removeAll(where: { $0 == club.id }) + dataStore.user.clubs?.removeAll(where: { $0 == club.id }) } else { - dataStore.user?.clubs?.append(club.id) + dataStore.user.clubs?.append(club.id) } try dataStore.userStorage.update() } catch { diff --git a/PadelClub/Views/Club/ClubSearchView.swift b/PadelClub/Views/Club/ClubSearchView.swift index 4fca530..f414c02 100644 --- a/PadelClub/Views/Club/ClubSearchView.swift +++ b/PadelClub/Views/Club/ClubSearchView.swift @@ -84,7 +84,7 @@ struct ClubSearchView: View { Button { let clubToEdit = club ?? Club.findOrCreate(name: clubMark.nom, code: clubMark.clubID) - if clubToEdit.creator == dataStore.user?.id && dataStore.user?.id != nil { + if clubToEdit.creator == dataStore.user.id { if clubToEdit.name.isEmpty { clubToEdit.name = clubMark.nom clubToEdit.acronym = clubToEdit.automaticShortName() @@ -98,8 +98,8 @@ struct ClubSearchView: View { if displayContext == .addition { do { try dataStore.clubs.addOrUpdate(instance: clubToEdit) - if dataStore.user?.clubs?.contains(where: { $0 == clubToEdit.id }) == false { - dataStore.user?.clubs?.append(clubToEdit.id) + if dataStore.user.clubs?.contains(where: { $0 == clubToEdit.id }) == false { + dataStore.user.clubs?.append(clubToEdit.id) try dataStore.userStorage.update() } } catch { diff --git a/PadelClub/Views/Club/ClubsView.swift b/PadelClub/Views/Club/ClubsView.swift index ec2830f..11d3f2f 100644 --- a/PadelClub/Views/Club/ClubsView.swift +++ b/PadelClub/Views/Club/ClubsView.swift @@ -26,7 +26,7 @@ struct ClubsView: View { // .tipStyle(tint: nil) // } // } - let clubs : [Club] = (dataStore.user?.clubsObjects(includeCreated: true)) ?? [] + let clubs : [Club] = dataStore.user.clubsObjects(includeCreated: true) ForEach(clubs) { club in if let selection { Button { @@ -40,7 +40,7 @@ struct ClubsView: View { .buttonStyle(.plain) } else { NavigationLink { - ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: dataStore.user?.id) ? .edition : .lockedForEditing) + ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: dataStore.user.id) ? .edition : .lockedForEditing) } label: { ClubRowView(club: club) } @@ -55,7 +55,7 @@ struct ClubsView: View { } } .overlay { - if dataStore.user?.hasFavoriteClubsAndCreatedClubs() == false { + if dataStore.user.hasFavoriteClubsAndCreatedClubs() == false { ContentUnavailableView { Label("Aucun club", systemImage: "house.and.flag.fill") } description: { diff --git a/PadelClub/Views/Club/CreateClubView.swift b/PadelClub/Views/Club/CreateClubView.swift index f455d3e..ee2d7b4 100644 --- a/PadelClub/Views/Club/CreateClubView.swift +++ b/PadelClub/Views/Club/CreateClubView.swift @@ -33,7 +33,7 @@ struct CreateClubView: View { let existingOrCreatedClub = Club.findOrCreate(name: club.name, code: club.code, city: club.city, zipCode: club.zipCode) //update existing club if rights ok / freshly created club with data input from user - if existingOrCreatedClub.hasBeenCreated(by: dataStore.user?.id) { + if existingOrCreatedClub.hasBeenCreated(by: dataStore.user.id) { existingOrCreatedClub.update(fromClub: club) do { try dataStore.clubs.addOrUpdate(instance: existingOrCreatedClub) @@ -44,8 +44,8 @@ struct CreateClubView: View { //save into user do { - if dataStore.user?.clubs?.contains(where: { $0 == existingOrCreatedClub.id }) == false { - dataStore.user?.clubs?.append(existingOrCreatedClub.id) + if dataStore.user.clubs?.contains(where: { $0 == existingOrCreatedClub.id }) == false { + dataStore.user.clubs?.append(existingOrCreatedClub.id) try dataStore.userStorage.update() } } catch { diff --git a/PadelClub/Views/Event/EventCreationView.swift b/PadelClub/Views/Event/EventCreationView.swift index 6689ede..aaca795 100644 --- a/PadelClub/Views/Event/EventCreationView.swift +++ b/PadelClub/Views/Event/EventCreationView.swift @@ -90,7 +90,7 @@ struct EventCreationView: View { Section { RowButtonView("Valider") { - let event = Event(creator: dataStore.user?.id, name: eventName) + let event = Event(creator: dataStore.user.id, name: eventName) event.club = selectedClub?.id tournaments.forEach { tournament in tournament.event = event.id diff --git a/PadelClub/Views/Match/MatchDetailView.swift b/PadelClub/Views/Match/MatchDetailView.swift index 67cfb4f..d467e89 100644 --- a/PadelClub/Views/Match/MatchDetailView.swift +++ b/PadelClub/Views/Match/MatchDetailView.swift @@ -129,7 +129,7 @@ struct MatchDetailView: View { showDetails = true } Spacer() - MenuWarningView(teams: match.teams(), message: match.matchWarningMessage(), umpireMail: dataStore.user?.email, subject: match.matchWarningSubject(), contactType: $contactType) + MenuWarningView(teams: match.teams(), message: match.matchWarningMessage(), umpireMail: dataStore.user.email, subject: match.matchWarningSubject(), contactType: $contactType) .buttonStyle(.borderless) } } diff --git a/PadelClub/Views/Navigation/Agenda/ActivityView.swift b/PadelClub/Views/Navigation/Agenda/ActivityView.swift index b4fe287..3541dff 100644 --- a/PadelClub/Views/Navigation/Agenda/ActivityView.swift +++ b/PadelClub/Views/Navigation/Agenda/ActivityView.swift @@ -122,14 +122,14 @@ struct ActivityView: View { // } .task { if navigation.agendaDestination == .tenup - && dataStore.user?.hasClubs() == true + && dataStore.user.hasClubs() == true && federalDataViewModel.federalTournaments.isEmpty { _gatherFederalTournaments() } } .onChange(of: navigation.agendaDestination) { if navigation.agendaDestination == .tenup - && dataStore.user?.hasClubs() == true + && dataStore.user.hasClubs() == true && federalDataViewModel.federalTournaments.isEmpty { _gatherFederalTournaments() } @@ -203,7 +203,7 @@ struct ActivityView: View { .tint(.master) } .sheet(isPresented: $presentClubSearchView, onDismiss: { - if dataStore.user?.hasClubs() == true { + if dataStore.user.hasClubs() == true { navigation.agendaDestination = .tenup } }) { @@ -218,7 +218,7 @@ struct ActivityView: View { isGatheringFederalTournaments = true Task { do { - let clubs : [Club] = (dataStore.user?.clubsObjects()) ?? [] + let clubs : [Club] = dataStore.user.clubsObjects() try await federalDataViewModel.gatherTournaments(clubs: clubs.filter { $0.code != nil }, startDate: .now.startOfMonth) } catch { self.error = error @@ -257,7 +257,7 @@ struct ActivityView: View { RowButtonView("Créer un nouvel événement") { newTournament = Tournament.newEmptyInstance() } - if dataStore.user?.hasClubs() == false { + if dataStore.user.hasClubs() == false { RowButtonView("Chercher l'un de vos clubs") { presentClubSearchView = true } @@ -278,7 +278,7 @@ struct ActivityView: View { } private func _tenupEmptyView() -> some View { - if dataStore.user?.hasClubs() == false { + if dataStore.user.hasClubs() == false { ContentUnavailableView { Label("Aucun tournoi", systemImage: "shield.slash") } description: { diff --git a/PadelClub/Views/Navigation/Agenda/EventListView.swift b/PadelClub/Views/Navigation/Agenda/EventListView.swift index dab5805..61942c7 100644 --- a/PadelClub/Views/Navigation/Agenda/EventListView.swift +++ b/PadelClub/Views/Navigation/Agenda/EventListView.swift @@ -51,7 +51,7 @@ struct EventListView: View { .headerProminence(.increased) .task { if navigation.agendaDestination == .tenup - && dataStore.user?.hasClubs() == true + && dataStore.user.hasClubs() == true && _tournaments.isEmpty { _gatherFederalTournaments(startDate: section) } @@ -64,7 +64,7 @@ struct EventListView: View { // isGatheringFederalTournaments = true Task { do { - let clubs : [Club] = (dataStore.user?.clubsObjects()) ?? [] + let clubs : [Club] = dataStore.user.clubsObjects() try await federalDataViewModel.gatherTournaments(clubs: clubs.filter { $0.code != nil }, startDate: startDate, endDate: startDate.endOfMonth) } catch { Logger.error(error) diff --git a/PadelClub/Views/Navigation/Umpire/UmpireView.swift b/PadelClub/Views/Navigation/Umpire/UmpireView.swift index 67952e7..afc9966 100644 --- a/PadelClub/Views/Navigation/Umpire/UmpireView.swift +++ b/PadelClub/Views/Navigation/Umpire/UmpireView.swift @@ -46,52 +46,51 @@ struct UmpireView: View { Label("Mon compte", systemImage: "person.circle.fill") } - if let user = dataStore.user { - let currentPlayerData = user.currentPlayerData() - Section { - if let currentPlayerData { - NavigationLink { - - } label: { - ImportedPlayerView(player: currentPlayerData) - } - } else { - NavigationLink { - SelectablePlayerListView(allowSelection: 1, searchField: user.firstName + " " + user.lastName, playerSelectionAction: { players in - if let player = players.first { - user.licenceId = player.license - if user.clubsObjects().contains(where: { $0.code == player.clubCode }) == false { - let userClub = Club.findOrCreate(name: player.clubName!, code: player.clubCode) - do { - try dataStore.clubs.addOrUpdate(instance: userClub) - user.setUserClub(userClub) - try dataStore.userStorage.update() - } catch { - Logger.error(error) - } + let user = dataStore.user + let currentPlayerData = user.currentPlayerData() + Section { + if let currentPlayerData { + NavigationLink { + + } label: { + ImportedPlayerView(player: currentPlayerData) + } + } else { + NavigationLink { + SelectablePlayerListView(allowSelection: 1, searchField: user.firstName + " " + user.lastName, playerSelectionAction: { players in + if let player = players.first { + user.licenceId = player.license + if user.clubsObjects().contains(where: { $0.code == player.clubCode }) == false { + let userClub = Club.findOrCreate(name: player.clubName!, code: player.clubCode) + do { + try dataStore.clubs.addOrUpdate(instance: userClub) + user.setUserClub(userClub) + try dataStore.userStorage.update() + } catch { + Logger.error(error) } } - }) - .id(UUID()) - } label: { - Label("Ma fiche joueur", systemImage: "person.bust.circle.fill") - } - } - } header: { - if currentPlayerData != nil { - Text("Ma fiche joueur") - } - } footer: { - if user.licenceId == nil { - Text("Si vous avez participé à un tournoi dans les 12 derniers mois, Padel Club peut vous retrouver.") - } else { - Button("supprimer", role: .destructive) { - user.licenceId = nil - do { - try dataStore.userStorage.update() - } catch { - Logger.error(error) } + }) + .id(UUID()) + } label: { + Label("Ma fiche joueur", systemImage: "person.bust.circle.fill") + } + } + } header: { + if currentPlayerData != nil { + Text("Ma fiche joueur") + } + } footer: { + if user.licenceId == nil { + Text("Si vous avez participé à un tournoi dans les 12 derniers mois, Padel Club peut vous retrouver.") + } else { + Button("supprimer", role: .destructive) { + user.licenceId = nil + do { + try dataStore.userStorage.update() + } catch { + Logger.error(error) } } } @@ -102,7 +101,7 @@ struct UmpireView: View { ClubsView() } label: { LabeledContent { - Text((dataStore.user?.clubs ?? []).count.formatted()) + Text((dataStore.user.clubs ?? []).count.formatted()) } label: { Label("Mes clubs", systemImage: "house.and.flag.circle.fill") } @@ -161,6 +160,17 @@ struct UmpireView: View { // } } .navigationTitle("Juge-Arbitre") + .toolbar { + #if DEBUG + ToolbarItem(placement: .topBarTrailing) { + if Store.main.collectionsCanSynchronize { + Image(systemName: "checkmark.icloud") + } else { + Image(systemName: "icloud.slash") + } + } + #endif + } } } } diff --git a/PadelClub/Views/Shared/TournamentFilterView.swift b/PadelClub/Views/Shared/TournamentFilterView.swift index 3a9a0ff..91d2455 100644 --- a/PadelClub/Views/Shared/TournamentFilterView.swift +++ b/PadelClub/Views/Shared/TournamentFilterView.swift @@ -27,7 +27,7 @@ struct TournamentFilterView: View { var body: some View { NavigationView { Form { - let clubs : [Club] = (dataStore.user?.clubsObjects()) ?? [] + let clubs : [Club] = dataStore.user.clubsObjects() if clubs.filter({ $0.code != nil }).isEmpty == false { Section { ForEach(clubs.filter({ $0.code != nil })) { club in diff --git a/PadelClub/Views/Subscription/Guard.swift b/PadelClub/Views/Subscription/Guard.swift index 7888277..f8c6854 100644 --- a/PadelClub/Views/Subscription/Guard.swift +++ b/PadelClub/Views/Subscription/Guard.swift @@ -135,7 +135,7 @@ import LeStorage func userFilteredPurchases() -> [StoreKit.Transaction] { - let userTransactions = self.purchasedTransactions.filter { Store.main.currentUserUUID() == $0.appAccountToken } + let userTransactions = self.purchasedTransactions.filter { Store.main.mandatoryUserUUID() == $0.appAccountToken } return userTransactions.filter { transaction in if let expirationDate = transaction.expirationDate { @@ -219,7 +219,7 @@ struct PurchaseRow: Identifiable { fileprivate extension StoreKit.Transaction { func purchase() -> Purchase { - let userId = Store.main.currentUserUUID().uuidString + let userId = Store.main.mandatoryUserUUID().uuidString return Purchase(user: userId, identifier: self.originalID, purchaseDate: self.purchaseDate, diff --git a/PadelClub/Views/Subscription/StoreManager.swift b/PadelClub/Views/Subscription/StoreManager.swift index cf809c9..1875a0a 100644 --- a/PadelClub/Views/Subscription/StoreManager.swift +++ b/PadelClub/Views/Subscription/StoreManager.swift @@ -90,7 +90,7 @@ class StoreManager { Logger.log("Store purchase started...") var options: Set = [] - let uuid: UUID = Store.main.currentUserUUID() + let uuid: UUID = Store.main.mandatoryUserUUID() let tokenOption = Product.PurchaseOption.appAccountToken(uuid) options.insert(tokenOption) diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift index 8169b8a..37bbab6 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift @@ -21,7 +21,7 @@ struct TournamentClubSettingsView: View { Section { if let selectedClub { NavigationLink { - ClubDetailView(club: selectedClub, displayContext: selectedClub.hasBeenCreated(by: dataStore.user?.id) ? .edition : .lockedForEditing) + ClubDetailView(club: selectedClub, displayContext: selectedClub.hasBeenCreated(by: dataStore.user.id) ? .edition : .lockedForEditing) } label: { ClubRowView(club: selectedClub) } diff --git a/PadelClub/Views/User/LoginView.swift b/PadelClub/Views/User/LoginView.swift index af815d7..3a884b0 100644 --- a/PadelClub/Views/User/LoginView.swift +++ b/PadelClub/Views/User/LoginView.swift @@ -88,7 +88,7 @@ struct LoginView: View { let user: User = try await service.login( username: self.username, password: self.password) - self.dataStore.setUser(user) + self.dataStore.user = user self.handler(user) } catch { switch error { diff --git a/PadelClub/Views/User/MainUserView.swift b/PadelClub/Views/User/MainUserView.swift index 1d572f4..2989aa1 100644 --- a/PadelClub/Views/User/MainUserView.swift +++ b/PadelClub/Views/User/MainUserView.swift @@ -16,8 +16,8 @@ struct MainUserView: View { var body: some View { Group { - if self.isConnected, let user = dataStore.user { - AccountView(user: user) { + if self.isConnected { + AccountView(user: dataStore.user) { self._checkConnection() } } else { @@ -31,7 +31,7 @@ struct MainUserView: View { } fileprivate func _checkConnection() { - self.isConnected = dataStore.user != nil && Store.main.hasToken() + self.isConnected = dataStore.user.username.count > 0 && Store.main.hasToken() } } diff --git a/PadelClub/Views/User/UserCreationView.swift b/PadelClub/Views/User/UserCreationView.swift index b56d698..e5b9008 100644 --- a/PadelClub/Views/User/UserCreationView.swift +++ b/PadelClub/Views/User/UserCreationView.swift @@ -122,7 +122,8 @@ struct UserCreationFormView: View { country: self.countries[self.selectedCountryIndex]) let service = try Store.main.service() - let _: User = try await service.createAccount(user: userCreationForm) + let user: User = try await service.createAccount(user: userCreationForm) + DataStore.shared.user = user self.isLoading = false self.showLoginScreen = true