diff --git a/Config/BWIBuildSettings.swift b/Config/BWIBuildSettings.swift index 3fb3b6b4a..cf7afe206 100644 --- a/Config/BWIBuildSettings.swift +++ b/Config/BWIBuildSettings.swift @@ -672,6 +672,9 @@ class BWIBuildSettings: NSObject { // MARK: OIDC var isOIDCEnabled = true + + // MARK: Change Password + var showPasswordChangedConfirmation = true // MARK: Create Room Menu var enableAllChatsToolbar = true diff --git a/Riot/Assets/de.lproj/Bwi.strings b/Riot/Assets/de.lproj/Bwi.strings index c4fa978f1..de7b8d186 100644 --- a/Riot/Assets/de.lproj/Bwi.strings +++ b/Riot/Assets/de.lproj/Bwi.strings @@ -198,7 +198,7 @@ "settings_old_password" = "Aktuelles Passwort"; "settings_new_password" = "Neues Passwort"; "settings_confirm_password" = "Neues Passwort bestätigen"; -"settings_password_updated" = "Dein Passwort wurde aktualisiert"; +"settings_password_changed" = "Dein Passwort wurde erfolgreich geändert."; "settings_password_condition" = "Regeln: Mindestlänge 8 Zeichen, mind. 1 Sonderzeichen, 1 Groß- und 1 Kleinbuchstaben und 1 Ziffer"; "settings_password_too_short_message" = "Das Passwort muss aus mindestens 8 Zeichen bestehen"; "settings_password_has_no_digit" = "Das Passwort muss mindestens eine Ziffer enthalten"; diff --git a/Riot/Assets/en.lproj/Bwi.strings b/Riot/Assets/en.lproj/Bwi.strings index 5fa2458fa..0de08e92b 100644 --- a/Riot/Assets/en.lproj/Bwi.strings +++ b/Riot/Assets/en.lproj/Bwi.strings @@ -154,7 +154,7 @@ "settings_new_password" = "new password"; "settings_confirm_password" = "confirm password"; "settings_fail_to_update_password" = "Fail to update password"; -"settings_password_updated" = "Your password has been updated"; +"settings_password_changed" = "Your password has been changed."; "settings_password_condition" = "Rules: Minimum length 8 characters, at least 1 special character, 1 uppercase and 1 lowercase letter and 1 number"; "settings_password_too_short_message" = "The password must be at least 8 characters long"; "settings_password_has_no_digit" = "The password must include at least one digit"; diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift index 6796dac14..5a4a27606 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift @@ -68,6 +68,8 @@ enum ChangePasswordViewAction { } enum ChangePasswordErrorType: Hashable { + /// The password has been changed on the server + case passwordChangeSucceeded /// An error response from the homeserver. case mxError(String) /// User entered new passwords do not match diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift index 6cfcea0e6..e9d0125c8 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift @@ -49,19 +49,25 @@ class ChangePasswordViewModel: ChangePasswordViewModelType, ChangePasswordViewMo switch viewAction { case .submit: guard state.bindings.newPassword1 == state.bindings.newPassword2 else { - Task { await displayError(.passwordsDontMatch) } + Task { await displayError(.passwordsDontMatch, primaryButtonCallback: {}) } return } Task { await callback?(.submit(oldPassword: state.bindings.oldPassword, newPassword: state.bindings.newPassword1, - signoutAllDevices: state.bindings.signoutAllDevices)) } + signoutAllDevices: state.bindings.signoutAllDevices)) + } case .toggleSignoutAllDevices: state.bindings.signoutAllDevices.toggle() } } - @MainActor func displayError(_ type: ChangePasswordErrorType) { + @MainActor func displayError(_ type: ChangePasswordErrorType, primaryButtonCallback: @escaping (() -> Void)) { switch type { + case .passwordChangeSucceeded: + state.bindings.alertInfo = AlertInfo(id: .passwordChangeSucceeded, + title: BWIL10n.settingsPasswordChanged, + message: "", + primaryButton: (VectorL10n.ok, action: { primaryButtonCallback() })) case .mxError(let message): state.bindings.alertInfo = AlertInfo(id: type, title: VectorL10n.error, diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift index db6848c9c..1c9ce23d9 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift @@ -21,5 +21,5 @@ protocol ChangePasswordViewModelProtocol { var context: ChangePasswordViewModelType.Context { get } /// Display an error to the user. - @MainActor func displayError(_ type: ChangePasswordErrorType) + @MainActor func displayError(_ type: ChangePasswordErrorType, primaryButtonCallback: @escaping (() -> Void)) } diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift index ef6f8a16d..522b082a3 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift @@ -110,13 +110,18 @@ final class ChangePasswordCoordinator: Coordinator, Presentable { currentTask = Task { [weak self] in do { - try passwordValidator.validate(password: newPassword) - try await parameters.restClient.changePassword(from: oldPassword, to: newPassword, logoutDevices: signoutAllDevices) + try self?.passwordValidator.validate(password: newPassword) + try await self?.parameters.restClient.changePassword(from: oldPassword, to: newPassword, logoutDevices: signoutAllDevices) guard !Task.isCancelled else { return } self?.stopLoading() - self?.callback?() + + if BWIBuildSettings.shared.showPasswordChangedConfirmation { + self?.handleSuccess() + } else { + self?.callback?() + } } catch { self?.stopLoading() self?.handleError(error) @@ -128,14 +133,21 @@ final class ChangePasswordCoordinator: Coordinator, Presentable { @MainActor private func handleError(_ error: Error) { if let mxError = MXError(nsError: error as NSError) { let message = mxError.authenticationErrorMessage() - changePasswordViewModel.displayError(.mxError(message)) + changePasswordViewModel.displayError(.mxError(message), primaryButtonCallback: {}) return } if let error = error as? PasswordValidatorError { - changePasswordViewModel.displayError(.mxError(error.localizedDescription)) + changePasswordViewModel.displayError(.mxError(error.localizedDescription), primaryButtonCallback: {}) } else { - changePasswordViewModel.displayError(.unknown) + changePasswordViewModel.displayError(.unknown, primaryButtonCallback: {}) } } + + // bwi: 4951 - password changed confirmation + @MainActor private func handleSuccess() { + changePasswordViewModel.displayError(.passwordChangeSucceeded, primaryButtonCallback: { [weak self] in + self?.callback?() + }) + } }