Swiftgram/TelegramUI/AuthorizationSequenceController.swift
2018-11-23 04:38:14 +03:00

674 lines
41 KiB
Swift

import Foundation
import AsyncDisplayKit
import Display
import Postbox
import TelegramCore
import SwiftSignalKit
import MtProtoKitDynamic
import MessageUI
import CoreTelephony
public final class AuthorizationSequenceController: NavigationController {
static func navigationBarTheme(_ theme: AuthorizationTheme) -> NavigationBarTheme {
return NavigationBarTheme(buttonColor: theme.accentColor, disabledButtonColor: UIColor(rgb: 0xd0d0d0), primaryTextColor: .black, backgroundColor: .clear, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
}
private var account: UnauthorizedAccount
private let apiId: Int32
private let apiHash: String
private var strings: PresentationStrings
public let theme: AuthorizationTheme
private let openUrl: (String) -> Void
private var stateDisposable: Disposable?
private let actionDisposable = MetaDisposable()
public init(account: UnauthorizedAccount, strings: PresentationStrings, openUrl: @escaping (String) -> Void, apiId: Int32, apiHash: String) {
self.account = account
self.apiId = apiId
self.apiHash = apiHash
self.strings = strings
self.openUrl = openUrl
self.theme = defaultLightAuthorizationTheme
super.init(mode: .single, theme: NavigationControllerTheme(navigationBar: AuthorizationSequenceController.navigationBarTheme(theme), emptyAreaColor: .black, emptyDetailIcon: nil))
self.stateDisposable = (account.postbox.stateView()
|> deliverOnMainQueue).start(next: { [weak self] view in
self?.updateState(state: view.state ?? UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty))
})
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
self.stateDisposable?.dispose()
self.actionDisposable.dispose()
}
override public func loadView() {
super.loadView()
self.view.backgroundColor = self.theme.backgroundColor
}
private func splashController() -> AuthorizationSequenceSplashController {
var currentController: AuthorizationSequenceSplashController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequenceSplashController {
currentController = c
break
}
}
let controller: AuthorizationSequenceSplashController
if let currentController = currentController {
controller = currentController
} else {
controller = AuthorizationSequenceSplashController(postbox: self.account.postbox, network: self.account.network, theme: self.theme)
controller.nextPressed = { [weak self] strings in
if let strongSelf = self {
if let strings = strings {
strongSelf.strings = strings
}
let masterDatacenterId = strongSelf.account.masterDatacenterId
let isTestingEnvironment = strongSelf.account.testingEnvironment
let countryCode = defaultCountryCode()
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: isTestingEnvironment, masterDatacenterId: masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: "")))
}).start()
}
}
}
return controller
}
private func phoneEntryController(countryCode: Int32, number: String) -> AuthorizationSequencePhoneEntryController {
var currentController: AuthorizationSequencePhoneEntryController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequencePhoneEntryController {
currentController = c
break
}
}
let controller: AuthorizationSequencePhoneEntryController
if let currentController = currentController {
controller = currentController
} else {
controller = AuthorizationSequencePhoneEntryController(network: self.account.network, strings: self.strings, theme: self.theme, openUrl: { [weak self] url in
self?.openUrl(url)
})
controller.loginWithNumber = { [weak self, weak controller] number in
if let strongSelf = self {
controller?.inProgress = true
strongSelf.actionDisposable.set((sendAuthorizationCode(account: strongSelf.account, phoneNumber: number, apiId: strongSelf.apiId, apiHash: strongSelf.apiHash) |> deliverOnMainQueue).start(next: { [weak self] account in
if let strongSelf = self {
controller?.inProgress = false
strongSelf.account = account
}
}, error: { error in
if let strongSelf = self, let controller = controller {
controller.inProgress = false
let text: String
var actions: [TextAlertAction] = [
TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})
]
switch error {
case .limitExceeded:
text = strongSelf.strings.Login_CodeFloodError
case .invalidPhoneNumber:
text = strongSelf.strings.Login_InvalidPhoneError
actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.strings.Login_PhoneNumberHelp, action: {
}))
case .phoneLimitExceeded:
text = strongSelf.strings.Login_PhoneFloodError
case .phoneBanned:
text = strongSelf.strings.Login_PhoneBannedError
case .generic:
text = strongSelf.strings.Login_UnknownError
case .timeout:
text = strongSelf.strings.Login_NetworkError
actions.append(TextAlertAction(type: .genericAction, title: strongSelf.strings.ChatSettings_ConnectionType_UseProxy, action: { [weak controller] in
guard let strongSelf = self, let controller = controller else {
return
}
controller.present(proxySettingsController(postbox: strongSelf.account.postbox, network: strongSelf.account.network, mode: .modal, theme: defaultPresentationTheme, strings: strongSelf.strings, updatedPresentationData: .single((defaultPresentationTheme, strongSelf.strings))), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}))
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: actions), in: .window(.root))
}
}))
}
}
}
controller.updateData(countryCode: countryCode, number: number)
return controller
}
private func codeEntryController(number: String, type: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, timeout: Int32?, termsOfService: (UnauthorizedAccountTermsOfService, Bool)?) -> AuthorizationSequenceCodeEntryController {
var currentController: AuthorizationSequenceCodeEntryController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequenceCodeEntryController {
if c.data?.1 == type {
currentController = c
}
break
}
}
let controller: AuthorizationSequenceCodeEntryController
if let currentController = currentController {
controller = currentController
} else {
controller = AuthorizationSequenceCodeEntryController(strings: self.strings, theme: self.theme, openUrl: { [weak self] url in
self?.openUrl(url)
})
controller.loginWithCode = { [weak self, weak controller] code in
if let strongSelf = self {
controller?.inProgress = true
/*
if let (termsOfService, exclusuve) = self.termsOfService, exclusuve {
var acceptImpl: (() -> Void)?
var declineImpl: (() -> Void)?
let controller = TermsOfServiceController(theme: TermsOfServiceControllerTheme(authTheme: self.theme), strings: self.strings, text: termsOfService.text, entities: termsOfService.entities, ageConfirmation: termsOfService.ageConfirmation, signingUp: true, accept: { _ in
acceptImpl?()
}, decline: {
declineImpl?()
}, openUrl: { [weak self] url in
self?.openUrl(url)
})
acceptImpl = { [weak self, weak controller] in
controller?.dismiss()
if let strongSelf = self {
strongSelf.termsOfService = nil
strongSelf.loginWithCode?(code)
}
}
declineImpl = { [weak self, weak controller] in
controller?.dismiss()
self?.reset?()
self?.controllerNode.activateInput()
}
self.view.endEditing(true)
self.present(controller, in: .window(.root))
} else {
*/
strongSelf.actionDisposable.set((authorizeWithCode(account: strongSelf.account, code: code, termsOfService: termsOfService?.0)
|> deliverOnMainQueue).start(next: { result in
guard let strongSelf = self else {
return
}
controller?.inProgress = false
switch result {
case let .signUp(data):
if let (termsOfService, explicit) = termsOfService, explicit {
var presentAlertAgainImpl: (() -> Void)?
let presentAlertImpl: () -> Void = {
guard let strongSelf = self else {
return
}
var dismissImpl: (() -> Void)?
let alertTheme = AlertControllerTheme(authTheme: strongSelf.theme)
let attributedText = stringWithAppliedEntities(termsOfService.text, entities: termsOfService.entities, baseColor: alertTheme.primaryColor, linkColor: alertTheme.accentColor, baseFont: Font.regular(13.0), linkFont: Font.regular(13.0), boldFont: Font.semibold(13.0), italicFont: Font.italic(13.0), fixedFont: Font.regular(13.0))
let contentNode = TextAlertContentNode(theme: alertTheme, title: NSAttributedString(string: strongSelf.strings.Login_TermsOfServiceHeader, font: Font.medium(17.0), textColor: alertTheme.primaryColor, paragraphAlignment: .center), text: attributedText, actions: [
TextAlertAction(type: .defaultAction, title: strongSelf.strings.Login_TermsOfServiceAgree, action: {
dismissImpl?()
guard let strongSelf = self else {
return
}
let _ = beginSignUp(account: strongSelf.account, data: data).start()
}), TextAlertAction(type: .genericAction, title: strongSelf.strings.Login_TermsOfServiceDecline, action: {
dismissImpl?()
guard let strongSelf = self else {
return
}
strongSelf.currentWindow?.present(standardTextAlertController(theme: alertTheme, title: strongSelf.strings.Login_TermsOfServiceDecline, text: strongSelf.strings.Login_TermsOfServiceSignupDecline, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_Cancel, action: {
presentAlertAgainImpl?()
}), TextAlertAction(type: .genericAction, title: strongSelf.strings.Login_TermsOfServiceDecline, action: {
guard let strongSelf = self else {
return
}
let account = strongSelf.account
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty))
}).start()
})]), on: .root, blockInteraction: false, completion: {})
})
], actionLayout: .vertical)
contentNode.textAttributeAction = (NSAttributedStringKey(rawValue: TelegramTextAttributes.URL), { value in
if let value = value as? String {
strongSelf.openUrl(value)
}
})
let controller = AlertController(theme: alertTheme, contentNode: contentNode)
dismissImpl = { [weak controller] in
controller?.dismissAnimated()
}
strongSelf.view.endEditing(true)
strongSelf.currentWindow?.present(controller, on: .root, blockInteraction: false, completion: {})
}
presentAlertAgainImpl = {
presentAlertImpl()
}
presentAlertImpl()
} else {
let _ = beginSignUp(account: strongSelf.account, data: data).start()
}
case .loggedIn:
break
}
}, error: { error in
Queue.mainQueue().async {
if let strongSelf = self, let controller = controller {
controller.inProgress = false
let text: String
switch error {
case .limitExceeded:
text = strongSelf.strings.Login_CodeFloodError
case .invalidCode:
text = strongSelf.strings.Login_InvalidCodeError
case .generic:
text = strongSelf.strings.Login_UnknownError
case .codeExpired:
text = strongSelf.strings.Login_CodeExpired
let account = strongSelf.account
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty))
}).start()
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
}
}
}))
}
}
}
controller.requestNextOption = { [weak self, weak controller] in
if let strongSelf = self {
if nextType == nil {
if MFMailComposeViewController.canSendMail() {
let phoneFormatted = formatPhoneNumber(number)
let composeController = MFMailComposeViewController()
//composeController.mailComposeDelegate = strongSelf
composeController.setToRecipients(["sms@stel.com"])
composeController.setSubject(strongSelf.strings.Login_EmailCodeSubject(phoneFormatted).0)
composeController.setMessageBody(strongSelf.strings.Login_EmailCodeBody(phoneFormatted).0, isHTML: false)
controller?.view.window?.rootViewController?.present(composeController, animated: true, completion: nil)
} else {
controller?.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: strongSelf.strings.Login_EmailNotConfiguredError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
}
} else {
controller?.inProgress = true
strongSelf.actionDisposable.set((resendAuthorizationCode(account: strongSelf.account)
|> deliverOnMainQueue).start(next: { result in
controller?.inProgress = false
}, error: { error in
if let strongSelf = self, let controller = controller {
controller.inProgress = false
let text: String
switch error {
case .limitExceeded:
text = strongSelf.strings.Login_CodeFloodError
case .invalidPhoneNumber:
text = strongSelf.strings.Login_InvalidPhoneError
case .phoneLimitExceeded:
text = strongSelf.strings.Login_PhoneFloodError
case .phoneBanned:
text = strongSelf.strings.Login_PhoneBannedError
case .generic:
text = strongSelf.strings.Login_UnknownError
case .timeout:
text = strongSelf.strings.Login_NetworkError
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
}
}))
}
}
}
controller.reset = { [weak self] in
if let strongSelf = self {
let account = strongSelf.account
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty))
}).start()
}
}
controller.updateData(number: formatPhoneNumber(number), codeType: type, nextType: nextType, timeout: timeout, termsOfService: termsOfService)
return controller
}
private func passwordEntryController(hint: String) -> AuthorizationSequencePasswordEntryController {
var currentController: AuthorizationSequencePasswordEntryController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequencePasswordEntryController {
currentController = c
break
}
}
let controller: AuthorizationSequencePasswordEntryController
if let currentController = currentController {
controller = currentController
} else {
controller = AuthorizationSequencePasswordEntryController(strings: self.strings, theme: self.theme)
controller.loginWithPassword = { [weak self, weak controller] password in
if let strongSelf = self {
controller?.inProgress = true
strongSelf.actionDisposable.set((authorizeWithPassword(account: strongSelf.account, password: password) |> deliverOnMainQueue).start(error: { error in
Queue.mainQueue().async {
if let strongSelf = self, let controller = controller {
controller.inProgress = false
let text: String
switch error {
case .limitExceeded:
text = strongSelf.strings.LoginPassword_FloodError
case .invalidPassword:
text = strongSelf.strings.LoginPassword_InvalidPasswordError
case .generic:
text = strongSelf.strings.Login_UnknownError
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
controller.passwordIsInvalid()
}
}
}))
}
}
}
controller.forgot = { [weak self, weak controller] in
if let strongSelf = self, let strongController = controller {
strongController.inProgress = true
strongSelf.actionDisposable.set((requestPasswordRecovery(account: strongSelf.account)
|> deliverOnMainQueue).start(next: { option in
if let strongSelf = self, let strongController = controller {
strongController.inProgress = false
switch option {
case let .email(pattern):
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
if let state = transaction.getState() as? UnauthorizedAccountState, case let .passwordEntry(hint, number, code) = state.contents {
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordRecovery(hint: hint, number: number, code: code, emailPattern: pattern)))
}
}).start()
case .none:
strongController.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: strongSelf.strings.TwoStepAuth_RecoveryUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
strongController.didForgotWithNoRecovery = true
}
}
}, error: { error in
if let strongSelf = self, let strongController = controller {
strongController.inProgress = false
}
}))
}
}
controller.reset = { [weak self, weak controller] in
if let strongSelf = self, let strongController = controller {
strongController.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: strongSelf.strings.TwoStepAuth_RecoveryUnavailable, actions: [
TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_Cancel, action: {}),
TextAlertAction(type: .destructiveAction, title: strongSelf.strings.Login_ResetAccountProtected_Reset, action: {
if let strongSelf = self, let strongController = controller {
strongController.inProgress = true
strongSelf.actionDisposable.set((performAccountReset(account: strongSelf.account)
|> deliverOnMainQueue).start(next: {
if let strongController = controller {
strongController.inProgress = false
}
}, error: { error in
if let strongSelf = self, let strongController = controller {
strongController.inProgress = false
let text: String
switch error {
case .generic:
text = strongSelf.strings.Login_UnknownError
case .limitExceeded:
text = strongSelf.strings.Login_ResetAccountProtected_LimitExceeded
}
strongController.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
}
}))
}
})]), in: .window(.root))
}
}
controller.updateData(hint: hint)
return controller
}
private func passwordRecoveryController(emailPattern: String) -> AuthorizationSequencePasswordRecoveryController {
var currentController: AuthorizationSequencePasswordRecoveryController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequencePasswordRecoveryController {
currentController = c
break
}
}
let controller: AuthorizationSequencePasswordRecoveryController
if let currentController = currentController {
controller = currentController
} else {
controller = AuthorizationSequencePasswordRecoveryController(strings: self.strings, theme: self.theme)
controller.recoverWithCode = { [weak self, weak controller] code in
if let strongSelf = self {
controller?.inProgress = true
strongSelf.actionDisposable.set((performPasswordRecovery(account: strongSelf.account, code: code) |> deliverOnMainQueue).start(error: { error in
Queue.mainQueue().async {
if let strongSelf = self, let controller = controller {
controller.inProgress = false
let text: String
switch error {
case .limitExceeded:
text = strongSelf.strings.LoginPassword_FloodError
case .invalidCode:
text = strongSelf.strings.Login_InvalidCodeError
case .expired:
text = strongSelf.strings.Login_CodeExpiredError
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
}
}
}))
}
}
controller.noAccess = { [weak self, weak controller] in
if let strongSelf = self, let controller = controller {
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: strongSelf.strings.TwoStepAuth_RecoveryFailed, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
let account = strongSelf.account
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
if let state = transaction.getState() as? UnauthorizedAccountState, case let .passwordRecovery(hint, number, code, _) = state.contents {
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code)))
}
}).start()
}
}
}
controller.updateData(emailPattern: emailPattern)
return controller
}
private func awaitingAccountResetController(protectedUntil: Int32, number: String?) -> AuthorizationSequenceAwaitingAccountResetController {
var currentController: AuthorizationSequenceAwaitingAccountResetController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequenceAwaitingAccountResetController {
currentController = c
break
}
}
let controller: AuthorizationSequenceAwaitingAccountResetController
if let currentController = currentController {
controller = currentController
} else {
controller = AuthorizationSequenceAwaitingAccountResetController(strings: self.strings, theme: self.theme)
controller.reset = { [weak self, weak controller] in
if let strongSelf = self, let strongController = controller {
strongController.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: strongSelf.strings.TwoStepAuth_ResetAccountConfirmation, actions: [
TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_Cancel, action: {}),
TextAlertAction(type: .destructiveAction, title: strongSelf.strings.Login_ResetAccountProtected_Reset, action: {
if let strongSelf = self, let strongController = controller {
strongController.inProgress = true
strongSelf.actionDisposable.set((performAccountReset(account: strongSelf.account)
|> deliverOnMainQueue).start(next: {
if let strongController = controller {
strongController.inProgress = false
}
}, error: { error in
if let strongSelf = self, let strongController = controller {
strongController.inProgress = false
let text: String
switch error {
case .generic:
text = strongSelf.strings.Login_UnknownError
case .limitExceeded:
text = strongSelf.strings.Login_ResetAccountProtected_LimitExceeded
}
strongController.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
}
}))
}
})]), in: .window(.root))
}
}
controller.logout = { [weak self] in
if let strongSelf = self {
let account = strongSelf.account
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty))
}).start()
}
}
}
controller.updateData(protectedUntil: protectedUntil, number: number ?? "")
return controller
}
private func signUpController(firstName: String, lastName: String, termsOfService: UnauthorizedAccountTermsOfService?) -> AuthorizationSequenceSignUpController {
var currentController: AuthorizationSequenceSignUpController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequenceSignUpController {
currentController = c
break
}
}
let controller: AuthorizationSequenceSignUpController
if let currentController = currentController {
controller = currentController
} else {
controller = AuthorizationSequenceSignUpController(strings: self.strings, theme: self.theme)
controller.signUpWithName = { [weak self, weak controller] firstName, lastName, avatarData in
if let strongSelf = self {
controller?.inProgress = true
strongSelf.actionDisposable.set((signUpWithName(account: strongSelf.account, firstName: firstName, lastName: lastName, avatarData: avatarData)
|> deliverOnMainQueue).start(error: { error in
Queue.mainQueue().async {
if let strongSelf = self, let controller = controller {
controller.inProgress = false
let text: String
switch error {
case .limitExceeded:
text = strongSelf.strings.Login_CodeFloodError
case .codeExpired:
text = strongSelf.strings.Login_CodeExpiredError
case .invalidFirstName:
text = strongSelf.strings.Login_InvalidFirstNameError
case .invalidLastName:
text = strongSelf.strings.Login_InvalidLastNameError
case .generic:
text = strongSelf.strings.Login_UnknownError
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
}
}
}))
}
}
}
controller.updateData(firstName: firstName, lastName: lastName, termsOfService: termsOfService)
return controller
}
private func updateState(state: PostboxCoding?) {
if let state = state as? UnauthorizedAccountState {
switch state.contents {
case .empty:
if let _ = self.viewControllers.last as? AuthorizationSequenceSplashController {
} else {
self.setViewControllers([self.splashController()], animated: !self.viewControllers.isEmpty)
}
case let .phoneEntry(countryCode, number):
self.setViewControllers([self.splashController(), self.phoneEntryController(countryCode: countryCode, number: number)], animated: !self.viewControllers.isEmpty)
case let .confirmationCodeEntry(number, type, _, timeout, nextType, termsOfService):
self.setViewControllers([self.splashController(), self.phoneEntryController(countryCode: defaultCountryCode(), number: ""), self.codeEntryController(number: number, type: type, nextType: nextType, timeout: timeout, termsOfService: termsOfService)], animated: !self.viewControllers.isEmpty)
case let .passwordEntry(hint, _, _):
self.setViewControllers([self.splashController(), self.passwordEntryController(hint: hint)], animated: !self.viewControllers.isEmpty)
case let .passwordRecovery(_, _, _, emailPattern):
self.setViewControllers([self.splashController(), self.passwordRecoveryController(emailPattern: emailPattern)], animated: !self.viewControllers.isEmpty)
case let .awaitingAccountReset(protectedUntil, number):
self.setViewControllers([self.splashController(), self.awaitingAccountResetController(protectedUntil: protectedUntil, number: number)], animated: !self.viewControllers.isEmpty)
case let .signUp(_, _, _, firstName, lastName, termsOfService):
self.setViewControllers([self.splashController(), self.signUpController(firstName: firstName, lastName: lastName, termsOfService: termsOfService)], animated: !self.viewControllers.isEmpty)
}
} else if let _ = state as? AuthorizedAccountState {
}
}
override public func setViewControllers(_ viewControllers: [UIViewController], animated: Bool) {
let wasEmpty = self.viewControllers.isEmpty
super.setViewControllers(viewControllers, animated: animated)
if wasEmpty {
self.topViewController?.view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
}
}
public func applyConfirmationCode(_ code: Int) {
if let controller = self.viewControllers.last as? AuthorizationSequenceCodeEntryController {
controller.applyConfirmationCode(code)
}
}
}
private func defaultCountryCode() -> Int32 {
var countryId: String? = nil
let networkInfo = CTTelephonyNetworkInfo()
if let carrier = networkInfo.subscriberCellularProvider {
countryId = carrier.isoCountryCode
}
if countryId == nil {
countryId = (Locale.current as NSLocale).object(forKey: .countryCode) as? String
}
var countryCode: Int32 = 1
if let countryId = countryId {
let normalizedId = countryId.uppercased()
for (code, idAndName) in countryCodeToIdAndName {
if idAndName.0 == normalizedId {
countryCode = Int32(code)
break
}
}
}
return countryCode
}