Merge commit '7f2ab1788ff168b788f20c4896822d74f3944214'

This commit is contained in:
Ali 2022-08-25 20:37:14 +03:00
commit e26c4a6bf0
31 changed files with 722 additions and 437 deletions

View File

@ -7979,3 +7979,22 @@ Sorry for the inconvenience.";
"Login.SelectCountry" = "Country";
"ReportPeer.ReportReaction" = "Report Reaction";
"Login.Or" = "or";
"Login.Continue" = "Continue";
"Login.EnterCodeSMSTitle" = "Enter Code";
"Login.EnterCodeSMSText" = "We've sent and SMS with an activation code to your phone **%@**.";
"Login.SendCodeAsSMS" = "Send the code as an SMS";
"Login.EnterCodeTelegramTitle" = "Enter Code";
"Login.EnterCodeTelegramText" = "We've sent the code to the **Telegram app** for %@ on your other device.";
"Login.AddEmailTitle" = "Add Email";
"Login.AddEmailText" = "Please enter your valid email address to protect your account.";
"Login.AddEmailPlaceholder" = "Enter your email";
"Login.EnterCodeEmailTitle" = "Check Your Email";
"Login.EnterCodeEmailText" = "Please enter the code we have sent to your email %@.";
"Login.WrongCodeError" = "Wrong code, please try again.";

View File

@ -13,4 +13,6 @@ public protocol ChatListController: ViewController {
func deactivateSearch(animated: Bool)
func activateCompose()
func maybeAskForPeerChatRemoval(peer: EngineRenderedPeer, joined: Bool, deleteGloballyIfPossible: Bool, completion: @escaping (Bool) -> Void, removed: @escaping () -> Void)
func playSignUpCompletedAnimation()
}

View File

