Move presentation of the loading spinner into AuthenticationCoordinator for new users.

Also moves key verification out of a bridge presenter in AuthenticationVC and into the AuthenticationCoordinator.
This commit is contained in:
Doug
2022-02-17 16:50:02 +00:00
parent 3695e25867
commit 3e4aab55cd
10 changed files with 279 additions and 181 deletions
@@ -2410,6 +2410,12 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
MXLogDebug(@"[AppDelegate] handleAppState: isLaunching: %@", isLaunching ? @"YES" : @"NO");
if (self.masterTabBarController.isOnboardingInProgress)
{
MXLogDebug(@"[AppDelegate] handleAppState: Skipping LaunchLoadingView due to Onboarding.");
return;
}
if (isLaunching)
{
MXLogDebug(@"[AppDelegate] handleAppState: LaunchLoadingView");
@@ -16,7 +16,6 @@
limitations under the License.
*/
import Foundation
import UIKit
/// A coordinator that handles authentication, verification and setting a PIN.
@@ -26,17 +25,27 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc
// MARK: Private
private let navigationRouter: NavigationRouterType
private let authenticationViewController: AuthenticationViewController
private let crossSigningService = CrossSigningService()
/// The password entered, for use when setting up cross-signing.
private var password: String?
/// The session created when successfully authenticated.
private var session: MXSession?
// MARK: Public
// Must be used only internally
var childCoordinators: [Coordinator] = []
var completion: ((MXKAuthenticationType) -> Void)?
var completion: ((AuthenticationCoordinatorResult) -> Void)?
// MARK: - Setup
override init() {
init(parameters: AuthenticationCoordinatorParameters) {
self.navigationRouter = parameters.navigationRouter
let authenticationViewController = AuthenticationViewController()
self.authenticationViewController = authenticationViewController
@@ -81,11 +90,157 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc
func continueSSOLogin(withToken loginToken: String, transactionID: String) -> Bool {
authenticationViewController.continueSSOLogin(withToken: loginToken, txnId: transactionID)
}
// MARK: - Private
private func showLoadingAnimation() {
let loadingViewController = LaunchLoadingViewController()
loadingViewController.modalPresentationStyle = .fullScreen
// Replace the navigation stack with the loading animation
// as there is nothing to navigate back to.
navigationRouter.setRootModule(loadingViewController)
}
private func presentCompleteSecurity(with session: MXSession) {
let isNewSignIn = true
let keyVerificationCoordinator = KeyVerificationCoordinator(session: session, flow: .completeSecurity(isNewSignIn))
keyVerificationCoordinator.delegate = self
let presentable = keyVerificationCoordinator.toPresentable()
presentable.presentationController?.delegate = self
navigationRouter.present(presentable, animated: true)
keyVerificationCoordinator.start()
add(childCoordinator: keyVerificationCoordinator)
}
private func authenticationDidComplete() {
completion?(.didComplete(authenticationViewController.authType))
}
private func registerSessionStateChangeNotification(for session: MXSession) {
NotificationCenter.default.addObserver(self, selector: #selector(sessionStateDidChange), name: .mxSessionStateDidChange, object: session)
}
private func unregisterSessionStateChangeNotification() {
NotificationCenter.default.removeObserver(self, name: .mxSessionStateDidChange, object: nil)
}
@objc private func sessionStateDidChange(_ notification: Notification) {
guard let session = notification.object as? MXSession else {
MXLog.error("[AuthenticationCoordinator] sessionStateDidChange: Missing session in the notification")
return
}
if session.state == .storeDataReady {
if let crypto = session.crypto, crypto.crossSigning != nil {
// Do not make key share requests while the "Complete security" is not complete.
// If the device is self-verified, the SDK will restore the existing key backup.
// Then, it will re-enable outgoing key share requests
crypto.setOutgoingKeyRequestsEnabled(false, onComplete: nil)
}
} else if session.state == .running {
unregisterSessionStateChangeNotification()
if let crypto = session.crypto, let crossSigning = crypto.crossSigning {
crossSigning.refreshState { [weak self] stateUpdated in
guard let self = self else { return }
MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: crossSigning.state: \(crossSigning.state)")
switch crossSigning.state {
case .notBootstrapped:
// TODO: This is still not sure we want to disable the automatic cross-signing bootstrap
// if the admin disabled e2e by default.
// Do like riot-web for the moment
if session.vc_homeserverConfiguration().isE2EEByDefaultEnabled {
// Bootstrap cross-signing on user's account
// We do it for both registration and new login as long as cross-signing does not exist yet
if let password = self.password, !password.isEmpty {
MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Bootstrap with password")
crossSigning.setup(withPassword: password) {
MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Bootstrap succeeded")
self.authenticationDidComplete()
} failure: { error in
MXLog.error("[AuthenticationCoordinator] sessionStateDidChange: Bootstrap failed. Error: \(error)")
crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil)
self.authenticationDidComplete()
}
} else {
// Try to setup cross-signing without authentication parameters in case if a grace period is enabled
self.crossSigningService.setupCrossSigningWithoutAuthentication(for: session) {
MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Bootstrap succeeded without credentials")
self.authenticationDidComplete()
} failure: { error in
MXLog.error("[AuthenticationCoordinator] sessionStateDidChange: Do not know how to bootstrap cross-signing. Skip it.")
crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil)
self.authenticationDidComplete()
}
}
} else {
crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil)
self.authenticationDidComplete()
}
case .crossSigningExists:
MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Complete security")
self.presentCompleteSecurity(with: session)
default:
MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Nothing to do")
crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil)
self.authenticationDidComplete()
}
} failure: { [weak self] error in
MXLog.error("[AuthenticationCoordinator] sessionStateDidChange: Fail to refresh crypto state with error: \(error)")
crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil)
self?.authenticationDidComplete()
}
} else {
authenticationDidComplete()
}
}
}
}
// MARK: - AuthenticationViewControllerDelegate
extension AuthenticationCoordinator: AuthenticationViewControllerDelegate {
func authenticationViewControllerDidDismiss(_ authenticationViewController: AuthenticationViewController!) {
completion?(authenticationViewController.authType)
func authenticationViewController(_ authenticationViewController: AuthenticationViewController!, didLoginWith session: MXSession!, andPassword password: String!) {
registerSessionStateChangeNotification(for: session)
self.session = session
self.password = password
self.showLoadingAnimation()
completion?(.didLogin(session))
}
}
// MARK: - KeyVerificationCoordinatorDelegate
extension AuthenticationCoordinator: KeyVerificationCoordinatorDelegate {
func keyVerificationCoordinatorDidComplete(_ coordinator: KeyVerificationCoordinatorType, otherUserId: String, otherDeviceId: String) {
if let crypto = session?.crypto,
!crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled {
MXLog.debug("[AuthenticationCoordinator][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys")
crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil)
}
navigationRouter.dismissModule(animated: true) { [weak self] in
self?.authenticationDidComplete()
}
}
func keyVerificationCoordinatorDidCancel(_ coordinator: KeyVerificationCoordinatorType) {
navigationRouter.dismissModule(animated: true) { [weak self] in
self?.authenticationDidComplete()
}
}
}
// MARK: - UIAdaptivePresentationControllerDelegate
extension AuthenticationCoordinator: UIAdaptivePresentationControllerDelegate {
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
// Prevent Key Verification from using swipe to dismiss
return false
}
}
@@ -18,9 +18,21 @@
import Foundation
struct AuthenticationCoordinatorParameters {
let navigationRouter: NavigationRouterType
}
enum AuthenticationCoordinatorResult {
/// The user has authenticated but key verification is yet to happen. The session value is
/// for a fresh session that still needs to load, sync etc before being ready.
case didLogin(MXSession)
/// All of the required authentication steps including key verification is complete.
case didComplete(MXKAuthenticationType)
}
/// `AuthenticationCoordinatorProtocol` is a protocol describing a Coordinator that handle's the authentication navigation flow.
protocol AuthenticationCoordinatorProtocol: Coordinator, Presentable {
var completion: ((MXKAuthenticationType) -> Void)? { get set }
var completion: ((AuthenticationCoordinatorResult) -> Void)? { get set }
/// Update the screen to display registration or login.
func update(authenticationType: MXKAuthenticationType)
@@ -62,6 +62,8 @@
@protocol AuthenticationViewControllerDelegate <NSObject>
- (void)authenticationViewControllerDidDismiss:(AuthenticationViewController *)authenticationViewController;
- (void)authenticationViewController:(AuthenticationViewController *)authenticationViewController
didLoginWithSession:(MXSession *)session
andPassword:(NSString *)password;
@end;
@@ -28,7 +28,7 @@
static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
@interface AuthenticationViewController () <AuthFallBackViewControllerDelegate, KeyVerificationCoordinatorBridgePresenterDelegate, SetPinCoordinatorBridgePresenterDelegate,
@interface AuthenticationViewController () <AuthFallBackViewControllerDelegate, SetPinCoordinatorBridgePresenterDelegate,
SocialLoginListViewDelegate,
SSOAuthenticationPresenterDelegate
>
@@ -63,7 +63,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
}
@property (nonatomic, readonly) BOOL isIdentityServerConfigured;
@property (nonatomic, strong) KeyVerificationCoordinatorBridgePresenter *keyVerificationCoordinatorBridgePresenter;
@property (nonatomic, strong) SetPinCoordinatorBridgePresenter *setPinCoordinatorBridgePresenter;
@property (nonatomic, strong) KeyboardAvoider *keyboardAvoider;
@@ -78,8 +77,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
// Current SSO transaction id used to identify and validate the SSO authentication callback
@property (nonatomic, strong) NSString *ssoCallbackTxnId;
@property (nonatomic, strong) CrossSigningService *crossSigningService;
@property (nonatomic, getter = isFirstViewAppearing) BOOL firstViewAppearing;
@property (nonatomic, strong) MXKErrorAlertPresentation *errorPresenter;
@@ -118,7 +115,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
_firstViewAppearing = YES;
self.crossSigningService = [CrossSigningService new];
self.errorPresenter = [MXKErrorAlertPresentation new];
}
@@ -318,11 +314,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
{
self.firstViewAppearing = NO;
}
if (self.keyVerificationCoordinatorBridgePresenter)
{
return;
}
// Verify that the app does not show the authentication screen whereas
// the user has already logged in.
@@ -379,7 +370,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
[self.authenticationActivityIndicator removeObserver:self forKeyPath:@"hidden"];
autoDiscovery = nil;
_keyVerificationCoordinatorBridgePresenter = nil;
_keyboardAvoider = nil;
}
@@ -557,30 +547,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
}
}
- (void)presentCompleteSecurityWithSession:(MXSession*)session
{
KeyVerificationCoordinatorBridgePresenter *keyVerificationCoordinatorBridgePresenter = [[KeyVerificationCoordinatorBridgePresenter alloc] initWithSession:session];
keyVerificationCoordinatorBridgePresenter.delegate = self;
[keyVerificationCoordinatorBridgePresenter presentCompleteSecurityFrom:self isNewSignIn:YES animated:YES];
self.keyVerificationCoordinatorBridgePresenter = keyVerificationCoordinatorBridgePresenter;
}
- (void)dismiss
{
self.userInteractionEnabled = YES;
[self.authenticationActivityIndicator stopAnimating];
// Dismiss (key verification) on successful login
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
if (self.authVCDelegate)
{
[self.authVCDelegate authenticationViewControllerDidDismiss:self];
}
}
- (BOOL)continueSSOLoginWithToken:(NSString*)loginToken txnId:(NSString*)txnId
{
// Check if transaction id is the same as expected
@@ -1377,119 +1343,8 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
}];
}
// Wait for session change to present complete security screen if needed
[self registerSessionStateChangeNotificationForSession:session];
}
- (void)registerSessionStateChangeNotificationForSession:(MXSession*)session
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionStateDidChangeNotification:) name:kMXSessionStateDidChangeNotification object:session];
}
- (void)unregisterSessionStateChangeNotification
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionStateDidChangeNotification object:nil];
}
- (void)sessionStateDidChangeNotification:(NSNotification*)notification
{
MXSession *session = (MXSession*)notification.object;
if (session.state == MXSessionStateStoreDataReady)
{
if (session.crypto.crossSigning)
{
// Do not make key share requests while the "Complete security" is not complete.
// If the device is self-verified, the SDK will restore the existing key backup.
// Then, it will re-enable outgoing key share requests
[session.crypto setOutgoingKeyRequestsEnabled:NO onComplete:nil];
}
}
else if (session.state == MXSessionStateRunning)
{
[self unregisterSessionStateChangeNotification];
if (session.crypto.crossSigning)
{
[session.crypto.crossSigning refreshStateWithSuccess:^(BOOL stateUpdated) {
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: crossSigning.state: %@", @(session.crypto.crossSigning.state));
switch (session.crypto.crossSigning.state)
{
case MXCrossSigningStateNotBootstrapped:
{
// TODO: This is still not sure we want to disable the automatic cross-signing bootstrap
// if the admin disabled e2e by default.
// Do like riot-web for the moment
if ([session vc_homeserverConfiguration].isE2EEByDefaultEnabled)
{
// Bootstrap cross-signing on user's account
// We do it for both registration and new login as long as cross-signing does not exist yet
if (self.authInputsView.password.length)
{
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Bootstrap with password");
[session.crypto.crossSigning setupWithPassword:self.authInputsView.password success:^{
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Bootstrap succeeded");
[self dismiss];
} failure:^(NSError * _Nonnull error) {
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Bootstrap failed. Error: %@", error);
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
[self dismiss];
}];
}
else
{
// Try to setup cross-signing without authentication parameters in case if a grace period is enabled
[self.crossSigningService setupCrossSigningWithoutAuthenticationFor:session success:^{
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Bootstrap succeeded without credentials");
[self dismiss];
} failure:^(NSError * _Nonnull error) {
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Do not know how to bootstrap cross-signing. Skip it.");
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
[self dismiss];
}];
}
}
else
{
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
[self dismiss];
}
break;
}
case MXCrossSigningStateCrossSigningExists:
{
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Complete security");
// Ask the user to verify this session
self.userInteractionEnabled = YES;
[self.authenticationActivityIndicator stopAnimating];
[self presentCompleteSecurityWithSession:session];
break;
}
default:
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Nothing to do");
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
[self dismiss];
break;
}
} failure:^(NSError * _Nonnull error) {
MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Fail to refresh crypto state with error: %@", error);
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
[self dismiss];
}];
}
else
{
[self dismiss];
}
}
// Ask the coordinator to show the loading spinner whilst waiting.
[self.authVCDelegate authenticationViewController:self didLoginWithSession:session andPassword:self.authInputsView.password];
}
#pragma mark - MXKAuthInputsViewDelegate
@@ -1621,24 +1476,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
[self setCustomServerFieldsVisible:YES];
}
#pragma mark - KeyVerificationCoordinatorBridgePresenterDelegate
- (void)keyVerificationCoordinatorBridgePresenterDelegateDidComplete:(KeyVerificationCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter otherUserId:(NSString * _Nonnull)otherUserId otherDeviceId:(NSString * _Nonnull)otherDeviceId
{
MXCrypto *crypto = coordinatorBridgePresenter.session.crypto;
if (!crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled)
{
MXLogDebug(@"[AuthenticationVC][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys");
[crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
}
[self dismiss];
}
- (void)keyVerificationCoordinatorBridgePresenterDelegateDidCancel:(KeyVerificationCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
{
[self dismiss];
}
#pragma mark - SetPinCoordinatorBridgePresenterDelegate
- (void)setPinCoordinatorBridgePresenterDelegateDidComplete:(SetPinCoordinatorBridgePresenter *)coordinatorBridgePresenter
@@ -0,0 +1,38 @@
//
// Copyright 2021 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
import Reusable
class LaunchLoadingViewController: UIViewController, Reusable {
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
init() {
super.init(nibName: "LaunchLoadingViewController", bundle: nil)
let launchLoadingView = LaunchLoadingView.instantiate()
launchLoadingView.update(theme: ThemeService.shared().theme)
view.vc_addSubViewMatchingParent(launchLoadingView)
// The launch time isn't profiled for analytics as it's presentation length
// will be artificially changed based on other views in the flow.
}
override func viewWillAppear(_ animated: Bool) {
navigationController?.setNavigationBarHidden(true, animated: false)
}
}
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="LaunchLoadingViewController" customModule="Riot" customModuleProvider="target">
<connections>
<outlet property="view" destination="25f-lP-cnO" id="Qdu-wY-5s0"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="25f-lP-cnO">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<viewLayoutGuide key="safeArea" id="FXc-bE-Yxp"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<point key="canvasLocation" x="192" y="-103"/>
</view>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
@@ -54,8 +54,8 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol {
private var navigationRouter: NavigationRouterType {
parameters.router
}
// Keep a strong ref as we need to init authVC early to preload its view (it is *really* slow to do in realtime)
private var authenticationCoordinator: AuthenticationCoordinatorProtocol = AuthenticationCoordinator()
// Keep a strong ref as we need to init authVC early to preload its view
private let authenticationCoordinator: AuthenticationCoordinatorProtocol
private var isShowingAuthentication = false
// MARK: Screen results
@@ -72,6 +72,11 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol {
init(parameters: OnboardingCoordinatorParameters) {
self.parameters = parameters
// Preload the authVC (it is *really* slow to load in realtime)
let authenticationParameters = AuthenticationCoordinatorParameters(navigationRouter: parameters.router)
authenticationCoordinator = AuthenticationCoordinator(parameters: authenticationParameters)
super.init()
}
@@ -178,9 +183,16 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol {
MXLog.debug("[OnboardingCoordinator] showAuthenticationScreen")
let coordinator = authenticationCoordinator
coordinator.completion = { [weak self, weak coordinator] authenticationType in
coordinator.completion = { [weak self, weak coordinator] result in
guard let self = self, let coordinator = coordinator else { return }
self.authenticationCoordinator(coordinator, didCompleteWith: authenticationType)
switch result {
case .didLogin(let session):
self.authenticationCoordinator(coordinator, didLoginWith: session)
case .didComplete(let authenticationType):
self.authenticationCoordinator(coordinator, didCompleteWith: authenticationType)
}
}
// Due to needing to preload the authVC, this breaks the Coordinator init/start pattern.
@@ -200,7 +212,6 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol {
coordinator.start()
add(childCoordinator: coordinator)
authenticationCoordinator = coordinator
if customHomeserver != nil || customIdentityServer != nil {
coordinator.updateHomeserver(customHomeserver, andIdentityServer: customIdentityServer)
@@ -217,6 +228,11 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol {
isShowingAuthentication = true
}
private func authenticationCoordinator(_ coordinator: AuthenticationCoordinatorProtocol, didLoginWith session: MXSession) {
// TODO: Show next screens whilst waiting for the everything to load.
// May need to move the spinner and key verification up to here in order to coordinate properly.
}
/// Displays the next view in the flow after the authentication screen.
private func authenticationCoordinator(_ coordinator: AuthenticationCoordinatorProtocol, didCompleteWith authenticationType: MXKAuthenticationType) {
completion?()
+3 -3
View File
@@ -119,9 +119,9 @@
self.delegate = self;
_isOnboardingInProgress = NO;
self.isOnboardingInProgress = NO;
// Note: UITabBarViewController shoud not be embed in a UINavigationController (https://github.com/vector-im/riot-ios/issues/3086)
// Note: UITabBarViewController should not be embed in a UINavigationController (https://github.com/vector-im/riot-ios/issues/3086)
[self vc_removeBackTitle];
[self setupTitleView];
@@ -520,7 +520,7 @@
[self.onboardingCoordinatorBridgePresenter dismissWithAnimated:YES completion:nil];
self.onboardingCoordinatorBridgePresenter = nil;
self.isOnboardingInProgress = NO;
self.isOnboardingInProgress = NO; // Must be set before calling didCompleteAuthentication
[self.masterTabBarDelegate masterTabBarControllerDidCompleteAuthentication:self];
};