diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 1b1af2591..fdff093ce 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -99,7 +99,7 @@ final class RiotSettings: NSObject { @UserDefault(key: "userInterfaceTheme", defaultValue: nil, storage: defaults) var userInterfaceTheme - // MARK: Other + // MARK: Analytics & Rageshakes /// Whether the user was previously shown the Matomo analytics prompt. var hasSeenAnalyticsPrompt: Bool { @@ -130,6 +130,12 @@ final class RiotSettings: NSObject { @UserDefault(key: "enableRageShake", defaultValue: false, storage: defaults) var enableRageShake + // MARK: User + + /// A dictionary of dictionaries keyed by user ID for storage of the `UserSessionProperties` from any active `UserSession`s. + @UserDefault(key: "userSessionProperties", defaultValue: [:], storage: defaults) + var userSessionProperties: [String: [String: Any]] + // MARK: Labs /// Indicates if CallKit ringing is enabled for group calls. This setting does not disable the CallKit integration for group calls, only relates to ringing. diff --git a/Riot/Managers/UserSessions/UserSession.swift b/Riot/Managers/UserSessions/UserSession.swift index fa5b883ac..8795812e6 100644 --- a/Riot/Managers/UserSessions/UserSession.swift +++ b/Riot/Managers/UserSessions/UserSession.swift @@ -33,21 +33,21 @@ class UserSession: NSObject, UserSessionProtocol { let account: MXKAccount // Keep strong reference to the MXSession because account.mxSession can become nil on logout or failure let matrixSession: MXSession + let userId: String /// An object that contains user specific properties. - private(set) lazy var properties = UserSessionProperties(userId: userId) - - var userId: String { - guard let userId = self.account.mxCredentials.userId else { - fatalError("[UserSession] identifier: account.mxCredentials.userId should be defined") - } - return userId - } + let userProperties: UserSessionProperties // MARK: - Setup init(account: MXKAccount, matrixSession: MXSession) { + guard let userId = account.mxCredentials.userId else { + fatalError("[UserSession] identifier: account.mxCredentials.userId should be defined") + } + self.account = account self.matrixSession = matrixSession + self.userId = userId + self.userProperties = UserSessionProperties(userId: userId) super.init() } } diff --git a/Riot/Managers/UserSessions/UserSessionProperties.swift b/Riot/Managers/UserSessions/UserSessionProperties.swift index e637aa3fc..4bac87579 100644 --- a/Riot/Managers/UserSessions/UserSessionProperties.swift +++ b/Riot/Managers/UserSessions/UserSessionProperties.swift @@ -21,7 +21,6 @@ class UserSessionProperties: NSObject { // MARK: - Constants private enum Constants { - static let suiteName = BuildSettings.baseBundleIdentifier + ".UserSession" static let useCaseKey = "useCase" } @@ -31,10 +30,16 @@ class UserSessionProperties: NSObject { /// The user ID for these properties private let userId: String - /// The underlying dictionary that stores the properties in user defaults. + + /// The underlying dictionary for this userId from user defaults. private var dictionary: [String: Any] { - didSet { - UserDefaults(suiteName: Constants.suiteName)?.set(dictionary, forKey: userId) + get { + RiotSettings.shared.userSessionProperties[userId] ?? [:] + } + set { + var sharedProperties = RiotSettings.shared.userSessionProperties + sharedProperties[userId] = newValue + RiotSettings.shared.userSessionProperties = sharedProperties } } @@ -65,8 +70,6 @@ class UserSessionProperties: NSObject { /// - Parameter userId: The user ID to load properties for. init(userId: String) { self.userId = userId - self.dictionary = UserDefaults(suiteName: Constants.suiteName)?.dictionary(forKey: userId) ?? [:] - super.init() } @@ -75,6 +78,9 @@ class UserSessionProperties: NSObject { /// Clear all of the stored properties. func delete() { dictionary = [:] - UserDefaults(suiteName: Constants.suiteName)?.removeObject(forKey: userId) + + var sharedProperties = RiotSettings.shared.userSessionProperties + sharedProperties[userId] = nil + RiotSettings.shared.userSessionProperties = sharedProperties } } diff --git a/Riot/Managers/UserSessions/UserSessionsService.swift b/Riot/Managers/UserSessions/UserSessionsService.swift index c5842dfed..c94497161 100644 --- a/Riot/Managers/UserSessions/UserSessionsService.swift +++ b/Riot/Managers/UserSessions/UserSessionsService.swift @@ -132,7 +132,7 @@ class UserSessionsService: NSObject { } // Clear any stored user properties from this session. - userSession.properties.delete() + userSession.userProperties.delete() self.userSessions.removeAll { (userSession) -> Bool in return userId == userSession.userId diff --git a/Riot/Modules/Authentication/AuthenticationCoordinator.swift b/Riot/Modules/Authentication/AuthenticationCoordinator.swift index 9cdb59ddb..e2ba6ee2e 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinator.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinator.swift @@ -63,7 +63,7 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc } func showCustomServer() { - authenticationViewController.hideCustomServers(false) + authenticationViewController.setCustomServerFieldsVisible(true) } func update(externalRegistrationParameters: [AnyHashable: Any]) { diff --git a/Riot/Modules/Authentication/AuthenticationViewController.h b/Riot/Modules/Authentication/AuthenticationViewController.h index 6d412400f..f3699125d 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.h +++ b/Riot/Modules/Authentication/AuthenticationViewController.h @@ -54,9 +54,9 @@ /// returns YES if the SSO login can be continued. - (BOOL)continueSSOLoginWithToken:(NSString*)loginToken txnId:(NSString*)txnId; -/// Hides/shows the custom homeserver field. -/// @param hidden YES to hide, NO to show. -- (void)hideCustomServers:(BOOL)hidden; +/// Show or hide the custom server textfields. +/// @param isVisible YES to show, NO to hide. +- (void)setCustomServerFieldsVisible:(BOOL)isVisible; @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 5579bc416..0ff35511e 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -160,7 +160,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; } self.serverOptionsContainer.hidden = !BuildSettings.authScreenShowCustomServerOptions; - [self hideCustomServers:YES]; + [self setCustomServerFieldsVisible:NO]; // Soft logout section self.softLogoutClearDataButton.layer.cornerRadius = 5; @@ -888,7 +888,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; { if (sender == self.customServersTickButton) { - [self hideCustomServers:!self.customServersContainer.hidden]; + [self setCustomServerFieldsVisible:self.customServersContainer.hidden]; } else if (sender == self.forgotPasswordButton) { @@ -1236,14 +1236,14 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self.view layoutIfNeeded]; } -- (void)hideCustomServers:(BOOL)hidden +- (void)setCustomServerFieldsVisible:(BOOL)isVisible { - if (self.customServersContainer.isHidden == hidden) + if (self.customServersContainer.isHidden != isVisible) { return; } - if (hidden) + if (!isVisible) { [self.homeServerTextField resignFirstResponder]; [self.identityServerTextField resignFirstResponder]; @@ -1361,7 +1361,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self.authenticationActivityIndicator startAnimating]; // Hide the custom server details in order to save customized inputs - [self hideCustomServers:YES]; + [self setCustomServerFieldsVisible:NO]; MXKAccount *account = [[MXKAccountManager sharedManager] accountForUserId:userId]; MXSession *session = account.mxSession; @@ -1586,7 +1586,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; { // wellKnown matches with application default servers // Hide custom servers - [self hideCustomServers:YES]; + [self setCustomServerFieldsVisible:NO]; } else { @@ -1618,7 +1618,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; } // And show custom servers - [self hideCustomServers:NO]; + [self setCustomServerFieldsVisible:YES]; } #pragma mark - KeyVerificationCoordinatorBridgePresenterDelegate diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift index 3dd2e3e5c..571140f43 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift @@ -138,7 +138,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { switch result { case .register: - showUseCase() + showUseCaseSelectionScreen() case .login: showAuthenticationScreen() } @@ -146,7 +146,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { @available(iOS 14.0, *) /// Show the use case screen for new users. - private func showUseCase() { + private func showUseCaseSelectionScreen() { let coordinator = OnboardingUseCaseCoordinator() coordinator.completion = { [weak self, weak coordinator] result in guard let self = self, let coordinator = coordinator else { return } @@ -227,7 +227,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { let useCaseResult = useCaseResult, let userSession = UserSessionsService.shared.mainUserSession { // Store the value in the user's session - userSession.properties.useCase = useCaseResult.userSessionPropertyValue + userSession.userProperties.useCase = useCaseResult.userSessionPropertyValue } } }