diff --git a/Riot/Assets/de.lproj/Bwi.strings b/Riot/Assets/de.lproj/Bwi.strings index 411a8aeca..023d04dd6 100644 --- a/Riot/Assets/de.lproj/Bwi.strings +++ b/Riot/Assets/de.lproj/Bwi.strings @@ -321,6 +321,7 @@ "key_verification_verified_this_session_information" = "Deine Anmeldung wurde erfolgreich verifiziert."; "key_verification_verified_other_session_information" = "Deine Anmeldung wurde erfolgreich verifiziert."; "key_verification_tile_request_alert_title" = "Verifizierung angefragt"; +"device_verification_crosssigning_wait_recover_secrets" = "Mit anderem Gerät verifizieren"; // MARK: - Secrets Recovery @@ -356,6 +357,9 @@ "secrets_reset_warning_message" = "Du verlierst dadurch deinen gesamten bisherigen Nachrichtenverlauf, sowie verfizierte Geräte oder Nutzer!"; "secrets_reset_reset_action" = "Zurücksetzen"; "secrets_reset_authentication_message" = "Bestätige mit deinem Passwort!"; +"secrets_recovery_verification_alert_title" = "Anmeldung verifizieren"; +"secrets_recovery_verification_alert_message" = "Eine Verifizierungsanfrage wurde gesendet. Öffne eine deiner anderen Sitzungen, um sie zu akzeptieren und mit der Verifizierung zu beginnen."; +"secrets_recovery_verification_alert_cancel" = "Ok"; // MARK: - PIN Protection diff --git a/Riot/Assets/en.lproj/Bwi.strings b/Riot/Assets/en.lproj/Bwi.strings index 156f50b58..918ed64dd 100644 --- a/Riot/Assets/en.lproj/Bwi.strings +++ b/Riot/Assets/en.lproj/Bwi.strings @@ -242,6 +242,10 @@ "key_verification_verify_qr_code_information_other_device" = "Scan code either with this device or another."; "key_verification_verify_qr_code_cannot_scan_action" = "Compare with emojis instead"; "key_verification_tile_request_alert_title" = "Verification requested"; +"device_verification_crosssigning_wait_recover_secrets" = "Verify with other device"; +"secrets_recovery_verification_alert_title" = "Verify"; +"secrets_recovery_verification_alert_message" = "A verification request has been sent. Open one of your sessions to accept and start the verification"; +"secrets_recovery_verification_alert_cancel" = "Ok"; "room_participants_security_information_room_not_encrypted" = "Messages in this room are not end-to-end encrypted."; "room_participants_security_information_room_not_encrypted_for_dm" = "Messages here are not end-to-end encrypted."; diff --git a/Riot/Generated/BWIStrings.swift b/Riot/Generated/BWIStrings.swift index 008debe6e..c4f9e5672 100644 --- a/Riot/Generated/BWIStrings.swift +++ b/Riot/Generated/BWIStrings.swift @@ -731,6 +731,10 @@ public class BWIL10n: NSObject { public static var deviceVerificationCancelled: String { return BWIL10n.tr("Bwi", "device_verification_cancelled") } + /// Mit anderem Gerät verifizieren + public static var deviceVerificationCrosssigningWaitRecoverSecrets: String { + return BWIL10n.tr("Bwi", "device_verification_crosssigning_wait_recover_secrets") + } /// Anmeldung verifizieren public static var deviceVerificationOtherLoginVerifyWaitTitle: String { return BWIL10n.tr("Bwi", "device_verification_other_login_verify_wait_title") @@ -1339,6 +1343,18 @@ public class BWIL10n: NSObject { public static var secretsRecoveryResetActionPart2: String { return BWIL10n.tr("Bwi", "secrets_recovery_reset_action_part_2") } + /// Ok + public static var secretsRecoveryVerificationAlertCancel: String { + return BWIL10n.tr("Bwi", "secrets_recovery_verification_alert_cancel") + } + /// Eine Verifizierungsanfrage wurde gesendet. Öffne eine deiner anderen Sitzungen, um sie zu akzeptieren und mit der Verifizierung zu beginnen. + public static var secretsRecoveryVerificationAlertMessage: String { + return BWIL10n.tr("Bwi", "secrets_recovery_verification_alert_message") + } + /// Anmeldung verifizieren + public static var secretsRecoveryVerificationAlertTitle: String { + return BWIL10n.tr("Bwi", "secrets_recovery_verification_alert_title") + } /// Gib dein Verschlüsselungskennwort ein, um auf deine verschlüsselten Nachrichten und deine Cross-Signing-Identität zuzugreifen. Mit der Cross-Signing-Identität kannst du andere Sitzungen verifizieren. public static var secretsRecoveryWithKeyInformationDefault: String { return BWIL10n.tr("Bwi", "secrets_recovery_with_key_information_default") diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinator.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinator.swift index 4c3281cb0..052dcb94c 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinator.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinator.swift @@ -49,8 +49,9 @@ final class KeyVerificationSelfVerifyWaitCoordinator: KeyVerificationSelfVerifyW // MARK: - Public methods - func start() { + func start() { self.keyVerificationSelfVerifyWaitViewModel.coordinatorDelegate = self + self.keyVerificationSelfVerifyWaitViewModel.checkCrosssigningDevices() } func toPresentable() -> UIViewController { diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.storyboard b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.storyboard index 0dcf70679..733d959a6 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.storyboard +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.storyboard @@ -1,9 +1,9 @@ - + - + @@ -17,13 +17,13 @@ - + - + - + - + @@ -73,12 +73,25 @@ Open Element on one of your other devices and follow the instructions. - + + - + - - + - + diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.swift index 7baaaf89a..5df827d65 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.swift @@ -41,6 +41,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { @IBOutlet private weak var recoverSecretsAvailabilityActivityIndicatorView: UIActivityIndicatorView! @IBOutlet private weak var recoverSecretsContainerView: UIView! @IBOutlet private weak var recoverSecretsButton: RoundedButton! + // bwi #5271 don't do crosssigning request at view start but as action on button click + @IBOutlet private weak var crosssigningButton: RoundedButton! @IBOutlet private weak var recoverSecretsAdditionalInformationLabel: UILabel! // MARK: Private @@ -53,6 +55,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { private weak var cancelBarButtonItem: UIBarButtonItem? + private var verificationAlert: UIAlertController? + // MARK: - Setup class func instantiate(with viewModel: KeyVerificationSelfVerifyWaitViewModelType, cancellable: Bool) -> KeyVerificationSelfVerifyWaitViewController { @@ -75,14 +79,13 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.registerThemeServiceDidChangeThemeNotification() self.update(theme: self.theme) + + self.viewModel.viewDelegate = self } - // BWI resend verificationrequest after cancling QR Code crosssigning override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - self.viewModel.viewDelegate = self - self.viewModel.process(viewAction: .loadData) } @@ -90,6 +93,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { return self.theme.statusBarStyle } + + // MARK: - Private private func update(theme: Theme) { @@ -109,6 +114,7 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.recoverSecretsAvailabilityActivityIndicatorView.color = theme.tintColor // BWI: #4966 self.recoverSecretsButton.update(theme: theme) + self.crosssigningButton.update(theme: theme) } private func registerThemeServiceDidChangeThemeNotification() { @@ -140,8 +146,15 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.mobileClientImageView.image = Asset.Images.smartphone.image.withRenderingMode(.alwaysTemplate) self.recoverSecretsAdditionalInformationLabel.text = BWIL10n.deviceVerificationSelfVerifyWaitRecoverSecretsAdditionalInformation + + self.recoverSecretsButton.setTitle(BWIL10n.deviceVerificationSelfVerifyWaitRecoverSecretsWithPassphrase, for: .normal) + self.crosssigningButton.setTitle(BWIL10n.deviceVerificationCrosssigningWaitRecoverSecrets, for: .normal) + + self.recoverSecretsAvailabilityLoadingContainerView.isHidden = true + + self.crosssigningButton.isHidden = true } - + private func render(viewState: KeyVerificationSelfVerifyWaitViewState) { switch viewState { case .loading: @@ -156,6 +169,10 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.renderCancelledByMe(reason: reason) case .error(let error): self.render(error: error) + case .verificationAccepted: + self.verificationAccepted() + case .crosssigningPossible(let possible): + self.showCrosssigningButton(possible) } } @@ -198,6 +215,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.recoverSecretsAvailabilityActivityIndicatorView.stopAnimating() self.recoverSecretsContainerView.isHidden = hideRecoverSecrets self.recoverSecretsButton.setTitle(recoverSecretsButtonTitle, for: .normal) + + self.showCrosssigningAlert() } private func renderCancelled(reason: MXTransactionCancelCode) { @@ -228,6 +247,35 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { } } + private func verificationAccepted() { + if let alert = self.verificationAlert { + alert.dismiss(animated: false) + } + } + + private func showCrosssigningButton(_ show: Bool) { + self.crosssigningButton.isHidden = !show + self.informationLabel.isHidden = !show + self.desktopClientImageView.isHidden = !show + self.mobileClientImageView.isHidden = !show + } + + // bwi: show an alert when corsssigning button is pressed. This makes it clearer to the user what to do next + private func showCrosssigningAlert() { + self.verificationAlert = UIAlertController(title: BWIL10n.secretsRecoveryVerificationAlertTitle, + message: BWIL10n.secretsRecoveryVerificationAlertMessage, + preferredStyle: .alert) + + if let alert = self.verificationAlert { + let cancelActionTitle = BWIL10n.secretsRecoveryVerificationAlertCancel + let cancelAction = UIAlertAction(title: cancelActionTitle, style: .cancel) + + alert.addAction(cancelAction) + + present(alert, animated: true, completion: nil) + } + } + // MARK: - Actions private func cancelButtonAction() { @@ -237,6 +285,10 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { @IBAction private func recoverSecretsButtonAction(_ sender: Any) { self.viewModel.process(viewAction: .recoverSecrets) } + + @IBAction private func crossSigningButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .loadData) + } } diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift index 2f1b8a2ce..041a6ef43 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift @@ -83,6 +83,18 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai } } + // bwi: only show corsssigning button when there is more than one device in your account + func checkCrosssigningDevices() { + self.session.matrixRestClient.devices { [weak self] response in + switch response { + case .success(let devices): + self?.update(viewState: .crosssigningPossible(devices.count > 1)) + case .failure: + break + } + } + } + // MARK: - Private private func loadData() { @@ -258,6 +270,8 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai } if keyVerificationRequest.state == MXKeyVerificationRequestStateReady { + self.update(viewState: .verificationAccepted) + self.unregisterKeyVerificationRequestChangeNotification() self.coordinatorDelegate?.keyVerificationSelfVerifyWaitViewModel(self, didAcceptKeyVerificationRequest: keyVerificationRequest) diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift index 66027c9e8..7c6f1832b 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift @@ -36,4 +36,6 @@ protocol KeyVerificationSelfVerifyWaitViewModelType { var coordinatorDelegate: KeyVerificationSelfVerifyWaitViewModelCoordinatorDelegate? { get set } func process(viewAction: KeyVerificationSelfVerifyWaitViewAction) + + func checkCrosssigningDevices() } diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewState.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewState.swift index efd500b5e..409726e82 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewState.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewState.swift @@ -36,4 +36,6 @@ enum KeyVerificationSelfVerifyWaitViewState { case cancelled(MXTransactionCancelCode) case cancelledByMe(MXTransactionCancelCode) case error(Error) + case verificationAccepted + case crosssigningPossible(Bool) }