Merge branch 'develop' into riot_2890

This commit is contained in:
manuroe
2020-01-16 09:33:57 +01:00
committed by GitHub
55 changed files with 2515 additions and 99 deletions
@@ -25,7 +25,6 @@ final class DeviceVerificationDataLoadingCoordinator: DeviceVerificationDataLoad
// MARK: Private
private let session: MXSession
private var deviceVerificationDataLoadingViewModel: DeviceVerificationDataLoadingViewModelType
private let deviceVerificationDataLoadingViewController: DeviceVerificationDataLoadingViewController
@@ -39,9 +38,14 @@ final class DeviceVerificationDataLoadingCoordinator: DeviceVerificationDataLoad
// MARK: - Setup
init(session: MXSession, otherUserId: String, otherDeviceId: String) {
self.session = session
let deviceVerificationDataLoadingViewModel = DeviceVerificationDataLoadingViewModel(session: self.session, otherUserId: otherUserId, otherDeviceId: otherDeviceId)
let deviceVerificationDataLoadingViewModel = DeviceVerificationDataLoadingViewModel(session: session, otherUserId: otherUserId, otherDeviceId: otherDeviceId)
let deviceVerificationDataLoadingViewController = DeviceVerificationDataLoadingViewController.instantiate(with: deviceVerificationDataLoadingViewModel)
self.deviceVerificationDataLoadingViewModel = deviceVerificationDataLoadingViewModel
self.deviceVerificationDataLoadingViewController = deviceVerificationDataLoadingViewController
}
init(incomingKeyVerificationRequest: MXKeyVerificationRequest) {
let deviceVerificationDataLoadingViewModel = DeviceVerificationDataLoadingViewModel(keyVerificationRequest: incomingKeyVerificationRequest)
let deviceVerificationDataLoadingViewController = DeviceVerificationDataLoadingViewController.instantiate(with: deviceVerificationDataLoadingViewModel)
self.deviceVerificationDataLoadingViewModel = deviceVerificationDataLoadingViewModel
self.deviceVerificationDataLoadingViewController = deviceVerificationDataLoadingViewController
@@ -60,6 +64,11 @@ final class DeviceVerificationDataLoadingCoordinator: DeviceVerificationDataLoad
// MARK: - DeviceVerificationDataLoadingViewModelCoordinatorDelegate
extension DeviceVerificationDataLoadingCoordinator: DeviceVerificationDataLoadingViewModelCoordinatorDelegate {
func deviceVerificationDataLoadingViewModel(_ viewModel: DeviceVerificationDataLoadingViewModelType, didAcceptKeyVerificationWithTransaction transaction: MXDeviceVerificationTransaction) {
self.delegate?.deviceVerificationDataLoadingCoordinator(self, didAcceptKeyVerificationRequestWithTransaction: transaction)
}
func deviceVerificationDataLoadingViewModel(_ viewModel: DeviceVerificationDataLoadingViewModelType, didLoadUser user: MXUser, device: MXDeviceInfo) {
self.delegate?.deviceVerificationDataLoadingCoordinator(self, didLoadUser: user, device: device)
}
@@ -20,6 +20,7 @@ import Foundation
protocol DeviceVerificationDataLoadingCoordinatorDelegate: class {
func deviceVerificationDataLoadingCoordinator(_ coordinator: DeviceVerificationDataLoadingCoordinatorType, didLoadUser user: MXUser, device: MXDeviceInfo)
func deviceVerificationDataLoadingCoordinator(_ coordinator: DeviceVerificationDataLoadingCoordinatorType, didAcceptKeyVerificationRequestWithTransaction transaction: MXDeviceVerificationTransaction)
func deviceVerificationDataLoadingCoordinatorDidCancel(_ coordinator: DeviceVerificationDataLoadingCoordinatorType)
}
@@ -112,9 +112,35 @@ final class DeviceVerificationDataLoadingViewController: UIViewController {
}
private func render(error: Error) {
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: {
self.viewModel.process(viewAction: .cancel)
})
var shouldDisplayError = true
var message: String?
switch error {
case DeviceVerificationDataLoadingViewModelError.transactionCancelled:
message = VectorL10n.deviceVerificationCancelled
case DeviceVerificationDataLoadingViewModelError.transactionCancelledByMe(reason: let reason):
if reason.value != MXTransactionCancelCode.user().value {
message = VectorL10n.deviceVerificationCancelledByMe(reason.humanReadable)
} else {
shouldDisplayError = false
}
default:
break
}
if shouldDisplayError {
let completion = {
self.viewModel.process(viewAction: .cancel)
}
if let message = message {
self.errorPresenter.presentError(from: self, title: "", message: message, animated: true, handler: completion)
} else {
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: completion)
}
}
}
private func renderError(message: String) {
@@ -20,6 +20,8 @@ import Foundation
enum DeviceVerificationDataLoadingViewModelError: Error {
case unknown
case transactionCancelled
case transactionCancelledByMe(reason: MXTransactionCancelCode)
}
final class DeviceVerificationDataLoadingViewModel: DeviceVerificationDataLoadingViewModelType {
@@ -28,9 +30,13 @@ final class DeviceVerificationDataLoadingViewModel: DeviceVerificationDataLoadin
// MARK: Private
private let session: MXSession
private let otherUserId: String
private let otherDeviceId: String
private let session: MXSession?
private let otherUserId: String?
private let otherDeviceId: String?
private let keyVerificationRequest: MXKeyVerificationRequest?
private var currentOperation: MXHTTPOperation?
// MARK: Public
@@ -43,9 +49,18 @@ final class DeviceVerificationDataLoadingViewModel: DeviceVerificationDataLoadin
self.session = session
self.otherUserId = otherUserId
self.otherDeviceId = otherDeviceId
self.keyVerificationRequest = nil
}
init(keyVerificationRequest: MXKeyVerificationRequest) {
self.session = nil
self.otherUserId = nil
self.otherDeviceId = nil
self.keyVerificationRequest = keyVerificationRequest
}
deinit {
self.currentOperation?.cancel()
}
// MARK: - Public
@@ -60,40 +75,74 @@ final class DeviceVerificationDataLoadingViewModel: DeviceVerificationDataLoadin
}
// MARK: - Private
private func loadData() {
guard let crypto = self.session.crypto else {
if let keyVerificationRequest = self.keyVerificationRequest {
self.acceptKeyVerificationRequest(keyVerificationRequest)
} else {
self.downloadOtherDeviceKeys()
}
}
private func acceptKeyVerificationRequest(_ keyVerificationRequest: MXKeyVerificationRequest) {
self.update(viewState: .loading)
keyVerificationRequest.accept(withMethod: MXKeyVerificationMethodSAS, success: { [weak self] (deviceVerificationTransaction) in
guard let self = self else {
return
}
if let outgoingSASTransaction = deviceVerificationTransaction as? MXOutgoingSASTransaction {
self.registerTransactionDidStateChangeNotification(transaction: outgoingSASTransaction)
} else {
self.update(viewState: .error(DeviceVerificationDataLoadingViewModelError.unknown))
}
}, failure: { [weak self] (error) in
guard let self = self else {
return
}
self.update(viewState: .error(error))
})
}
private func downloadOtherDeviceKeys() {
guard let session = self.session,
let crypto = session.crypto,
let otherUserId = self.otherUserId,
let otherDeviceId = self.otherDeviceId else {
self.update(viewState: .errorMessage(VectorL10n.deviceVerificationErrorCannotLoadDevice))
NSLog("[DeviceVerificationDataLoadingViewModel] Error session.crypto is nil")
return
}
if let otherUser = self.session.user(withUserId: otherUserId) {
if let otherUser = session.user(withUserId: otherUserId) {
self.update(viewState: .loading)
crypto.downloadKeys([self.otherUserId], forceDownload: false, success: { [weak self] (usersDevicesMap, crossSigningKeysMap) in
self.currentOperation = crypto.downloadKeys([otherUserId], forceDownload: false, success: { [weak self] (usersDevicesMap, crossSigningKeysMap) in
guard let sself = self else {
return
}
if let otherDevice = usersDevicesMap?.object(forDevice: sself.otherDeviceId, forUser: sself.otherUserId) {
if let otherDevice = usersDevicesMap?.object(forDevice: otherDeviceId, forUser: otherUserId) {
sself.update(viewState: .loaded)
sself.coordinatorDelegate?.deviceVerificationDataLoadingViewModel(sself, didLoadUser: otherUser, device: otherDevice)
} else {
sself.update(viewState: .errorMessage(VectorL10n.deviceVerificationErrorCannotLoadDevice))
}
}, failure: { [weak self] (error) in
guard let sself = self else {
return
sself.update(viewState: .errorMessage(VectorL10n.deviceVerificationErrorCannotLoadDevice))
}
let finalError = error ?? DeviceVerificationDataLoadingViewModelError.unknown
sself.update(viewState: .error(finalError))
}, failure: { [weak self] (error) in
guard let sself = self else {
return
}
let finalError = error ?? DeviceVerificationDataLoadingViewModelError.unknown
sself.update(viewState: .error(finalError))
})
} else {
self.update(viewState: .errorMessage(VectorL10n.deviceVerificationErrorCannotLoadDevice))
}
@@ -102,4 +151,38 @@ final class DeviceVerificationDataLoadingViewModel: DeviceVerificationDataLoadin
private func update(viewState: DeviceVerificationDataLoadingViewState) {
self.viewDelegate?.deviceVerificationDataLoadingViewModel(self, didUpdateViewState: viewState)
}
// MARK: MXDeviceVerificationTransactionDidChange
private func registerTransactionDidStateChangeNotification(transaction: MXOutgoingSASTransaction) {
NotificationCenter.default.addObserver(self, selector: #selector(transactionDidStateChange(notification:)), name: NSNotification.Name.MXDeviceVerificationTransactionDidChange, object: transaction)
}
private func unregisterTransactionDidStateChangeNotification() {
NotificationCenter.default.removeObserver(self, name: .MXDeviceVerificationTransactionDidChange, object: nil)
}
@objc private func transactionDidStateChange(notification: Notification) {
guard let transaction = notification.object as? MXOutgoingSASTransaction else {
return
}
switch transaction.state {
case MXSASTransactionStateShowSAS:
self.unregisterTransactionDidStateChangeNotification()
self.update(viewState: .loaded)
self.coordinatorDelegate?.deviceVerificationDataLoadingViewModel(self, didAcceptKeyVerificationWithTransaction: transaction)
case MXSASTransactionStateCancelled:
self.unregisterTransactionDidStateChangeNotification()
self.update(viewState: .error(DeviceVerificationDataLoadingViewModelError.transactionCancelled))
case MXSASTransactionStateCancelledByMe:
guard let reason = transaction.reasonCancelCode else {
return
}
self.unregisterTransactionDidStateChangeNotification()
self.update(viewState: .error(DeviceVerificationDataLoadingViewModelError.transactionCancelledByMe(reason: reason)))
default:
break
}
}
}
@@ -24,6 +24,7 @@ protocol DeviceVerificationDataLoadingViewModelViewDelegate: class {
protocol DeviceVerificationDataLoadingViewModelCoordinatorDelegate: class {
func deviceVerificationDataLoadingViewModel(_ viewModel: DeviceVerificationDataLoadingViewModelType, didLoadUser user: MXUser, device: MXDeviceInfo)
func deviceVerificationDataLoadingViewModel(_ viewModel: DeviceVerificationDataLoadingViewModelType, didAcceptKeyVerificationWithTransaction transaction: MXDeviceVerificationTransaction)
func deviceVerificationDataLoadingViewModelDidCancel(_ viewModel: DeviceVerificationDataLoadingViewModelType)
}