@ -75,7 +75,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
self.clipNode = ASDisplayNode()
var controllerRemovedImpl: ((ViewController) -> Void)?
self.container = NavigationContainer(controllerRemoved: { c in
self.container = NavigationContainer(isFlat: false, controllerRemoved: { c in
controllerRemovedImpl?(c)
})
self.container.clipsToBounds = true

View File

@ -6,15 +6,17 @@ import TelegramPresentationData
import TextFormat
import Markdown
public func authorizationCurrentOptionText(_ type: SentAuthorizationCodeType, strings: PresentationStrings, primaryColor: UIColor, accentColor: UIColor) -> NSAttributedString {
public func authorizationCurrentOptionText(_ type: SentAuthorizationCodeType, phoneNumber: String, email: String?, strings: PresentationStrings, primaryColor: UIColor, accentColor: UIColor) -> NSAttributedString {
let fontSize: CGFloat = 17.0
let body = MarkdownAttributeSet(font: Font.regular(fontSize), textColor: primaryColor)
let bold = MarkdownAttributeSet(font: Font.semibold(fontSize), textColor: primaryColor)
let attributes = MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil })
switch type {
case .sms:
return NSAttributedString(string: strings.Login_CodeSentSms, font: Font.regular(fontSize), textColor: primaryColor, paragraphAlignment: .center)
return parseMarkdownIntoAttributedString(strings.Login_EnterCodeSMSText(phoneNumber).string, attributes: attributes, textAlignment: .center)
case .otherSession:
let body = MarkdownAttributeSet(font: Font.regular(fontSize), textColor: primaryColor)
let bold = MarkdownAttributeSet(font: Font.semibold(fontSize), textColor: primaryColor)
return parseMarkdownIntoAttributedString(strings.Login_CodeSentInternal, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center)
return parseMarkdownIntoAttributedString(strings.Login_EnterCodeTelegramText(phoneNumber).string, attributes: attributes, textAlignment: .center)
case .missedCall:
let body = MarkdownAttributeSet(font: Font.regular(fontSize), textColor: primaryColor)
let bold = MarkdownAttributeSet(font: Font.semibold(fontSize), textColor: primaryColor)
@ -26,8 +28,7 @@ public func authorizationCurrentOptionText(_ type: SentAuthorizationCodeType, st
case .emailSetupRequired:
return NSAttributedString(string: "", font: Font.regular(fontSize), textColor: primaryColor, paragraphAlignment: .center)
case let .email(emailPattern, _, _, _, _):
//TODO: localize
let mutableString = NSAttributedString(string: "Please enter the code we have sent to your email \(emailPattern).", font: Font.regular(fontSize), textColor: primaryColor, paragraphAlignment: .center).mutableCopy() as! NSMutableAttributedString
let mutableString = NSAttributedString(string: strings.Login_EnterCodeEmailText(email ?? emailPattern).string, font: Font.regular(fontSize), textColor: primaryColor, paragraphAlignment: .center).mutableCopy() as! NSMutableAttributedString
let range = (mutableString.string as NSString).range(of: "*******")
if range.location != NSNotFound {
mutableString.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler), value: true, range: range)

View File

@ -30,6 +30,7 @@ import ComponentFlow
import LottieAnimationComponent
import ProgressIndicatorComponent
import PremiumUI
import ConfettiEffect
import AnimationCache
import MultiAnimationRenderer
import EmojiStatusSelectionComponent
@ -1584,7 +1585,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.didAppear = true
self.chatListDisplayNode.containerNode.updateEnableAdjacentFilterLoading(true)
@ -3462,6 +3463,17 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller)
})
}
private var playedSignUpCompletedAnimation = false
public func playSignUpCompletedAnimation() {
guard !self.playedSignUpCompletedAnimation else {
return
}
self.playedSignUpCompletedAnimation = true
Queue.mainQueue().after(0.3) {
self.view.addSubview(ConfettiView(frame: self.view.bounds))
}
}
}
private final class ChatListTabBarContextExtractedContentSource: ContextExtractedContentSource {

View File

@ -2,23 +2,30 @@ import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
import PhoneNumberFormat
public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
public struct Theme: Equatable {
public var inactiveBorder: UInt32
public var activeBorder: UInt32
public var succeedBorder: UInt32
public var failedBorder: UInt32
public var foreground: UInt32
public var isDark: Bool
public init(
inactiveBorder: UInt32,
activeBorder: UInt32,
succeedBorder: UInt32,
failedBorder: UInt32,
foreground: UInt32,
isDark: Bool
) {
self.inactiveBorder = inactiveBorder
self.activeBorder = activeBorder
self.succeedBorder = succeedBorder
self.failedBorder = failedBorder
self.foreground = foreground
self.isDark = isDark
}
@ -71,7 +78,7 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
}
}
func update(textColor: UInt32, text: String, size: CGSize, fontSize: CGFloat, animated: Bool) {
func update(textColor: UInt32, text: String, size: CGSize, fontSize: CGFloat, animated: Bool, delay: Double? = nil) {
let previousText = self.text
self.text = text
@ -83,10 +90,10 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
} else {
if let copyView = self.textNode.view.snapshotContentTree() {
self.view.insertSubview(copyView, at: 0)
copyView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak copyView] _ in
copyView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, delay: delay ?? 0.0, removeOnCompletion: false, completion: { [weak copyView] _ in
copyView?.removeFromSuperview()
})
copyView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: size.height / 2.0), duration: 0.2, removeOnCompletion: false, additive: true)
copyView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: size.height / 2.0), duration: 0.2, delay: delay ?? 0.0, removeOnCompletion: false, additive: true)
}
}
}
@ -160,6 +167,28 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
}
}
private var isSucceed = false
private var isFailed = false
private var isResetting = false
public func animateError() {
self.isFailed = true
self.updateItemViews(animated: true)
Queue.mainQueue().after(0.85, {
self.textValue = ""
self.isResetting = true
self.updateItemViews(animated: true)
self.isResetting = false
self.textField.text = ""
self.isFailed = false
self.updateItemViews(animated: true)
})
}
public func animateSuccess() {
self.isSucceed = true
self.updateItemViews(animated: true)
}
@objc func textFieldChanged(_ textField: UITextField) {
self.textValue = textField.text ?? ""
self.updateItemViews(animated: true)
@ -170,6 +199,11 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
guard let count = self.count else {
return false
}
guard !self.isFailed else {
return false
}
var text = textField.text ?? ""
guard let stringRange = Range(range, in: text) else {
return false
@ -220,6 +254,7 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
return
}
var delay: Double = 0.0
for i in 0 ..< self.itemViews.count {
let itemView = self.itemViews[i]
let itemSize = itemView.bounds.size
@ -233,14 +268,26 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
fontSize = floor(21.0 * height / 28.0)
}
itemView.update(borderColor: self.focusIndex == i ? theme.activeBorder : theme.inactiveBorder, isHighlighted: self.focusIndex == i)
let borderColor: UInt32
if self.isSucceed {
borderColor = theme.succeedBorder
} else if self.isFailed {
borderColor = theme.failedBorder
} else {
borderColor = self.focusIndex == i ? theme.activeBorder : theme.inactiveBorder
}
itemView.update(borderColor: borderColor, isHighlighted: self.focusIndex == i)
let itemText: String
if i < self.textValue.count {
itemText = String(self.textValue[self.textValue.index(self.textValue.startIndex, offsetBy: i)])
} else {
itemText = ""
}
itemView.update(textColor: theme.foreground, text: itemText, size: itemSize, fontSize: fontSize, animated: animated)
itemView.update(textColor: theme.foreground, text: itemText, size: itemSize, fontSize: fontSize, animated: animated, delay: delay)
if self.isResetting {
delay += 0.05
}
}
}
@ -291,7 +338,17 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
self.itemViews.append(itemView)
self.addSubnode(itemView)
}
itemView.update(borderColor: self.focusIndex == i ? theme.activeBorder : theme.inactiveBorder, isHighlighted: self.focusIndex == i)
let borderColor: UInt32
if self.isSucceed {
borderColor = theme.succeedBorder
} else if self.isFailed {
borderColor = theme.failedBorder
} else {
borderColor = self.focusIndex == i ? theme.activeBorder : theme.inactiveBorder
}
itemView.update(borderColor: borderColor, isHighlighted: self.focusIndex == i)
let itemText: String
if i < self.textValue.count {
itemText = String(self.textValue[self.textValue.index(self.textValue.startIndex, offsetBy: i)])

View File

@ -43,11 +43,17 @@ private func loadCountryCodes() -> [Country] {
let countryId = String(data[codeRange.upperBound ..< idRange.lowerBound])
let maybeNameRange = data.range(of: endOfLine, options: [], range: idRange.upperBound ..< data.endIndex)
guard let patternRange = data.range(of: delimiter, options: [], range: idRange.upperBound ..< data.endIndex) else {
break
}
let pattern = String(data[idRange.upperBound ..< patternRange.lowerBound])
let maybeNameRange = data.range(of: endOfLine, options: [], range: patternRange.upperBound ..< data.endIndex)
let countryName = locale.localizedString(forIdentifier: countryId) ?? ""
if let _ = Int(countryCode) {
let code = Country.CountryCode(code: countryCode, prefixes: [], patterns: [])
let code = Country.CountryCode(code: countryCode, prefixes: [], patterns: !pattern.isEmpty ? [pattern] : [])
let country = Country(id: countryId, name: countryName, localizedName: nil, countryCodes: [code], hidden: false)
result.append(country)
countriesByPrefix["\(code.code)"] = (country, code)
@ -86,6 +92,7 @@ public func loadServerCountryCodes(accountManager: AccountManager<TelegramAccoun
}
}
countryCodesByPrefix = countriesByPrefix
Queue.mainQueue().async {
completion()
}

View File

@ -38,7 +38,11 @@ private func loadCountryCodes() -> [(String, Int)] {
let countryId = String(data[codeRange.upperBound ..< idRange.lowerBound])
let maybeNameRange = data.range(of: endOfLine, options: [], range: idRange.upperBound ..< data.endIndex)
guard let patternRange = data.range(of: delimiter, options: [], range: idRange.upperBound ..< data.endIndex) else {
break
}
let maybeNameRange = data.range(of: endOfLine, options: [], range: patternRange.upperBound ..< data.endIndex)
if let countryCodeInt = Int(countryCode) {
result.append((countryId, countryCodeInt))

View File

@ -57,9 +57,13 @@ private func loadCountriesInfo() -> [(Int, String, String)] {
let countryId = String(data[codeRange.upperBound ..< idRange.lowerBound])
guard let patternRange = data.range(of: delimiter, options: [], range: idRange.upperBound ..< data.endIndex) else {
break
}
let countryName: String
let nameRange1 = data.range(of: endOfLine1, options: [], range: idRange.upperBound ..< data.endIndex)
let nameRange2 = data.range(of: endOfLine2, options: [], range: idRange.upperBound ..< data.endIndex)
let nameRange1 = data.range(of: endOfLine1, options: [], range: patternRange.upperBound ..< data.endIndex)
let nameRange2 = data.range(of: endOfLine2, options: [], range: patternRange.upperBound ..< data.endIndex)
var nameRange: Range<String.Index>?
if let nameRange1 = nameRange1, let nameRange2 = nameRange2 {
if nameRange1.lowerBound < nameRange2.lowerBound {
@ -71,10 +75,10 @@ private func loadCountriesInfo() -> [(Int, String, String)] {
nameRange = nameRange1 ?? nameRange2
}
if let nameRange = nameRange {
countryName = String(data[idRange.upperBound ..< nameRange.lowerBound])
countryName = String(data[patternRange.upperBound ..< nameRange.lowerBound])
currentLocation = nameRange.upperBound
} else {
countryName = String(data[idRange.upperBound ..< data.index(data.endIndex, offsetBy: -1)])
countryName = String(data[patternRange.upperBound ..< data.index(data.endIndex, offsetBy: -1)])
}
array.append((countryCode, countryId, countryName))

View File

@ -73,6 +73,7 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega
var pending: PendingChild?
}
private let isFlat: Bool
public private(set) var controllers: [ViewController] = []
private var state: State = State(layout: nil, canBeClosed: nil, top: nil, transition: nil, pending: nil)
@ -119,7 +120,8 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega
private var panRecognizer: InteractiveTransitionGestureRecognizer?
public init(controllerRemoved: @escaping (ViewController) -> Void) {
public init(isFlat: Bool, controllerRemoved: @escaping (ViewController) -> Void) {
self.isFlat = isFlat
self.controllerRemoved = controllerRemoved
super.init()
@ -224,7 +226,7 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega
bottomController.viewWillAppear(true)
let bottomNode = bottomController.displayNode
let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, isInteractive: true, container: self, topNode: topNode, topNavigationBar: topController.navigationBar, bottomNode: bottomNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self, weak bottomController] progress, transition, topFrame, bottomFrame in
let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, isInteractive: true, isFlat: self.isFlat, container: self, topNode: topNode, topNavigationBar: topController.navigationBar, bottomNode: bottomNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self, weak bottomController] progress, transition, topFrame, bottomFrame in
if let strongSelf = self {
if let top = strongSelf.state.top {
strongSelf.syncKeyboard(leftEdge: top.value.displayNode.frame.minX, transition: transition)
@ -459,7 +461,7 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega
}
toValue.value.setIgnoreAppearanceMethodInvocations(false)
let topTransition = TopTransition(type: transitionType, previous: fromValue, coordinator: NavigationTransitionCoordinator(transition: mappedTransitionType, isInteractive: false, container: self, topNode: topController.displayNode, topNavigationBar: topController.navigationBar, bottomNode: bottomController.displayNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] _, transition, topFrame, bottomFrame in
let topTransition = TopTransition(type: transitionType, previous: fromValue, coordinator: NavigationTransitionCoordinator(transition: mappedTransitionType, isInteractive: false, isFlat: self.isFlat, container: self, topNode: topController.displayNode, topNavigationBar: topController.navigationBar, bottomNode: bottomController.displayNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] _, transition, topFrame, bottomFrame in
guard let strongSelf = self else {
return
}

View File

@ -142,6 +142,7 @@ open class NavigationController: UINavigationController, ContainableController,
private let mode: NavigationControllerMode
private var theme: NavigationControllerTheme
private let isFlat: Bool
var inCallNavigate: (() -> Void)?
private var inCallStatusBar: StatusBar?
@ -235,9 +236,10 @@ open class NavigationController: UINavigationController, ContainableController,
self.requestLayout(transition: transition)
}
public init(mode: NavigationControllerMode, theme: NavigationControllerTheme, backgroundDetailsMode: NavigationEmptyDetailsBackgoundMode? = nil) {
public init(mode: NavigationControllerMode, theme: NavigationControllerTheme, isFlat: Bool = false, backgroundDetailsMode: NavigationEmptyDetailsBackgoundMode? = nil) {
self.mode = mode
self.theme = theme
self.isFlat = isFlat
self.backgroundDetailsMode = backgroundDetailsMode
super.init(nibName: nil, bundle: nil)
@ -759,7 +761,7 @@ open class NavigationController: UINavigationController, ContainableController,
transition.updateFrame(node: flatContainer, frame: CGRect(origin: CGPoint(), size: layout.size))
flatContainer.update(layout: layout, canBeClosed: false, controllers: controllers, transition: transition)
case let .split(splitContainer):
let flatContainer = NavigationContainer(controllerRemoved: { [weak self] controller in
let flatContainer = NavigationContainer(isFlat: self.isFlat, controllerRemoved: { [weak self] controller in
self?.controllerRemoved(controller)
})
flatContainer.statusBarStyleUpdated = { [weak self] transition in
@ -782,7 +784,7 @@ open class NavigationController: UINavigationController, ContainableController,
splitContainer.removeFromSupernode()
}
} else {
let flatContainer = NavigationContainer(controllerRemoved: { [weak self] controller in
let flatContainer = NavigationContainer(isFlat: self.isFlat, controllerRemoved: { [weak self] controller in
self?.controllerRemoved(controller)
})
flatContainer.statusBarStyleUpdated = { [weak self] transition in

View File

@ -51,7 +51,7 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes
self.scrollNode = ASScrollNode()
self.container = NavigationContainer(controllerRemoved: controllerRemoved)
self.container = NavigationContainer(isFlat: false, controllerRemoved: controllerRemoved)
self.container.clipsToBounds = true
super.init()

View File

@ -51,10 +51,10 @@ final class NavigationSplitContainer: ASDisplayNode {
scrollToTop(.detail)
}
self.masterContainer = NavigationContainer(controllerRemoved: controllerRemoved)
self.masterContainer = NavigationContainer(isFlat: false, controllerRemoved: controllerRemoved)
self.masterContainer.clipsToBounds = true
self.detailContainer = NavigationContainer(controllerRemoved: controllerRemoved)
self.detailContainer = NavigationContainer(isFlat: false, controllerRemoved: controllerRemoved)
self.detailContainer.clipsToBounds = true
self.separator = ASDisplayNode()

View File

@ -37,6 +37,7 @@ final class NavigationTransitionCoordinator {
private let container: NavigationContainer
private let transition: NavigationTransition
let isInteractive: Bool
let isFlat: Bool
let topNode: ASDisplayNode
let bottomNode: ASDisplayNode
private let topNavigationBar: NavigationBar?
@ -51,9 +52,10 @@ final class NavigationTransitionCoordinator {
private var currentCompletion: (() -> Void)?
private var didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)?
init(transition: NavigationTransition, isInteractive: Bool, container: NavigationContainer, topNode: ASDisplayNode, topNavigationBar: NavigationBar?, bottomNode: ASDisplayNode, bottomNavigationBar: NavigationBar?, didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? = nil) {
init(transition: NavigationTransition, isInteractive: Bool, isFlat: Bool, container: NavigationContainer, topNode: ASDisplayNode, topNavigationBar: NavigationBar?, bottomNode: ASDisplayNode, bottomNavigationBar: NavigationBar?, didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? = nil) {
self.transition = transition
self.isInteractive = isInteractive
self.isFlat = isFlat
self.container = container
self.didUpdateProgress = didUpdateProgress
self.topNode = topNode
@ -98,8 +100,10 @@ final class NavigationTransitionCoordinator {
self.container.insertSubnode(bottomNode, belowSubnode: topNode)
}
self.container.insertSubnode(self.dimNode, belowSubnode: topNode)
self.container.insertSubnode(self.shadowNode, belowSubnode: self.dimNode)
if !self.isFlat {
self.container.insertSubnode(self.dimNode, belowSubnode: topNode)
self.container.insertSubnode(self.shadowNode, belowSubnode: self.dimNode)
}
if let customTransitionNode = self.customTransitionNode {
self.container.addSubnode(customTransitionNode)
}
@ -135,7 +139,7 @@ final class NavigationTransitionCoordinator {
let containerSize = self.container.bounds.size
let topFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(position * containerSize.width), y: 0.0), size: containerSize)
let bottomFrame = CGRect(origin: CGPoint(x: ((position - 1.0) * containerSize.width * 0.3), y: 0.0), size: containerSize)
let bottomFrame = CGRect(origin: CGPoint(x: self.isFlat ? -floorToScreenPixels((1.0 - position) * containerSize.width) : ((position - 1.0) * containerSize.width * 0.3), y: 0.0), size: containerSize)
var canInvokeCompletion = false
var hadEarlyCompletion = false

View File

@ -203,7 +203,7 @@ public final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate {
self.countryCodeField.textField.returnKeyType = .next
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.countryCodeField.textField.keyboardType = .asciiCapableNumberPad
self.countryCodeField.textField.textContentType = .telephoneNumber
// self.countryCodeField.textField.textContentType = .telephoneNumber
} else {
self.countryCodeField.textField.keyboardType = .numberPad
}
@ -214,7 +214,7 @@ public final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate {
self.numberField.textField.font = font
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.numberField.textField.keyboardType = .asciiCapableNumberPad
self.numberField.textField.textContentType = .telephoneNumber
// self.numberField.textField.textContentType = .telephoneNumber
} else {
self.numberField.textField.keyboardType = .numberPad
}

View File

@ -590,45 +590,14 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
strongSelf.paymentDisposable.set((inAppPurchaseManager.buyProduct(product.storeProduct, targetPeerId: strongSelf.peerId)
|> deliverOnMainQueue).start(next: { [weak self] status in
if let strongSelf = self, case .purchased = status {
strongSelf.activationDisposable.set((strongSelf.context.account.postbox.peerView(id: strongSelf.context.account.peerId)
|> castError(AssignAppStoreTransactionError.self)
|> take(until: { view in
if let peer = view.peers[view.peerId], peer.isPremium {
return SignalTakeAction(passthrough: false, complete: true)
} else {
return SignalTakeAction(passthrough: false, complete: false)
}
})
|> mapToSignal { _ -> Signal<Never, AssignAppStoreTransactionError> in
return .never()
Queue.mainQueue().after(2.0) {
let _ = updatePremiumPromoConfigurationOnce(account: strongSelf.context.account).start()
strongSelf.inProgress = false
strongSelf.updateInProgress(false)
strongSelf.updated(transition: .easeInOut(duration: 0.25))
strongSelf.completion(duration)
}
|> timeout(15.0, queue: Queue.mainQueue(), alternate: .fail(.timeout))
|> deliverOnMainQueue).start(error: { [weak self] _ in
if let strongSelf = self {
strongSelf.inProgress = false
strongSelf.updateInProgress(false)
strongSelf.updated(transition: .immediate)
// addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail")
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
let alertController = textAlertController(context: strongSelf.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
strongSelf.present(alertController)
}
}, completed: { [weak self] in
if let strongSelf = self {
Queue.mainQueue().after(2.0) {
let _ = updatePremiumPromoConfigurationOnce(account: strongSelf.context.account).start()
strongSelf.inProgress = false
strongSelf.updateInProgress(false)
strongSelf.updated(transition: .easeInOut(duration: 0.25))
strongSelf.completion(duration)
}
}
}))
}
}, error: { [weak self] error in
if let strongSelf = self {

View File

@ -61,6 +61,11 @@
@property (nonatomic, copy) void (^startMessaging)(void);
@property (nonatomic, copy) void (^startMessagingInAlternativeLanguage)(NSString *);
@property (nonatomic, copy) UIView *(^createStartButton)(CGFloat);
- (UIView *)createAnimationSnapshot;
- (UIView *)createTextSnapshot;
@property (nonatomic) bool isEnabled;
- (void)startTimer;

View File

@ -24,7 +24,7 @@
_headline=headline;
UILabel *headlineLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, 64+8)];
headlineLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:IPAD ? 96/2 : 36];
headlineLabel.font = [UIFont boldSystemFontOfSize:35.0]; //[UIFont fontWithName:@"HelveticaNeue-Light" size:IPAD ? 96/2 : 36];
headlineLabel.text = _headline;
headlineLabel.textColor = color;
headlineLabel.textAlignment = NSTextAlignmentCenter;
@ -32,14 +32,11 @@
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = IPAD ? 6 : 5;
style.lineSpacing = IPAD ? 4 : 3;
style.lineBreakMode = NSLineBreakByWordWrapping;
style.alignment = NSTextAlignmentCenter;
NSMutableArray *boldRanges = [[NSMutableArray alloc] init];
NSMutableString *cleanText = [[NSMutableString alloc] initWithString:description];
@ -60,11 +57,9 @@
[boldRanges addObject:[NSValue valueWithRange:NSMakeRange(startRange.location, endRange.location - startRange.location)]];
}
_description = [[NSMutableAttributedString alloc]initWithString:cleanText];
NSDictionary *boldAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:@"HelveticaNeue-Medium" size:IPAD ? 44/2 : 17], NSFontAttributeName, nil];
[UIFont boldSystemFontOfSize:IPAD ? 22 : 17.0], NSFontAttributeName, nil];
for (NSValue *nRange in boldRanges)
{
[_description addAttributes:boldAttributes range:[nRange rangeValue]];
@ -76,7 +71,7 @@
[_description addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, _description.length)];
UILabel *descriptionLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 25 + (IPAD ? 22 : 0), frame.size.width, 120+8+5)];
descriptionLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:IPAD ? 44/2 : 17];
descriptionLabel.font = [UIFont systemFontOfSize:IPAD ? 22 : 17.0];
descriptionLabel.attributedText = _description;
descriptionLabel.numberOfLines=0;
descriptionLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;

View File

@ -93,7 +93,6 @@ typedef enum {
UIColor *_regularDotColor;
UIColor *_highlightedDotColor;
UIButton *_startButton;
TGModernButton *_alternativeLanguageButton;
SMetaDisposable *_localizationsDisposable;
@ -102,6 +101,8 @@ typedef enum {
SVariable *_alternativeLocalization;
NSDictionary<NSString *, NSString *> *_englishStrings;
UIView *_wrapperView;
bool _loadedView;
}
@end
@ -308,6 +309,9 @@ typedef enum {
[self loadGL];
_wrapperView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_wrapperView];
_pageScrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
_pageScrollView.clipsToBounds = true;
_pageScrollView.opaque = true;
@ -317,7 +321,7 @@ typedef enum {
_pageScrollView.pagingEnabled = true;
_pageScrollView.contentSize = CGSizeMake(_headlines.count * self.view.bounds.size.width, self.view.bounds.size.height);
_pageScrollView.delegate = self;
[self.view addSubview:_pageScrollView];
[_wrapperView addSubview:_pageScrollView];
_pageViews = [NSMutableArray array];
@ -331,41 +335,6 @@ typedef enum {
}
[_pageScrollView setPage:0];
_startButton = [[UIButton alloc] init];
_startButton.adjustsImageWhenDisabled = false;
[_startButton setTitle:_englishStrings[@"Tour.StartButton"] forState:UIControlStateNormal];
[_startButton.titleLabel setFont:TGMediumSystemFontOfSize(20.0f)];
[_startButton setTitleColor:_backgroundColor forState:UIControlStateNormal];
static UIImage *buttonBackgroundImage = nil;
static UIImage *buttonHighlightedBackgroundImage = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(48.0, 48.0), false, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [_buttonColor CGColor]);
CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 48.0f, 48.0f));
buttonBackgroundImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:24 topCapHeight:24];
UIGraphicsEndImageContext();
}
{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(48.0, 48.0), false, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat hue = 0.0f;
CGFloat sat = 0.0f;
CGFloat bri = 0.0f;
[_buttonColor getHue:&hue saturation:&sat brightness:&bri alpha:nil];
UIColor *color = [[UIColor alloc] initWithHue:hue saturation:sat brightness:bri * 0.7 alpha:1.0];
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 48.0f, 48.0f));
buttonHighlightedBackgroundImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:24 topCapHeight:24];
UIGraphicsEndImageContext();
}
});
[_startButton setContentEdgeInsets:UIEdgeInsetsMake(0.0f, 20.0f, 0.0f, 20.0f)];
[_startButton setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal];
[_startButton setBackgroundImage:buttonHighlightedBackgroundImage forState:UIControlStateHighlighted];
[self.view addSubview:_startButton];
[self.view addSubview:_alternativeLanguageButton];
_pageControl = [[UIPageControl alloc] init];
@ -374,7 +343,20 @@ typedef enum {
[_pageControl setNumberOfPages:6];
_pageControl.pageIndicatorTintColor = _regularDotColor;
_pageControl.currentPageIndicatorTintColor = _highlightedDotColor;
[self.view addSubview:_pageControl];
[_wrapperView addSubview:_pageControl];
}
- (UIView *)createAnimationSnapshot {
UIImage *image = _glkView.snapshot;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:_glkView.frame];
imageView.image = image;
return imageView;
}
- (UIView *)createTextSnapshot {
UIView *snapshotView = [_wrapperView snapshotViewAfterScreenUpdates:false];
snapshotView.frame = _wrapperView.frame;
return snapshotView;
}
- (BOOL)shouldAutorotate
@ -527,12 +509,16 @@ typedef enum {
_pageControl.frame = CGRectMake(0, pageControlY, self.view.bounds.size.width, 7);
_glkView.frame = CGRectChangedOriginY(_glkView.frame, glViewY - statusBarHeight);
[_startButton sizeToFit];
_startButton.frame = CGRectMake(floor((self.view.bounds.size.width - _startButton.frame.size.width) / 2.0f), self.view.bounds.size.height - startButtonY - statusBarHeight, _startButton.frame.size.width, 48.0f);
[_startButton addTarget:self action:@selector(startButtonPress) forControlEvents:UIControlEventTouchUpInside];
CGFloat startButtonWidth = self.view.bounds.size.width - 48.0f;
UIView *startButton = self.createStartButton(startButtonWidth);
if (startButton.superview == nil) {
[self.view addSubview:startButton];
}
startButton.frame = CGRectMake(floor((self.view.bounds.size.width - startButtonWidth) / 2.0f), self.view.bounds.size.height - startButtonY - statusBarHeight, startButtonWidth, 50.0f);
_alternativeLanguageButton.frame = CGRectMake(floor((self.view.bounds.size.width - _alternativeLanguageButton.frame.size.width) / 2.0f), CGRectGetMaxY(_startButton.frame) + languageButtonOffset, _alternativeLanguageButton.frame.size.width, _alternativeLanguageButton.frame.size.height);
_alternativeLanguageButton.frame = CGRectMake(floor((self.view.bounds.size.width - _alternativeLanguageButton.frame.size.width) / 2.0f), CGRectGetMaxY(startButton.frame) + languageButtonOffset, _alternativeLanguageButton.frame.size.width, _alternativeLanguageButton.frame.size.height);
_wrapperView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
_pageScrollView.frame=CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height - 20);
_pageScrollView.contentSize=CGSizeMake(_headlines.count * self.view.bounds.size.width, 150);
_pageScrollView.contentOffset = CGPointMake(_currentPage * self.view.bounds.size.width, 0);
@ -691,7 +677,6 @@ NSInteger _current_page_end;
- (void)setIsEnabled:(bool)isEnabled {
if (_isEnabled != isEnabled) {
_isEnabled = isEnabled;
_startButton.alpha = _isEnabled ? 1.0 : 0.6;
_alternativeLanguageButton.alpha = _isEnabled ? 1.0 : 0.6;
}
}

View File

@ -137,11 +137,11 @@ private struct ChangePhoneNumberCodeControllerState: Equatable {
}
}
private func changePhoneNumberCodeControllerEntries(presentationData: PresentationData, state: ChangePhoneNumberCodeControllerState, codeData: ChangeAccountPhoneNumberData, timeout: Int32?, strings: PresentationStrings) -> [ChangePhoneNumberCodeEntry] {
private func changePhoneNumberCodeControllerEntries(presentationData: PresentationData, state: ChangePhoneNumberCodeControllerState, codeData: ChangeAccountPhoneNumberData, timeout: Int32?, strings: PresentationStrings, phoneNumber: String) -> [ChangePhoneNumberCodeEntry] {
var entries: [ChangePhoneNumberCodeEntry] = []
entries.append(.codeEntry(presentationData.theme, presentationData.strings, presentationData.strings.ChangePhoneNumberCode_CodePlaceholder, state.codeText))
var text = authorizationCurrentOptionText(codeData.type, strings: presentationData.strings, primaryColor: presentationData.theme.list.itemPrimaryTextColor, accentColor: presentationData.theme.list.itemAccentColor).string
var text = authorizationCurrentOptionText(codeData.type, phoneNumber: phoneNumber, email: nil, strings: presentationData.strings, primaryColor: presentationData.theme.list.itemPrimaryTextColor, accentColor: presentationData.theme.list.itemAccentColor).string
if let nextType = codeData.nextType {
text += "\n\n" + authorizationNextOptionText(currentType: codeData.type, nextType: nextType, timeout: timeout, strings: presentationData.strings, primaryColor: .black, accentColor: .black).0.string
}
@ -316,7 +316,7 @@ func changePhoneNumberCodeController(context: AccountContext, phoneNumber: Strin
}
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(formatPhoneNumber(phoneNumber)), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: changePhoneNumberCodeControllerEntries(presentationData: presentationData, state: state, codeData: data, timeout: timeout, strings: presentationData.strings), style: .blocks, focusItemTag: ChangePhoneNumberCodeTag.input, emptyStateItem: nil, animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: changePhoneNumberCodeControllerEntries(presentationData: presentationData, state: state, codeData: data, timeout: timeout, strings: presentationData.strings, phoneNumber: phoneNumber), style: .blocks, focusItemTag: ChangePhoneNumberCodeTag.input, emptyStateItem: nil, animateChanges: false)
return (controllerState, (listState, arguments))
} |> afterDisposed {

View File

@ -263,7 +263,7 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
self.setupGloss()
}
private func setupGloss() {
if self.gloss {
if self.shimmerView == nil {
@ -312,6 +312,39 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
}
}
public func animateTitle(from title: String) {
let originalTitle = self.title ?? ""
self.title = title
Queue.mainQueue().justDispatch {
if let snapshotView = self.titleNode.view.snapshotView(afterScreenUpdates: false) {
snapshotView.frame = self.titleNode.frame
self.view.insertSubview(snapshotView, aboveSubview: self.titleNode.view)
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
})
self.titleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.title = originalTitle
}
}
}
public func animateTitle(to title: String) {
if let snapshotView = self.titleNode.view.snapshotView(afterScreenUpdates: false) {
snapshotView.frame = self.titleNode.frame
self.view.insertSubview(snapshotView, aboveSubview: self.titleNode.view)
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
})
self.titleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.title = title
}
}
private func setupGradientAnimations() {
guard let buttonBackgroundAnimationView = self.buttonBackgroundAnimationView else {
return

View File

@ -1,232 +1,235 @@
1876;JM;Jamaica
1869;KN;Saint Kitts & Nevis
1868;TT;Trinidad & Tobago
1784;VC;Saint Vincent & the Grenadines
1767;DM;Dominica
1758;LC;Saint Lucia
1721;SX;Sint Maarten
1684;AS;American Samoa
1671;GU;Guam
1670;MP;Northern Mariana Islands
1664;MS;Montserrat
1649;TC;Turks & Caicos Islands
1473;GD;Grenada
1441;BM;Bermuda
1345;KY;Cayman Islands
1340;VI;US Virgin Islands
1284;VG;British Virgin Islands
1268;AG;Antigua & Barbuda
1264;AI;Anguilla
1246;BB;Barbados
1242;BS;Bahamas
998;UZ;Uzbekistan
996;KG;Kyrgyzstan
995;GE;Georgia
994;AZ;Azerbaijan
993;TM;Turkmenistan
992;TJ;Tajikistan
977;NP;Nepal
976;MN;Mongolia
975;BT;Bhutan
974;QA;Qatar
973;BH;Bahrain
972;IL;Israel
971;AE;United Arab Emirates
970;PS;Palestine
968;OM;Oman
967;YE;Yemen
966;SA;Saudi Arabia
965;KW;Kuwait
964;IQ;Iraq
963;SY;Syrian Arab Republic
962;JO;Jordan
961;LB;Lebanon
960;MV;Maldives
886;TW;Taiwan
880;BD;Bangladesh
856;LA;Laos
855;KH;Cambodia
853;MO;Macau
852;HK;Hong Kong
850;KP;North Korea
692;MH;Marshall Islands
691;FM;Micronesia
690;TK;Tokelau
689;PF;French Polynesia
688;TV;Tuvalu
687;NC;New Caledonia
686;KI;Kiribati
685;WS;Samoa
683;NU;Niue
682;CK;Cook Islands
681;WF;Wallis & Futuna
680;PW;Palau
679;FJ;Fiji
678;VU;Vanuatu
677;SB;Solomon Islands
676;TO;Tonga
675;PG;Papua New Guinea
674;NR;Nauru
673;BN;Brunei Darussalam
672;NF;Norfolk Island
670;TL;Timor-Leste
599;BQ;Bonaire, Sint Eustatius & Saba
599;CW;Curaçao
598;UY;Uruguay
597;SR;Suriname
596;MQ;Martinique
595;PY;Paraguay
594;GF;French Guiana
593;EC;Ecuador
592;GY;Guyana
591;BO;Bolivia
590;GP;Guadeloupe
509;HT;Haiti
508;PM;Saint Pierre & Miquelon
507;PA;Panama
506;CR;Costa Rica
505;NI;Nicaragua
504;HN;Honduras
503;SV;El Salvador
502;GT;Guatemala
501;BZ;Belize
500;FK;Falkland Islands
423;LI;Liechtenstein
421;SK;Slovakia
420;CZ;Czech Republic
383;XK;Kosovo
389;MK;Macedonia
387;BA;Bosnia & Herzegovina
386;SI;Slovenia
385;HR;Croatia
382;ME;Montenegro
381;RS;Serbia
380;UA;Ukraine
378;SM;San Marino
377;MC;Monaco
376;AD;Andorra
375;BY;Belarus
374;AM;Armenia
373;MD;Moldova
372;EE;Estonia
371;LV;Latvia
370;LT;Lithuania
359;BG;Bulgaria
358;FI;Finland
357;CY;Cyprus
356;MT;Malta
355;AL;Albania
354;IS;Iceland
353;IE;Ireland
352;LU;Luxembourg
351;PT;Portugal
350;GI;Gibraltar
299;GL;Greenland
298;FO;Faroe Islands
297;AW;Aruba
291;ER;Eritrea
290;SH;Saint Helena
269;KM;Comoros
268;SZ;Swaziland
267;BW;Botswana
266;LS;Lesotho
265;MW;Malawi
264;NA;Namibia
263;ZW;Zimbabwe
262;RE;Réunion
261;MG;Madagascar
260;ZM;Zambia
258;MZ;Mozambique
257;BI;Burundi
256;UG;Uganda
255;TZ;Tanzania
254;KE;Kenya
253;DJ;Djibouti
252;SO;Somalia
251;ET;Ethiopia
250;RW;Rwanda
249;SD;Sudan
248;SC;Seychelles
247;SH;Saint Helena
246;IO;Diego Garcia
245;GW;Guinea-Bissau
244;AO;Angola
243;CD;Congo (Dem. Rep.)
242;CG;Congo (Rep.)
241;GA;Gabon
240;GQ;Equatorial Guinea
239;ST;São Tomé & Príncipe
238;CV;Cape Verde
237;CM;Cameroon
236;CF;Central African Rep.
235;TD;Chad
234;NG;Nigeria
233;GH;Ghana
232;SL;Sierra Leone
231;LR;Liberia
230;MU;Mauritius
229;BJ;Benin
228;TG;Togo
227;NE;Niger
226;BF;Burkina Faso
225;CI;Côte d`Ivoire
224;GN;Guinea
223;ML;Mali
222;MR;Mauritania
221;SN;Senegal
220;GM;Gambia
218;LY;Libya
216;TN;Tunisia
213;DZ;Algeria
212;MA;Morocco
211;SS;South Sudan
98;IR;Iran
95;MM;Myanmar
94;LK;Sri Lanka
93;AF;Afghanistan
92;PK;Pakistan
91;IN;India
90;TR;Turkey
86;CN;China
84;VN;Vietnam
82;KR;South Korea
81;JP;Japan
66;TH;Thailand
65;SG;Singapore
64;NZ;New Zealand
63;PH;Philippines
62;ID;Indonesia
61;AU;Australia
60;MY;Malaysia
58;VE;Venezuela
57;CO;Colombia
56;CL;Chile
55;BR;Brazil
54;AR;Argentina
53;CU;Cuba
52;MX;Mexico
51;PE;Peru
49;DE;Germany
48;PL;Poland
47;NO;Norway
46;SE;Sweden
45;DK;Denmark
44;GB;United Kingdom
43;AT;Austria
41;CH;Switzerland
40;RO;Romania
39;IT;Italy
36;HU;Hungary
34;ES;Spain
33;FR;France
32;BE;Belgium
31;NL;Netherlands
30;GR;Greece
27;ZA;South Africa
20;EG;Egypt
7;RU;Russian Federation
7;KZ;Kazakhstan
1;US;USA
1;PR;Puerto Rico
1;DO;Dominican Rep.
1;CA;Canada
376;AD;XX XX XX;Andorra
971;AE;XX XXX XXXX;United Arab Emirates
93;AF;XXX XXX XXX;Afghanistan
1268;AG;XXX XXXX;Antigua & Barbuda
1264;AI;XXX XXXX;Anguilla
355;AL;XX XXX XXXX;Albania
374;AM;XX XXX XXX;Armenia
244;AO;XXX XXX XXX;Angola
54;AR;;Argentina
1684;AS;XXX XXXX;American Samoa
43;AT;XXX XXXXXX;Austria
61;AU;X XXXX XXXX;Australia
297;AW;XXX XXXX;Aruba
994;AZ;XX XXX XXXX;Azerbaijan
387;BA;XX XXX XXX;Bosnia & Herzegovina
1246;BB;XXX XXXX;Barbados
880;BD;XX XXX XXX;Bangladesh
32;BE;XXX XX XX XX;Belgium
226;BF;XX XX XX XX;Burkina Faso
359;BG;;Bulgaria
973;BH;XXXX XXXX;Bahrain
257;BI;XX XX XXXX;Burundi
229;BJ;XX XXX XXX;Benin
1441;BM;XXX XXXX;Bermuda
673;BN;XXX XXXX;Brunei Darussalam
591;BO;X XXX XXXX;Bolivia
599;BQ;;Bonaire, Sint Eustatius & Saba
55;BR;XX XXXXX XXXX;Brazil
1242;BS;XXX XXXX;Bahamas
975;BT;XX XXX XXX;Bhutan
267;BW;XX XXX XXX;Botswana
375;BY;XX XXX XXXX;Belarus
501;BZ;;Belize
1;US;XXX XXX XXXX;United States
1;CA;XXX XXX XXXX;Canada
243;CD;XX XXX XXXX;Congo (Dem. Rep.)
236;CF;XX XX XX XX;Central African Rep.
242;CG;XX XXX XXXX;Congo (Rep.)
41;CH;XX XXX XXXX;Switzerland
225;CI;XX XX XX XXXX;Côte d'Ivoire
682;CK;;Cook Islands
56;CL;X XXXX XXXX;Chile
237;CM;XXXX XXXX;Cameroon
86;CN;XXX XXXX XXXX;China
57;CO;XXX XXX XXXX;Colombia
506;CR;XXXX XXXX;Costa Rica
53;CU;X XXX XXXX;Cuba
238;CV;XXX XXXX;Cape Verde
599;CW;;Curaçao
357;CY;XXXX XXXX;Cyprus
420;CZ;XXX XXX XXX;Czech Republic
49;DE;;Germany
253;DJ;XX XX XX XX;Djibouti
45;DK;XXXX XXXX;Denmark
1767;DM;XXX XXXX;Dominica
1809;DO;XXX XXXX;Dominican Rep.
1829;DO;XXX XXXX;Dominican Rep.
1849;DO;XXX XXXX;Dominican Rep.
213;DZ;XXX XX XX XX;Algeria
593;EC;XX XXX XXXX;Ecuador
372;EE;XXXX XXX;Estonia
20;EG;XX XXXX XXXX;Egypt
291;ER;X XXX XXX;Eritrea
34;ES;XXX XXX XXX;Spain
251;ET;XX XXX XXX;Ethiopia
358;FI;;Finland
679;FJ;XXX XXXX;Fiji
500;FK;;Falkland Islands
691;FM;;Micronesia
298;FO;XXX XXX;Faroe Islands
33;FR;X XX XX XX XX;France
241;GA;X XX XX XX;Gabon
44;GB;XXXX XXXXXX;United Kingdom
1473;GD;XXX XXXX;Grenada
995;GE;XXX XXX XXX;Georgia
594;GF;;French Guiana
233;GH;XX XXX XXXX;Ghana
350;GI;XXXX XXXX;Gibraltar
299;GL;XXX XXX;Greenland
220;GM;XXX XXXX;Gambia
224;GN;XXX XXX XXX;Guinea
590;GP;XXX XX XX XX;Guadeloupe
240;GQ;XXX XXX XXX;Equatorial Guinea
30;GR;XXX XXX XXXX;Greece
502;GT;X XXX XXXX;Guatemala
1671;GU;XXX XXXX;Guam
245;GW;XXX XXXX;Guinea-Bissau
592;GY;;Guyana
852;HK;X XXX XXXX;Hong Kong
504;HN;XXXX XXXX;Honduras
385;HR;XX XXX XXX;Croatia
509;HT;XXXX XXXX;Haiti
36;HU;XXX XXX XXX;Hungary
62;ID;XXX XXXXXX;Indonesia
353;IE;XX XXX XXXX;Ireland
972;IL;XX XXX XXXX;Israel
91;IN;XXXXX XXXXX;India
246;IO;XXX XXXX;Diego Garcia
964;IQ;XXX XXX XXXX;Iraq
98;IR;XXX XXX XXXX;Iran
354;IS;XXX XXXX;Iceland
39;IT;XXX XXX XXXX;Italy
1876;JM;XXX XXXX;Jamaica
962;JO;X XXXX XXXX;Jordan
81;JP;XX XXXX XXXX;Japan
254;KE;XXX XXX XXX;Kenya
996;KG;XXX XXXXXX;Kyrgyzstan
855;KH;XX XXX XXX;Cambodia
686;KI;XXXX XXXX;Kiribati
269;KM;XXX XXXX;Comoros
1869;KN;XXX XXXX;Saint Kitts & Nevis
850;KP;;North Korea
82;KR;XX XXXX XXX;South Korea
965;KW;XXXX XXXX;Kuwait
1345;KY;XXX XXXX;Cayman Islands
7;RU;XXX XXX XXXX;Russian Federation
7;KZ;XXX XXX XX XX;Kazakhstan
856;LA;XX XX XXX XXX;Laos
961;LB;;Lebanon
1758;LC;XXX XXXX;Saint Lucia
423;LI;XXX XXXX;Liechtenstein
94;LK;XX XXX XXXX;Sri Lanka
231;LR;XX XXX XXXX;Liberia
266;LS;XX XXX XXX;Lesotho
370;LT;XXX XXXXX;Lithuania
352;LU;XXX XXX XXX;Luxembourg
371;LV;XXX XXXXX;Latvia
218;LY;XX XXX XXXX;Libya
212;MA;XX XXX XXXX;Morocco
377;MC;XXXX XXXX;Monaco
373;MD;XX XXX XXX;Moldova
382;ME;;Montenegro
261;MG;XX XX XXX XX;Madagascar
692;MH;;Marshall Islands
389;MK;XX XXXXXX;North Macedonia
223;ML;XXXX XXXX;Mali
95;MM;;Myanmar
976;MN;XX XX XXXX;Mongolia
853;MO;XXXX XXXX;Macau
1670;MP;XXX XXXX;Northern Mariana Islands
596;MQ;;Martinique
222;MR;XXXX XXXX;Mauritania
1664;MS;XXX XXXX;Montserrat
356;MT;XX XX XX XX;Malta
230;MU;XXXX XXXX;Mauritius
960;MV;XXX XXXX;Maldives
265;MW;XX XXX XXXX;Malawi
52;MX;;Mexico
60;MY;;Malaysia
258;MZ;XX XXX XXXX;Mozambique
264;NA;XX XXX XXXX;Namibia
687;NC;;New Caledonia
227;NE;XX XX XX XX;Niger
672;NF;;Norfolk Island
234;NG;XX XXXX XXXX;Nigeria
505;NI;XXXX XXXX;Nicaragua
31;NL;X XX XX XX XX;Netherlands
47;NO;XXX XX XXX;Norway
977;NP;XX XXXX XXXX;Nepal
674;NR;;Nauru
683;NU;;Niue
64;NZ;XXXX XXXX;New Zealand
968;OM;XXXX XXXX;Oman
507;PA;XXXX XXXX;Panama
51;PE;XXX XXX XXX;Peru
689;PF;;French Polynesia
675;PG;;Papua New Guinea
63;PH;XXX XXX XXXX;Philippines
92;PK;XXX XXX XXXX;Pakistan
48;PL;XXX XXX XXX;Poland
508;PM;;Saint Pierre & Miquelon
1787;PR;XXX XXXX;Puerto Rico
1939;PR;XXX XXXX;Puerto Rico
970;PS;XXX XX XXXX;Palestine
351;PT;XXX XXX XXX;Portugal
680;PW;;Palau
595;PY;XXX XXX XXX;Paraguay
974;QA;XX XXX XXX;Qatar
262;RE;XXX XXX XXX;Réunion
40;RO;XXX XXX XXX;Romania
381;RS;XX XXX XXX;Serbia
250;RW;XXX XXX XXX;Rwanda
966;SA;XX XXX XXXX;Saudi Arabia
677;SB;;Solomon Islands
248;SC;X XX XX XX;Seychelles
249;SD;XX XXX XXXX;Sudan
46;SE;XX XXX XXXX;Sweden
65;SG;XXXX XXXX;Singapore
247;SH;;Saint Helena
290;SH;XX XXX;Saint Helena
386;SI;XX XXX XXX;Slovenia
421;SK;XXX XXX XXX;Slovakia
232;SL;XX XXX XXX;Sierra Leone
378;SM;;San Marino
221;SN;XX XXX XXXX;Senegal
252;SO;XX XXX XXX;Somalia
597;SR;XXX XXXX;Suriname
211;SS;XX XXX XXXX;South Sudan
239;ST;XX XXXXX;São Tomé & Príncipe
503;SV;XXXX XXXX;El Salvador
1721;SX;XXX XXXX;Sint Maarten
963;SY;XXX XXX XXX;Syria
268;SZ;XXXX XXXX;Eswatini
1649;TC;XXX XXXX;Turks & Caicos Islands
235;TD;XX XX XX XX;Chad
228;TG;XX XXX XXX;Togo
66;TH;X XXXX XXXX;Thailand
992;TJ;XX XXX XXXX;Tajikistan
690;TK;;Tokelau
670;TL;;Timor-Leste
993;TM;XX XXXXXX;Turkmenistan
216;TN;XX XXX XXX;Tunisia
676;TO;;Tonga
90;TR;XXX XXX XXXX;Turkey
1868;TT;XXX XXXX;Trinidad & Tobago
688;TV;;Tuvalu
886;TW;XXX XXX XXX;Taiwan
255;TZ;XX XXX XXXX;Tanzania
380;UA;XX XXX XX XX;Ukraine
256;UG;XX XXX XXXX;Uganda
598;UY;X XXX XXXX;Uruguay
998;UZ;XX XXX XX XX;Uzbekistan
1784;VC;XXX XXXX;Saint Vincent & the Grenadines
58;VE;XXX XXX XXXX;Venezuela
1284;VG;XXX XXXX;British Virgin Islands
1340;VI;XXX XXXX;US Virgin Islands
84;VN;;Vietnam
678;VU;;Vanuatu
681;WF;;Wallis & Futuna
685;WS;;Samoa
383;XK;XXXX XXXX;Kosovo
967;YE;XXX XXX XXX;Yemen
27;ZA;XX XXX XXXX;South Africa
260;ZM;XX XXX XXXX;Zambia
263;ZW;XX XXX XXXX;Zimbabwe

View File

@ -1105,8 +1105,10 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|> take(1)
|> timeout(4.0, queue: .mainQueue(), alternate: .complete())
|> deliverOnMainQueue).start(completed: {
authContextValue.rootController.view.endEditing(true)
authContextValue.rootController.dismiss()
Queue.mainQueue().after(0.75) {
authContextValue.rootController.view.endEditing(true)
authContextValue.rootController.dismiss()
}
})
} else {
authContextValue.rootController.view.endEditing(true)

View File

@ -115,6 +115,15 @@ final class AuthorizationSequenceCodeEntryController: ViewController {
self.controllerNode.resetCode()
}
func animateSuccess() {
self.controllerNode.animateSuccess()
}
func animateError(text: String) {
self.hapticFeedback.error()
self.controllerNode.animateError(text: text)
}
func updateData(number: String, codeType: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, timeout: Int32?, termsOfService: (UnauthorizedAccountTermsOfService, Bool)?) {
self.termsOfService = termsOfService
if self.data?.0 != number || self.data?.1 != codeType || self.data?.2 != nextType || self.data?.3 != timeout {

View File

@ -33,6 +33,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
private var signInWithAppleButton: UIControl?
private let codeInputView: CodeInputView
private let errorTextNode: ImmediateTextNode
private var codeType: SentAuthorizationCodeType?
@ -69,7 +70,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.codeInputView.alpha = self.inProgress ? 0.6 : 1.0
}
}
init(strings: PresentationStrings, theme: PresentationTheme) {
self.strings = strings
self.theme = theme
@ -119,6 +120,11 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.codeInputView.textField.keyboardType = .numberPad
}
self.errorTextNode = ImmediateTextNode()
self.errorTextNode.alpha = 0.0
self.errorTextNode.displaysAsynchronously = false
self.errorTextNode.textAlignment = .center
self.dividerNode = AuthorizationDividerNode(theme: self.theme, strings: self.strings)
if #available(iOS 13.0, *) {
@ -136,8 +142,6 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.backgroundColor = self.theme.list.plainBackgroundColor
self.addSubnode(self.codeInputView)
//self.addSubnode(self.codeSeparatorNode)
//self.addSubnode(self.codeField)
self.addSubnode(self.titleNode)
self.addSubnode(self.titleIconNode)
self.addSubnode(self.currentOptionNode)
@ -145,6 +149,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.addSubnode(self.nextOptionButtonNode)
self.addSubnode(self.animationNode)
self.addSubnode(self.dividerNode)
self.addSubnode(self.errorTextNode)
self.codeInputView.updated = { [weak self] in
guard let strongSelf = self else {
@ -208,7 +213,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
}
self.appleSignInAllowed = appleSignInAllowed
self.currentOptionNode.attributedText = authorizationCurrentOptionText(codeType, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor)
self.currentOptionNode.attributedText = authorizationCurrentOptionText(codeType, phoneNumber: self.phoneNumber, email: nil, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor)
if case .missedCall = codeType {
self.currentOptionInfoNode.attributedText = NSAttributedString(string: self.strings.Login_CodePhonePatternInfoText, font: Font.regular(17.0), textColor: self.theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
} else {
@ -259,18 +264,18 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
var animationName = "IntroMessage"
if let codeType = self.codeType {
switch codeType {
case .otherSession:
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_CheckOtherSessionMessages, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
case .missedCall:
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterMissingDigits, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
case .email:
self.titleNode.attributedText = NSAttributedString(string: "Check Your Email", font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeEmailTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
animationName = "IntroLetter"
case .sms:
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeSMSTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
default:
self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeTelegramTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
}
} else {
self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.semibold(40.0), textColor: self.theme.list.itemPrimaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeTelegramTitle, font: Font.semibold(40.0), textColor: self.theme.list.itemPrimaryTextColor)
}
if let inputHeight = layout.inputHeight {
@ -286,11 +291,11 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.animationNode.visibility = true
}
let animationSize = CGSize(width: 88.0, height: 88.0)
let animationSize = CGSize(width: 100.0, height: 100.0)
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let currentOptionSize = self.currentOptionNode.updateLayout(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude))
let currentOptionInfoSize = self.currentOptionInfoNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude))
let currentOptionSize = self.currentOptionNode.updateLayout(CGSize(width: layout.size.width - 48.0, height: CGFloat.greatestFiniteMagnitude))
let currentOptionInfoSize = self.currentOptionInfoNode.measure(CGSize(width: layout.size.width - 48.0, height: CGFloat.greatestFiniteMagnitude))
let nextOptionSize = self.nextOptionTitleNode.updateLayout(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let codeLength: Int
@ -323,6 +328,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
theme: CodeInputView.Theme(
inactiveBorder: self.theme.list.itemPlainSeparatorColor.argb,
activeBorder: self.theme.list.itemAccentColor.argb,
succeedBorder: self.theme.list.itemDisclosureActions.constructive.fillColor.argb,
failedBorder: self.theme.list.itemDestructiveColor.argb,
foreground: self.theme.list.itemPrimaryTextColor.argb,
isDark: self.theme.overallDarkAppearance
),
@ -372,9 +379,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 18.0, maxValue: 18.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.currentOptionNode, size: currentOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 10.0, maxValue: 10.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.codeInputView, size: codeFieldSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
//items.append(AuthorizationLayoutItem(node: self.codeField, size: CGSize(width: layout.size.width - 88.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
//items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 88.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.codeInputView, size: codeFieldSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 30.0, maxValue: 30.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
case .missedCall:
@ -393,15 +398,11 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
})
}
// items.append(AuthorizationLayoutItem(node: self.titleIconNode, size: self.titleIconNode.image!.size, spacingBefore: AuthorizationLayoutItemSpacing(weight: 41.0, maxValue: 41.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 18.0, maxValue: 18.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.currentOptionNode, size: currentOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 10.0, maxValue: 10.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.codeInputView, size: codeFieldSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
/*items.append(AuthorizationLayoutItem(node: self.codeField, size: CGSize(width: layout.size.width - 88.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 88.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))*/
items.append(AuthorizationLayoutItem(node: self.currentOptionInfoNode, size: currentOptionInfoSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 60.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
@ -467,12 +468,38 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
func activateInput() {
let _ = self.codeInputView.becomeFirstResponder()
//self.codeField.textField.becomeFirstResponder()
}
func animateError() {
self.codeInputView.layer.addShakeAnimation()
//self.codeField.layer.addShakeAnimation()
}
func animateError(text: String) {
self.codeInputView.animateError()
self.codeInputView.layer.addShakeAnimation(amplitude: -30.0, duration: 0.5, count: 6, decay: true)
self.errorTextNode.attributedText = NSAttributedString(string: text, font: Font.regular(17.0), textColor: self.theme.list.itemDestructiveColor, paragraphAlignment: .center)
if let (layout, _) = self.layoutArguments {
let errorTextSize = self.errorTextNode.updateLayout(CGSize(width: layout.size.width - 48.0, height: .greatestFiniteMagnitude))
self.errorTextNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - errorTextSize.width) / 2.0), y: self.codeInputView.frame.maxY + 28.0), size: errorTextSize)
}
self.errorTextNode.alpha = 1.0
self.errorTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
self.errorTextNode.layer.addShakeAnimation(amplitude: -8.0, duration: 0.5, count: 6, decay: true)
Queue.mainQueue().after(0.85) {
self.errorTextNode.alpha = 0.0
self.errorTextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15)
}
}
func animateSuccess() {
self.codeInputView.animateSuccess()
let values: [NSNumber] = [1.0, 1.1, 1.0]
self.codeInputView.layer.animateKeyframes(values: values, duration: 0.4, keyPath: "transform.scale")
}
@objc func codeFieldTextChanged(_ textField: UITextField) {

View File

@ -68,7 +68,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
navigationStatusBar = .white
}
super.init(mode: .single, theme: NavigationControllerTheme(statusBar: navigationStatusBar, navigationBar: AuthorizationSequenceController.navigationBarTheme(presentationData.theme), emptyAreaColor: .black))
super.init(mode: .single, theme: NavigationControllerTheme(statusBar: navigationStatusBar, navigationBar: AuthorizationSequenceController.navigationBarTheme(presentationData.theme), emptyAreaColor: .black), isFlat: true)
self.stateDisposable = (TelegramEngineUnauthorized(account: self.account).auth.state()
|> map { state -> InnerState in
@ -130,7 +130,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
return controller
}
private func phoneEntryController(countryCode: Int32, number: String) -> AuthorizationSequencePhoneEntryController {
private func phoneEntryController(countryCode: Int32, number: String, splashController: AuthorizationSequenceSplashController?) -> AuthorizationSequencePhoneEntryController {
var currentController: AuthorizationSequencePhoneEntryController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequencePhoneEntryController {
@ -156,6 +156,9 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .empty)).start()
}
})
if let splahController = splashController {
controller.animateWithSplashController(splahController)
}
controller.accountUpdated = { [weak self] updatedAccount in
guard let strongSelf = self else {
return
@ -393,35 +396,39 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
let _ = beginSignUp(account: strongSelf.account, data: data).start()
}
case .loggedIn:
break
controller?.animateSuccess()
}
}, error: { error in
Queue.mainQueue().async {
if let strongSelf = self, let controller = controller {
controller.inProgress = false
var resetCode = false
let text: String
switch error {
case .limitExceeded:
resetCode = true
text = strongSelf.presentationData.strings.Login_CodeFloodError
case .invalidCode:
resetCode = true
text = strongSelf.presentationData.strings.Login_InvalidCodeError
case .generic:
text = strongSelf.presentationData.strings.Login_UnknownError
case .codeExpired:
text = strongSelf.presentationData.strings.Login_CodeExpired
let account = strongSelf.account
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).start()
if case .invalidCode = error {
controller.animateError(text: strongSelf.presentationData.strings.Login_WrongCodeError)
} else {
var resetCode = false
let text: String
switch error {
case .limitExceeded:
resetCode = true
text = strongSelf.presentationData.strings.Login_CodeFloodError
case .invalidCode:
resetCode = true
text = strongSelf.presentationData.strings.Login_InvalidCodeError
case .generic:
text = strongSelf.presentationData.strings.Login_UnknownError
case .codeExpired:
text = strongSelf.presentationData.strings.Login_CodeExpired
let account = strongSelf.account
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).start()
}
if resetCode {
controller.resetCode()
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
if resetCode {
controller.resetCode()
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
}
}))
@ -985,7 +992,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
if self.otherAccountPhoneNumbers.1.isEmpty {
controllers.append(self.splashController())
} else {
controllers.append(self.phoneEntryController(countryCode: defaultCountryCode(), number: ""))
controllers.append(self.phoneEntryController(countryCode: defaultCountryCode(), number: "", splashController: nil))
}
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
}
@ -994,14 +1001,21 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
if !self.otherAccountPhoneNumbers.1.isEmpty {
controllers.append(self.splashController())
}
controllers.append(self.phoneEntryController(countryCode: countryCode, number: number))
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
var previousSplashController: AuthorizationSequenceSplashController?
for c in self.viewControllers {
if let c = c as? AuthorizationSequenceSplashController {
previousSplashController = c
break
}
}
controllers.append(self.phoneEntryController(countryCode: countryCode, number: number, splashController: previousSplashController))
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty && (previousSplashController == nil || self.viewControllers.count > 2))
case let .confirmationCodeEntry(number, type, _, timeout, nextType, _):
var controllers: [ViewController] = []
if !self.otherAccountPhoneNumbers.1.isEmpty {
controllers.append(self.splashController())
}
controllers.append(self.phoneEntryController(countryCode: defaultCountryCode(), number: ""))
controllers.append(self.phoneEntryController(countryCode: defaultCountryCode(), number: "", splashController: nil))
if case let .emailSetupRequired(appleSignInAllowed) = type {
controllers.append(self.emailSetupController(number: number, appleSignInAllowed: appleSignInAllowed))
} else {

View File

@ -17,7 +17,7 @@ final class AuthorizationDividerNode: ASDisplayNode {
init(theme: PresentationTheme, strings: PresentationStrings) {
self.titleNode = ImmediateTextNode()
self.titleNode.maximumNumberOfLines = 1
self.titleNode.attributedText = NSAttributedString(string: "or", font: Font.regular(17.0), textColor: theme.list.itemSecondaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: strings.Login_Or, font: Font.regular(17.0), textColor: theme.list.itemSecondaryTextColor)
self.leftLineNode = ASDisplayNode()
self.leftLineNode.backgroundColor = theme.list.itemSecondaryTextColor
@ -90,20 +90,20 @@ final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UIText
self.titleNode = ASTextNode()
self.titleNode.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = false
self.titleNode.attributedText = NSAttributedString(string: "Add Email", font: Font.light(30.0), textColor: self.theme.list.itemPrimaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_AddEmailTitle, font: Font.light(30.0), textColor: self.theme.list.itemPrimaryTextColor)
self.noticeNode = ASTextNode()
self.noticeNode.isUserInteractionEnabled = false
self.noticeNode.displaysAsynchronously = false
self.noticeNode.lineSpacing = 0.1
self.noticeNode.attributedText = NSAttributedString(string: "Please enter your valid email address to protect your account.", font: Font.regular(16.0), textColor: self.theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
self.noticeNode.attributedText = NSAttributedString(string: self.strings.Login_AddEmailText, font: Font.regular(16.0), textColor: self.theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
if #available(iOS 13.0, *) {
self.signInWithAppleButton = ASAuthorizationAppleIDButton(authorizationButtonType: .signIn, authorizationButtonStyle: theme.overallDarkAppearance ? .white : .black)
(self.signInWithAppleButton as? ASAuthorizationAppleIDButton)?.cornerRadius = 11
}
self.proceedNode = SolidRoundedButtonNode(title: "Continue", theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
self.proceedNode = SolidRoundedButtonNode(title: self.strings.Login_Continue, theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
self.codeSeparatorNode = ASDisplayNode()
self.codeSeparatorNode.isLayerBacked = true
@ -120,7 +120,7 @@ final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UIText
self.codeField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
self.codeField.textField.tintColor = self.theme.list.itemAccentColor
self.codeField.textField.placeholder = "Enter Your Email"
self.codeField.textField.placeholder = self.strings.Login_AddEmailPlaceholder
self.dividerNode = AuthorizationDividerNode(theme: self.theme, strings: self.strings)
@ -193,9 +193,9 @@ final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UIText
insets.bottom += max(inputHeight, insets.bottom)
}
self.titleNode.attributedText = NSAttributedString(string: "Add Email", font: Font.bold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_AddEmailTitle, font: Font.bold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
let animationSize = CGSize(width: 88.0, height: 88.0)
let animationSize = CGSize(width: 100.0, height: 100.0)
let titleSize = self.titleNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let noticeSize = self.noticeNode.measure(CGSize(width: layout.size.width - 80.0, height: CGFloat.greatestFiniteMagnitude))

View File

@ -97,6 +97,17 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
}
}
private var shouldAnimateIn = false
private var transitionInArguments: (buttonFrame: CGRect, animationSnapshot: UIView, textSnapshot: UIView)?
func animateWithSplashController(_ controller: AuthorizationSequenceSplashController) {
self.shouldAnimateIn = true
if let animationSnapshot = controller.animationSnapshot, let textSnapshot = controller.textSnaphot {
self.transitionInArguments = (controller.buttonFrame, animationSnapshot, textSnapshot)
}
}
override public func loadDisplayNode() {
self.displayNode = AuthorizationSequencePhoneEntryControllerNode(sharedContext: self.sharedContext, account: self.account, strings: self.presentationData.strings, theme: self.presentationData.theme, debugAction: { [weak self] in
guard let strongSelf = self else {
@ -146,22 +157,42 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
})
}
private var animatingIn = false
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.controllerNode.activateInput()
if self.shouldAnimateIn {
self.animatingIn = true
if let (buttonFrame, animationSnapshot, textSnapshot) = self.transitionInArguments {
self.controllerNode.willAnimateIn(buttonFrame: buttonFrame, animationSnapshot: animationSnapshot, textSnapshot: textSnapshot)
}
Queue.mainQueue().justDispatch {
self.controllerNode.activateInput()
}
} else {
self.controllerNode.activateInput()
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.controllerNode.activateInput()
if !self.animatingIn {
self.controllerNode.activateInput()
}
}
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
if self.shouldAnimateIn, let inputHeight = layout.inputHeight, inputHeight > 0.0 {
if let (buttonFrame, animationSnapshot, textSnapshot) = self.transitionInArguments {
self.shouldAnimateIn = false
self.controllerNode.animateIn(buttonFrame: buttonFrame, animationSnapshot: animationSnapshot, textSnapshot: textSnapshot)
}
}
}
@objc func nextPressed() {

View File

@ -154,12 +154,18 @@ private final class PhoneAndCountryNode: ASDisplayNode {
let flagString = emojiFlagForISOCountryCode(name)
let localizedName: String = AuthorizationSequenceCountrySelectionController.lookupCountryNameById(name, strings: strongSelf.strings) ?? countryName
strongSelf.countryButton.setTitle("\(flagString) \(localizedName)", with: Font.regular(20.0), with: theme.list.itemAccentColor, for: [])
strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_PhonePlaceholder, font: Font.regular(20.0), textColor: theme.list.itemPlaceholderTextColor)
if strongSelf.phoneInputNode.mask == nil {
strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_PhonePlaceholder, font: Font.regular(20.0), textColor: theme.list.itemPlaceholderTextColor)
}
} else if let code = Int(code), let (countryId, countryName) = countryCodeToIdAndName[code] {
let flagString = emojiFlagForISOCountryCode(countryId)
let localizedName: String = AuthorizationSequenceCountrySelectionController.lookupCountryNameById(countryId, strings: strongSelf.strings) ?? countryName
strongSelf.countryButton.setTitle("\(flagString) \(localizedName)", with: Font.regular(20.0), with: theme.list.itemAccentColor, for: [])
strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_PhonePlaceholder, font: Font.regular(20.0), textColor: theme.list.itemPlaceholderTextColor)
if strongSelf.phoneInputNode.mask == nil {
strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_PhonePlaceholder, font: Font.regular(20.0), textColor: theme.list.itemPlaceholderTextColor)
}
} else {
strongSelf.countryButton.setTitle(strings.Login_SelectCountry, with: Font.regular(20.0), with: theme.list.itemAccentColor, for: [])
strongSelf.phoneInputNode.mask = nil
@ -330,7 +336,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
self.phoneAndCountryNode = PhoneAndCountryNode(strings: strings, theme: theme)
self.proceedNode = SolidRoundedButtonNode(title: "Continue", theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
self.proceedNode = SolidRoundedButtonNode(title: self.strings.Login_Continue, theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
self.proceedNode.progressType = .embedded
super.init()
@ -380,6 +386,64 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
#endif
}
private var animationSnapshotView: UIView?
private var textSnapshotView: UIView?
private var forcedButtonFrame: CGRect?
func willAnimateIn(buttonFrame: CGRect, animationSnapshot: UIView, textSnapshot: UIView) {
self.proceedNode.frame = buttonFrame
self.proceedNode.title = "Start Messaging"
self.animationSnapshotView = animationSnapshot
self.view.insertSubview(animationSnapshot, at: 0)
self.textSnapshotView = textSnapshot
self.view.insertSubview(textSnapshot, at: 0)
let nodes: [ASDisplayNode] = [
self.animationNode,
self.titleNode,
self.noticeNode,
self.phoneAndCountryNode,
self.contactSyncNode
]
for node in nodes {
node.alpha = 0.0
}
}
func animateIn(buttonFrame: CGRect, animationSnapshot: UIView, textSnapshot: UIView) {
self.proceedNode.animateTitle(to: self.strings.Login_Continue)
let duration: Double = 0.3
self.animationSnapshotView?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak self] _ in
self?.animationSnapshotView?.removeFromSuperview()
self?.animationSnapshotView = nil
})
self.animationSnapshotView?.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -100.0), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
self.textSnapshotView?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak self] _ in
self?.textSnapshotView?.removeFromSuperview()
self?.textSnapshotView = nil
})
self.textSnapshotView?.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -140.0), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
let nodes: [ASDisplayNode] = [
self.animationNode,
self.titleNode,
self.noticeNode,
self.phoneAndCountryNode,
self.contactSyncNode
]
for node in nodes {
node.alpha = 1.0
node.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
}
}
func updateCountryCode() {
self.phoneAndCountryNode.phoneInputNode.codeAndNumber = self.codeAndNumber
}
@ -396,7 +460,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
let inset: CGFloat = 24.0
let animationSize = CGSize(width: 88.0, height: 88.0)
let animationSize = CGSize(width: 100.0, height: 100.0)
let titleSize = self.titleNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let noticeSize = self.noticeNode.measure(CGSize(width: min(274.0, layout.size.width - 28.0), height: CGFloat.greatestFiniteMagnitude))
let proceedHeight = self.proceedNode.updateLayout(width: layout.size.width - inset * 2.0, transition: transition)
@ -411,12 +475,19 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
let contactSyncSize = self.contactSyncNode.updateLayout(width: layout.size.width)
if self.hasOtherAccounts {
self.contactSyncNode.isHidden = false
items.append(AuthorizationLayoutItem(node: self.contactSyncNode, size: contactSyncSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 16.0, maxValue: 16.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.contactSyncNode, size: contactSyncSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 14.0, maxValue: 14.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
} else {
self.contactSyncNode.isHidden = true
}
transition.updateFrame(node: self.proceedNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - proceedSize.width) / 2.0), y: layout.size.height - insets.bottom - proceedSize.height - inset), size: proceedSize))
let buttonFrame: CGRect
if let forcedButtonFrame = self.forcedButtonFrame, (layout.inputHeight ?? 0.0).isZero {
buttonFrame = forcedButtonFrame
} else {
buttonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - proceedSize.width) / 2.0), y: layout.size.height - insets.bottom - proceedSize.height - inset), size: proceedSize)
}
transition.updateFrame(node: self.proceedNode, frame: buttonFrame)
self.animationNode.updateLayout(size: animationSize)

View File

@ -141,7 +141,7 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
self.addPhotoButton.addSubnode(self.currentPhotoNode)
self.addPhotoButton.allowsGroupOpacity = true
self.proceedNode = SolidRoundedButtonNode(title: "Continue", theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
self.proceedNode = SolidRoundedButtonNode(title: self.strings.Login_Continue, theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
super.init()

View File

@ -7,7 +7,7 @@ import TelegramCore
import SwiftSignalKit
import TelegramPresentationData
import LegacyComponents
import SolidRoundedButtonNode
import RMIntro
final class AuthorizationSequenceSplashController: ViewController {
@ -28,6 +28,8 @@ final class AuthorizationSequenceSplashController: ViewController {
private let suggestedLocalization = Promise<SuggestedLocalizationInfo?>()
private let activateLocalizationDisposable = MetaDisposable()
private let startButton: SolidRoundedButtonNode
init(accountManager: AccountManager<TelegramAccountManagerTypes>, account: UnauthorizedAccount, theme: PresentationTheme) {
self.accountManager = accountManager
self.account = account
@ -68,7 +70,9 @@ final class AuthorizationSequenceSplashController: ViewController {
})
})
self.controller = RMIntroViewController(backgroundColor: theme.list.plainBackgroundColor, primaryColor: theme.list.itemPrimaryTextColor, buttonColor: theme.intro.startButtonColor, accentColor: theme.list.itemAccentColor, regularDotColor: theme.intro.dotColor, highlightedDotColor: theme.list.itemPrimaryTextColor, suggestedLocalizationSignal: localizationSignal)
self.controller = RMIntroViewController(backgroundColor: theme.list.plainBackgroundColor, primaryColor: theme.list.itemPrimaryTextColor, buttonColor: theme.intro.startButtonColor, accentColor: theme.list.itemAccentColor, regularDotColor: theme.intro.dotColor, highlightedDotColor: theme.list.itemAccentColor, suggestedLocalizationSignal: localizationSignal)
self.startButton = SolidRoundedButtonNode(title: "Start Messaging", theme: SolidRoundedButtonTheme(theme: theme), height: 50.0, cornerRadius: 13.0, gloss: true)
super.init(navigationBarPresentationData: nil)
@ -84,6 +88,15 @@ final class AuthorizationSequenceSplashController: ViewController {
self?.activateLocalization(code)
}
}
self.startButton.pressed = { [weak self] in
self?.activateLocalization("en")
}
self.controller.createStartButton = { [weak self] width in
let _ = self?.startButton.updateLayout(width: width, transition: .immediate)
return self?.startButton.view
}
}
required init(coder aDecoder: NSCoder) {
@ -99,20 +112,32 @@ final class AuthorizationSequenceSplashController: ViewController {
self.displayNodeDidLoad()
}
var buttonFrame: CGRect {
return self.startButton.frame
}
var animationSnapshot: UIView? {
return self.controller.createAnimationSnapshot()
}
var textSnaphot: UIView? {
return self.controller.createTextSnapshot()
}
private func addControllerIfNeeded() {
if !controller.isViewLoaded || controller.view.superview == nil {
self.displayNode.view.addSubview(controller.view)
if !self.controller.isViewLoaded || self.controller.view.superview == nil {
self.displayNode.view.addSubview(self.controller.view)
if let layout = self.validLayout {
controller.view.frame = CGRect(origin: CGPoint(), size: layout.size)
}
controller.viewDidAppear(false)
self.controller.viewDidAppear(false)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.addControllerIfNeeded()
controller.viewWillAppear(false)
self.controller.viewWillAppear(false)
}
override func viewDidAppear(_ animated: Bool) {
@ -182,6 +207,7 @@ final class AuthorizationSequenceSplashController: ViewController {
}
strongSelf.controller.isEnabled = false
strongSelf.startButton.alpha = 0.6
let accountManager = strongSelf.accountManager
strongSelf.activateLocalizationDisposable.set(TelegramEngineUnauthorized(account: strongSelf.account).localization.downloadAndApplyLocalization(accountManager: accountManager, languageCode: code).start(completed: {
@ -202,6 +228,7 @@ final class AuthorizationSequenceSplashController: ViewController {
}
|> deliverOnMainQueue).start(next: { strings in
self?.controller.isEnabled = true
self?.startButton.alpha = 1.0
self?.pressNext(strings: strings)
})
}))