diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index abd1ef9ad..e3de014c9 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -47,6 +47,14 @@ 3232ABA9225730E100AD6A5C /* DeviceVerificationStartViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232AB9E225730E100AD6A5C /* DeviceVerificationStartViewModel.swift */; }; 3232ABAA225730E100AD6A5C /* DeviceVerificationCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232AB9F225730E100AD6A5C /* DeviceVerificationCoordinatorBridgePresenter.swift */; }; 3232ABAB225730E100AD6A5C /* DeviceVerificationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABA0225730E100AD6A5C /* DeviceVerificationCoordinator.swift */; }; + 3232ABB52257BE6400AD6A5C /* DeviceVerificationVerifyCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABAD2257BE6400AD6A5C /* DeviceVerificationVerifyCoordinatorType.swift */; }; + 3232ABB62257BE6400AD6A5C /* DeviceVerificationVerifyViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3232ABAE2257BE6400AD6A5C /* DeviceVerificationVerifyViewController.storyboard */; }; + 3232ABB72257BE6400AD6A5C /* DeviceVerificationVerifyViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABAF2257BE6400AD6A5C /* DeviceVerificationVerifyViewModelType.swift */; }; + 3232ABB82257BE6500AD6A5C /* DeviceVerificationVerifyCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABB02257BE6400AD6A5C /* DeviceVerificationVerifyCoordinator.swift */; }; + 3232ABB92257BE6500AD6A5C /* DeviceVerificationVerifyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABB12257BE6400AD6A5C /* DeviceVerificationVerifyViewController.swift */; }; + 3232ABBA2257BE6500AD6A5C /* DeviceVerificationVerifyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABB22257BE6400AD6A5C /* DeviceVerificationVerifyViewModel.swift */; }; + 3232ABBB2257BE6500AD6A5C /* DeviceVerificationVerifyViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABB32257BE6400AD6A5C /* DeviceVerificationVerifyViewState.swift */; }; + 3232ABBC2257BE6500AD6A5C /* DeviceVerificationVerifyViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABB42257BE6400AD6A5C /* DeviceVerificationVerifyViewAction.swift */; }; 3233F7461F3497E2006ACA81 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; }; 3233F7471F3497E2006ACA81 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3275FD8C21A5A2C500B9C13D /* TermsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3275FD8B21A5A2C500B9C13D /* TermsView.swift */; }; @@ -527,6 +535,14 @@ 3232AB9E225730E100AD6A5C /* DeviceVerificationStartViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationStartViewModel.swift; sourceTree = ""; }; 3232AB9F225730E100AD6A5C /* DeviceVerificationCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationCoordinatorBridgePresenter.swift; sourceTree = ""; }; 3232ABA0225730E100AD6A5C /* DeviceVerificationCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationCoordinator.swift; sourceTree = ""; }; + 3232ABAD2257BE6400AD6A5C /* DeviceVerificationVerifyCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifyCoordinatorType.swift; sourceTree = ""; }; + 3232ABAE2257BE6400AD6A5C /* DeviceVerificationVerifyViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = DeviceVerificationVerifyViewController.storyboard; sourceTree = ""; }; + 3232ABAF2257BE6400AD6A5C /* DeviceVerificationVerifyViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifyViewModelType.swift; sourceTree = ""; }; + 3232ABB02257BE6400AD6A5C /* DeviceVerificationVerifyCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifyCoordinator.swift; sourceTree = ""; }; + 3232ABB12257BE6400AD6A5C /* DeviceVerificationVerifyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifyViewController.swift; sourceTree = ""; }; + 3232ABB22257BE6400AD6A5C /* DeviceVerificationVerifyViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifyViewModel.swift; sourceTree = ""; }; + 3232ABB32257BE6400AD6A5C /* DeviceVerificationVerifyViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifyViewState.swift; sourceTree = ""; }; + 3232ABB42257BE6400AD6A5C /* DeviceVerificationVerifyViewAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifyViewAction.swift; sourceTree = ""; }; 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = ""; }; 3267EFB320E379FD00FF1CAA /* CHANGES.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGES.rst; sourceTree = ""; }; 3267EFB420E379FD00FF1CAA /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; @@ -1292,6 +1308,7 @@ isa = PBXGroup; children = ( 3232AB96225730E100AD6A5C /* Start */, + 3232ABAC2257BE6400AD6A5C /* Verify */, 3232AB95225730E100AD6A5C /* DeviceVerificationCoordinatorType.swift */, 3232AB9F225730E100AD6A5C /* DeviceVerificationCoordinatorBridgePresenter.swift */, 3232ABA0225730E100AD6A5C /* DeviceVerificationCoordinator.swift */, @@ -1314,6 +1331,21 @@ path = Start; sourceTree = ""; }; + 3232ABAC2257BE6400AD6A5C /* Verify */ = { + isa = PBXGroup; + children = ( + 3232ABAD2257BE6400AD6A5C /* DeviceVerificationVerifyCoordinatorType.swift */, + 3232ABAE2257BE6400AD6A5C /* DeviceVerificationVerifyViewController.storyboard */, + 3232ABAF2257BE6400AD6A5C /* DeviceVerificationVerifyViewModelType.swift */, + 3232ABB02257BE6400AD6A5C /* DeviceVerificationVerifyCoordinator.swift */, + 3232ABB12257BE6400AD6A5C /* DeviceVerificationVerifyViewController.swift */, + 3232ABB22257BE6400AD6A5C /* DeviceVerificationVerifyViewModel.swift */, + 3232ABB32257BE6400AD6A5C /* DeviceVerificationVerifyViewState.swift */, + 3232ABB42257BE6400AD6A5C /* DeviceVerificationVerifyViewAction.swift */, + ); + path = Verify; + sourceTree = ""; + }; 3233F7291F31F3B4006ACA81 /* libs */ = { isa = PBXGroup; children = ( @@ -3403,6 +3435,7 @@ B1B557B320EF5AEF00210D55 /* EventDetailsView.xib in Resources */, B1B557DD20EF5FBB00210D55 /* FilesSearchTableViewCell.xib in Resources */, B1B5590320EF768F00210D55 /* RoomSelectedStickerBubbleCell.xib in Resources */, + 3232ABB62257BE6400AD6A5C /* DeviceVerificationVerifyViewController.storyboard in Resources */, B1B5573F20EE6C4D00210D55 /* SegmentedViewController.xib in Resources */, B1B5581E20EF625800210D55 /* RoomTitleView.xib in Resources */, B1B558C020EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib in Resources */, @@ -3639,6 +3672,7 @@ B1B5598820EFC3E000210D55 /* WidgetManager.m in Sources */, B1DB4F0E22316FFF0065DBFA /* UserNameColorGenerator.swift in Sources */, B1057789221304EC00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.swift in Sources */, + 3232ABB72257BE6400AD6A5C /* DeviceVerificationVerifyViewModelType.swift in Sources */, B16932B120F3AC9200746532 /* RoomSearchDataSource.m in Sources */, B16932A320F3A21C00746532 /* main.m in Sources */, B1B5574520EE6C4D00210D55 /* StartChatViewController.m in Sources */, @@ -3707,6 +3741,7 @@ B1B5573D20EE6C4D00210D55 /* WebViewViewController.m in Sources */, 3209451221F1C1430088CAA2 /* BlackTheme.swift in Sources */, B1B5572720EE6C4D00210D55 /* RoomSearchViewController.m in Sources */, + 3232ABBC2257BE6500AD6A5C /* DeviceVerificationVerifyViewAction.swift in Sources */, F05927C91FDED836009F2A68 /* MXGroup+Riot.m in Sources */, B1B5594520EF7BD000210D55 /* TableViewCellWithCollectionView.m in Sources */, F083BDEF1E7009ED00A9B29C /* UINavigationController+Riot.m in Sources */, @@ -3731,6 +3766,7 @@ B1B5582C20EF666100210D55 /* DirectoryRecentTableViewCell.m in Sources */, B1B558E420EF768F00210D55 /* RoomMembershipWithPaginationTitleBubbleCell.m in Sources */, B1B5573620EE6C4D00210D55 /* GroupsViewController.m in Sources */, + 3232ABB82257BE6500AD6A5C /* DeviceVerificationVerifyCoordinator.swift in Sources */, B1B5572A20EE6C4D00210D55 /* RoomMemberDetailsViewController.m in Sources */, B1B5590120EF768F00210D55 /* RoomMembershipExpandedWithPaginationTitleBubbleCell.m in Sources */, B1B558C920EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */, @@ -3742,6 +3778,7 @@ 3232AB4F2256558300AD6A5C /* TemplateScreenViewController.swift in Sources */, B1B558FC20EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B5572920EE6C4D00210D55 /* RoomFilesViewController.m in Sources */, + 3232ABBA2257BE6500AD6A5C /* DeviceVerificationVerifyViewModel.swift in Sources */, B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */, B1B558E020EF768F00210D55 /* RoomOutgoingTextMsgBubbleCell.m in Sources */, B1B5593C20EF7BAC00210D55 /* TableViewCellWithCheckBoxes.m in Sources */, @@ -3749,6 +3786,7 @@ F0D2ADA11F6AA5FD00A7097D /* MXRoomSummary+Riot.m in Sources */, B1B5596F20EFA85D00210D55 /* EncryptionInfoView.m in Sources */, B1B5573820EE6C4D00210D55 /* GroupParticipantsViewController.m in Sources */, + 3232ABBB2257BE6500AD6A5C /* DeviceVerificationVerifyViewState.swift in Sources */, 3232ABAB225730E100AD6A5C /* DeviceVerificationCoordinator.swift in Sources */, B1B5583E20EF6E7F00210D55 /* GroupRoomTableViewCell.m in Sources */, B14F143522144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewController.swift in Sources */, @@ -3823,6 +3861,7 @@ B1B558C820EF768F00210D55 /* RoomIncomingEncryptedAttachmentBubbleCell.m in Sources */, B1B557C620EF5CD400210D55 /* DirectoryServerDetailTableViewCell.m in Sources */, B1B5590920EF768F00210D55 /* RoomEmptyBubbleCell.m in Sources */, + 3232ABB92257BE6500AD6A5C /* DeviceVerificationVerifyViewController.swift in Sources */, B139C21F21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift in Sources */, B1B5574720EE6C4D00210D55 /* UsersDevicesViewController.m in Sources */, B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */, @@ -3858,6 +3897,7 @@ F083BDF91E7009ED00A9B29C /* RoomEmailInvitation.m in Sources */, B1B5572C20EE6C4D00210D55 /* RoomParticipantsViewController.m in Sources */, B1B558EE20EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.m in Sources */, + 3232ABB52257BE6400AD6A5C /* DeviceVerificationVerifyCoordinatorType.swift in Sources */, 32BF994F21FA29A400698084 /* SettingsKeyBackupViewModel.swift in Sources */, B1B5574920EE6C4D00210D55 /* RiotSplitViewController.m in Sources */, B1B5574E20EE6C4D00210D55 /* DirectoryServerPickerViewController.m in Sources */, diff --git a/Riot/Generated/Storyboards.swift b/Riot/Generated/Storyboards.swift index ee9cee1c8..53dd3798f 100644 --- a/Riot/Generated/Storyboards.swift +++ b/Riot/Generated/Storyboards.swift @@ -17,6 +17,11 @@ internal enum StoryboardScene { internal static let initialScene = InitialSceneType(storyboard: DeviceVerificationStartViewController.self) } + internal enum DeviceVerificationVerifyViewController: StoryboardType { + internal static let storyboardName = "DeviceVerificationVerifyViewController" + + internal static let initialScene = InitialSceneType(storyboard: DeviceVerificationVerifyViewController.self) + } internal enum KeyBackupRecoverFromPassphraseViewController: StoryboardType { internal static let storyboardName = "KeyBackupRecoverFromPassphraseViewController" diff --git a/Riot/Modules/DeviceVerification/DeviceVerificationCoordinator.swift b/Riot/Modules/DeviceVerification/DeviceVerificationCoordinator.swift index cb61de551..79c3ac493 100644 --- a/Riot/Modules/DeviceVerification/DeviceVerificationCoordinator.swift +++ b/Riot/Modules/DeviceVerification/DeviceVerificationCoordinator.swift @@ -107,15 +107,29 @@ final class DeviceVerificationCoordinator: DeviceVerificationCoordinatorType { coordinator.delegate = self return coordinator } + + private func showVerify(animated: Bool) { + guard let transaction = self.transaction else { + return + } + + let coordinator = DeviceVerificationVerifyCoordinator(session: self.session, transaction: transaction) + coordinator.delegate = self + coordinator.start() + + // TODO: Do not push, replace + self.add(childCoordinator: coordinator) + self.navigationRouter.push(coordinator, animated: animated) { [weak self] in + self?.remove(childCoordinator: coordinator) + } + } } -// MARK: - DeviceVerificationStartCoordinatorDelegate extension DeviceVerificationCoordinator: DeviceVerificationStartCoordinatorDelegate { func deviceVerificationStartCoordinator(_ coordinator: DeviceVerificationStartCoordinatorType, didCompleteWithOutgoingTransaction transaction: MXSASTransaction) { self.transaction = transaction - // TODO - self.delegate?.deviceVerificationCoordinatorDidComplete(self) + self.showVerify(animated: true) } func deviceVerificationStartCoordinator(_ coordinator: DeviceVerificationStartCoordinatorType, didTransactionCancelled transaction: MXSASTransaction) { @@ -128,3 +142,13 @@ extension DeviceVerificationCoordinator: DeviceVerificationStartCoordinatorDeleg self.delegate?.deviceVerificationCoordinatorDidComplete(self) } } + +extension DeviceVerificationCoordinator: DeviceVerificationVerifyCoordinatorDelegate { + func deviceVerificationVerifyCoordinatorDidComplete(_ coordinator: DeviceVerificationVerifyCoordinatorType) { + self.delegate?.deviceVerificationCoordinatorDidComplete(self) + } + + func deviceVerificationVerifyCoordinatorDidCancel(_ coordinator: DeviceVerificationVerifyCoordinatorType) { + self.delegate?.deviceVerificationCoordinatorDidComplete(self) + } +} diff --git a/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyCoordinator.swift b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyCoordinator.swift new file mode 100644 index 000000000..932ea64c6 --- /dev/null +++ b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyCoordinator.swift @@ -0,0 +1,71 @@ +// File created from ScreenTemplate +// $ createScreen.sh DeviceVerification/Verify DeviceVerificationVerify +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import Foundation +import UIKit + +final class DeviceVerificationVerifyCoordinator: DeviceVerificationVerifyCoordinatorType { + + // MARK: - Properties + + // MARK: Private + + private let session: MXSession + private var deviceVerificationVerifyViewModel: DeviceVerificationVerifyViewModelType + private let deviceVerificationVerifyViewController: DeviceVerificationVerifyViewController + + // MARK: Public + + // Must be used only internally + var childCoordinators: [Coordinator] = [] + + weak var delegate: DeviceVerificationVerifyCoordinatorDelegate? + + // MARK: - Setup + + init(session: MXSession, transaction: MXSASTransaction) { + self.session = session + + let deviceVerificationVerifyViewModel = DeviceVerificationVerifyViewModel(session: self.session, transaction:transaction) + let deviceVerificationVerifyViewController = DeviceVerificationVerifyViewController.instantiate(with: deviceVerificationVerifyViewModel) + self.deviceVerificationVerifyViewModel = deviceVerificationVerifyViewModel + self.deviceVerificationVerifyViewController = deviceVerificationVerifyViewController + } + + // MARK: - Public methods + + func start() { + self.deviceVerificationVerifyViewModel.coordinatorDelegate = self + } + + func toPresentable() -> UIViewController { + return self.deviceVerificationVerifyViewController + } +} + +// MARK: - DeviceVerificationVerifyViewModelCoordinatorDelegate +extension DeviceVerificationVerifyCoordinator: DeviceVerificationVerifyViewModelCoordinatorDelegate { + + func deviceVerificationVerifyViewModelDidComplete(_ viewModel: DeviceVerificationVerifyViewModelType) { + self.delegate?.deviceVerificationVerifyCoordinatorDidComplete(self) + } + + func deviceVerificationVerifyViewModelDidCancel(_ viewModel: DeviceVerificationVerifyViewModelType) { + self.delegate?.deviceVerificationVerifyCoordinatorDidCancel(self) + } +} diff --git a/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyCoordinatorType.swift b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyCoordinatorType.swift new file mode 100644 index 000000000..d9816480b --- /dev/null +++ b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyCoordinatorType.swift @@ -0,0 +1,29 @@ +// File created from ScreenTemplate +// $ createScreen.sh DeviceVerification/Verify DeviceVerificationVerify +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import Foundation + +protocol DeviceVerificationVerifyCoordinatorDelegate: class { + func deviceVerificationVerifyCoordinatorDidComplete(_ coordinator: DeviceVerificationVerifyCoordinatorType) + func deviceVerificationVerifyCoordinatorDidCancel(_ coordinator: DeviceVerificationVerifyCoordinatorType) +} + +/// `DeviceVerificationVerifyCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow. +protocol DeviceVerificationVerifyCoordinatorType: Coordinator, Presentable { + var delegate: DeviceVerificationVerifyCoordinatorDelegate? { get } +} diff --git a/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewAction.swift b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewAction.swift new file mode 100644 index 000000000..5ed5933c6 --- /dev/null +++ b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewAction.swift @@ -0,0 +1,26 @@ +// File created from ScreenTemplate +// $ createScreen.sh DeviceVerification/Verify DeviceVerificationVerify +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import Foundation + +/// DeviceVerificationVerifyViewController view actions exposed to view model +enum DeviceVerificationVerifyViewAction { + case confirm + case complete + case cancel +} diff --git a/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewController.storyboard b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewController.storyboard new file mode 100644 index 000000000..9b95e7e5c --- /dev/null +++ b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewController.storyboard @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewController.swift b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewController.swift new file mode 100644 index 000000000..00760d4fb --- /dev/null +++ b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewController.swift @@ -0,0 +1,185 @@ +// File created from ScreenTemplate +// $ createScreen.sh DeviceVerification/Verify DeviceVerificationVerify +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import UIKit + +final class DeviceVerificationVerifyViewController: UIViewController { + + // MARK: - Constants + + private enum Constants { + static let aConstant: Int = 666 + } + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var scrollView: UIScrollView! + + @IBOutlet private weak var messageLabel: UILabel! + @IBOutlet private weak var okButton: UIButton! + + // MARK: Private + + private var viewModel: DeviceVerificationVerifyViewModelType! + private var theme: Theme! + private var keyboardAvoider: KeyboardAvoider? + private var errorPresenter: MXKErrorPresentation! + private var activityPresenter: ActivityIndicatorPresenter! + + // MARK: - Setup + + class func instantiate(with viewModel: DeviceVerificationVerifyViewModelType) -> DeviceVerificationVerifyViewController { + let viewController = StoryboardScene.DeviceVerificationVerifyViewController.initialScene.instantiate() + viewController.viewModel = viewModel + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = "Template" + + self.setupViews() + self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.scrollView) + self.activityPresenter = ActivityIndicatorPresenter() + self.errorPresenter = MXKErrorAlertPresentation() + + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + + self.viewModel.viewDelegate = self + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + self.keyboardAvoider?.startAvoiding() + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + self.keyboardAvoider?.stopAvoiding() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + + // TODO: + self.messageLabel.textColor = theme.textPrimaryColor + + self.okButton.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.okButton) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + private func setupViews() { + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in + self?.cancelButtonAction() + } + + self.navigationItem.rightBarButtonItem = cancelBarButtonItem + + self.scrollView.keyboardDismissMode = .interactive + + self.messageLabel.text = "VectorL10n.deviceVerificationVerifyTitle" + self.messageLabel.isHidden = true + } + + private func render(viewState: DeviceVerificationVerifyViewState) { + switch viewState { + case .loading: + self.renderLoading() + case .loaded: + self.renderLoaded() + case .error(let error): + self.render(error: error) + } + } + + private func renderLoading() { + self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) + } + + private func renderLoaded() { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + + self.messageLabel.text = "TODO" + self.messageLabel.isHidden = false + } + + private func render(error: Error) { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + } + + + // MARK: - Actions + + @IBAction private func okButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .complete) + } + + private func cancelButtonAction() { + self.viewModel.process(viewAction: .cancel) + } +} + + +// MARK: - DeviceVerificationVerifyViewModelViewDelegate +extension DeviceVerificationVerifyViewController: DeviceVerificationVerifyViewModelViewDelegate { + + func deviceVerificationVerifyViewModel(_ viewModel: DeviceVerificationVerifyViewModelType, didUpdateViewState viewSate: DeviceVerificationVerifyViewState) { + self.render(viewState: viewSate) + } +} diff --git a/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewModel.swift b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewModel.swift new file mode 100644 index 000000000..65f56aeda --- /dev/null +++ b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewModel.swift @@ -0,0 +1,69 @@ +// File created from ScreenTemplate +// $ createScreen.sh DeviceVerification/Verify DeviceVerificationVerify +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import Foundation + +final class DeviceVerificationVerifyViewModel: DeviceVerificationVerifyViewModelType { + + // MARK: - Properties + + // MARK: Private + + private let session: MXSession + private let transaction: MXSASTransaction + + // MARK: Public + + weak var viewDelegate: DeviceVerificationVerifyViewModelViewDelegate? + weak var coordinatorDelegate: DeviceVerificationVerifyViewModelCoordinatorDelegate? + + // MARK: - Setup + + init(session: MXSession, transaction: MXSASTransaction) { + self.session = session + self.transaction = transaction + } + + deinit { + } + + // MARK: - Public + + func process(viewAction: DeviceVerificationVerifyViewAction) { + switch viewAction { + case .confirm: + self.confirm() + case .complete: + self.coordinatorDelegate?.deviceVerificationVerifyViewModelDidComplete(self) + case .cancel: + self.coordinatorDelegate?.deviceVerificationVerifyViewModelDidCancel(self) + } + } + + // MARK: - Private + + private func confirm() { + self.update(viewState: .loading) + + // TODO + } + + private func update(viewState: DeviceVerificationVerifyViewState) { + self.viewDelegate?.deviceVerificationVerifyViewModel(self, didUpdateViewState: viewState) + } +} diff --git a/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewModelType.swift b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewModelType.swift new file mode 100644 index 000000000..348e7f927 --- /dev/null +++ b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewModelType.swift @@ -0,0 +1,37 @@ +// File created from ScreenTemplate +// $ createScreen.sh DeviceVerification/Verify DeviceVerificationVerify +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import Foundation + +protocol DeviceVerificationVerifyViewModelViewDelegate: class { + func deviceVerificationVerifyViewModel(_ viewModel: DeviceVerificationVerifyViewModelType, didUpdateViewState viewSate: DeviceVerificationVerifyViewState) +} + +protocol DeviceVerificationVerifyViewModelCoordinatorDelegate: class { + func deviceVerificationVerifyViewModelDidComplete(_ viewModel: DeviceVerificationVerifyViewModelType) + func deviceVerificationVerifyViewModelDidCancel(_ viewModel: DeviceVerificationVerifyViewModelType) +} + +/// Protocol describing the view model used by `DeviceVerificationVerifyViewController` +protocol DeviceVerificationVerifyViewModelType { + + var viewDelegate: DeviceVerificationVerifyViewModelViewDelegate? { get set } + var coordinatorDelegate: DeviceVerificationVerifyViewModelCoordinatorDelegate? { get set } + + func process(viewAction: DeviceVerificationVerifyViewAction) +} diff --git a/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewState.swift b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewState.swift new file mode 100644 index 000000000..bccd66485 --- /dev/null +++ b/Riot/Modules/DeviceVerification/Verify/DeviceVerificationVerifyViewState.swift @@ -0,0 +1,26 @@ +// File created from ScreenTemplate +// $ createScreen.sh DeviceVerification/Verify DeviceVerificationVerify +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import Foundation + +/// DeviceVerificationVerifyViewController view state +enum DeviceVerificationVerifyViewState { + case loading + case loaded + case error(Error) +}