mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-28 04:06:57 +02:00
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:
@@ -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?()
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user