Update API

This commit is contained in:
Ilya Laktyushin
2024-04-15 16:39:53 +04:00
parent 78b0c5f509
commit 231d8f0808
21 changed files with 1379 additions and 1050 deletions

View File

@@ -220,7 +220,7 @@ public final class AuthorizationSequenceCodeEntryController: ViewController {
minimalCodeLength = Int(length)
case let .firebase(_, length):
minimalCodeLength = Int(length)
case .flashCall, .emailSetupRequired:
case .flashCall, .emailSetupRequired, .word, .phrase:
break
}

View File

@@ -39,6 +39,9 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
private var signInWithAppleButton: UIControl?
private let proceedNode: SolidRoundedButtonNode
private let textField: TextFieldNode
private let textSeparatorNode: ASDisplayNode
private let codeInputView: CodeInputView
private let errorTextNode: ImmediateTextNode
@@ -64,7 +67,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
var email: String?
var currentCode: String {
return self.codeInputView.text
switch self.codeType {
case .word, .phrase:
return self.textField.textField.text ?? ""
default:
return self.codeInputView.text
}
}
var loginWithCode: ((String) -> Void)?
@@ -81,6 +89,19 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
var inProgress: Bool = false {
didSet {
self.codeInputView.alpha = self.inProgress ? 0.6 : 1.0
switch self.codeType {
case .word, .phrase:
if self.inProgress != oldValue {
if self.inProgress {
self.proceedNode.transitionToProgress()
} else {
self.proceedNode.transitionFromProgress()
}
}
default:
break
}
}
}
@@ -151,6 +172,28 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.codeInputView.textField.keyboardType = .numberPad
}
self.textSeparatorNode = ASDisplayNode()
self.textSeparatorNode.isLayerBacked = true
self.textSeparatorNode.backgroundColor = self.theme.list.itemPlainSeparatorColor
self.textField = TextFieldNode()
self.textField.textField.font = Font.regular(20.0)
self.textField.textField.textColor = self.theme.list.itemPrimaryTextColor
self.textField.textField.textAlignment = .natural
self.textField.textField.autocorrectionType = .yes
self.textField.textField.autocorrectionType = .no
self.textField.textField.spellCheckingType = .yes
self.textField.textField.spellCheckingType = .no
self.textField.textField.autocapitalizationType = .none
self.textField.textField.keyboardType = .default
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.textField.textField.textContentType = UITextContentType(rawValue: "")
}
self.textField.textField.returnKeyType = .default
self.textField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.textField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
self.textField.textField.tintColor = self.theme.list.itemAccentColor
self.errorTextNode = ImmediateTextNode()
self.errorTextNode.alpha = 0.0
self.errorTextNode.displaysAsynchronously = false
@@ -175,11 +218,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.signInWithAppleButton?.isHidden = true
(self.signInWithAppleButton as? ASAuthorizationAppleIDButton)?.cornerRadius = 11
}
self.proceedNode = SolidRoundedButtonNode(title: self.strings.Login_OpenFragment, theme: SolidRoundedButtonTheme(backgroundColor: UIColor(rgb: 0x37475a), foregroundColor: .white), 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
self.proceedNode.isHidden = true
self.proceedNode.iconSpacing = 4.0
self.proceedNode.animationSize = CGSize(width: 36.0, height: 36.0)
self.proceedNode.isEnabled = false
super.init()
@@ -189,7 +233,11 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.backgroundColor = self.theme.list.plainBackgroundColor
self.textField.textField.delegate = self
self.addSubnode(self.codeInputView)
self.addSubnode(self.textSeparatorNode)
self.addSubnode(self.textField)
self.addSubnode(self.titleNode)
self.addSubnode(self.titleActivateAreaNode)
self.addSubnode(self.titleIconNode)
@@ -208,9 +256,11 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
guard let strongSelf = self else {
return
}
strongSelf.textChanged(text: strongSelf.codeInputView.text)
strongSelf.codeChanged(text: strongSelf.codeInputView.text)
}
self.textField.textField.addTarget(self, action: #selector(self.textDidChange), for: .editingChanged)
self.codeInputView.longPressed = { [weak self] in
guard let strongSelf = self else {
return
@@ -261,7 +311,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
func updateCode(_ code: String) {
self.codeInputView.text = code
self.textChanged(text: code)
self.codeChanged(text: code)
if let codeLength = self.requiredCodeLength, code.count == Int(codeLength) {
self.loginWithCode?(code)
@@ -401,6 +451,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
var animationName = "IntroMessage"
var animationPlaybackMode: AnimatedStickerPlaybackMode = .once
var textFieldPlaceholder = ""
if let codeType = self.codeType {
switch codeType {
case .missedCall:
@@ -412,9 +463,20 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeSMSTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
case .fragment:
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeFragmentTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
self.proceedNode.title = self.strings.Login_OpenFragment
self.proceedNode.updateTheme(SolidRoundedButtonTheme(backgroundColor: UIColor(rgb: 0x37475a), foregroundColor: .white))
self.proceedNode.isEnabled = true
animationName = "IntroFragment"
animationPlaybackMode = .count(3)
self.proceedNode.animation = "anim_fragment"
case .word:
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterWordTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
textFieldPlaceholder = self.strings.Login_EnterWordPlaceholder
case .phrase:
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterPhraseTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
textFieldPlaceholder = self.strings.Login_EnterPhrasePlaceholder
default:
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeTelegramTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
}
@@ -422,14 +484,17 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeTelegramTitle, font: Font.semibold(40.0), textColor: self.theme.list.itemPrimaryTextColor)
}
self.textField.textField.placeholder = textFieldPlaceholder
self.titleActivateAreaNode.accessibilityLabel = self.titleNode.attributedText?.string ?? ""
if let inputHeight = layout.inputHeight {
if let codeType = self.codeType, case .email = codeType {
switch self.codeType {
case .email, .fragment:
insets.bottom = max(inputHeight, insets.bottom)
} else if let codeType = self.codeType, case .fragment = codeType {
insets.bottom = max(inputHeight, insets.bottom)
} else {
case .word, .phrase:
insets.bottom = max(inputHeight, layout.standardKeyboardHeight)
default:
insets.bottom = max(inputHeight, layout.standardInputHeight)
}
}
@@ -475,6 +540,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
codeLength = Int(length)
case .emailSetupRequired:
codeLength = 6
case .word, .phrase:
codeLength = 0
case .none:
codeLength = 6
}
@@ -498,8 +565,11 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
if layout.size.width > 320.0 {
items.append(AuthorizationLayoutItem(node: self.animationNode, size: animationSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 10.0, maxValue: 10.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
self.animationNode.updateLayout(size: animationSize)
self.animationNode.isHidden = false
self.animationNode.visibility = true
} else {
insets.top = navigationBarHeight
self.animationNode.isHidden = true
}
var additionalBottomInset: CGFloat = 20.0
@@ -550,7 +620,19 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
}
}
items.append(AuthorizationLayoutItem(node: self.codeInputView, size: codeFieldSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 30.0, maxValue: 30.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: canReset || pendingDate != nil ? 0.0 : 104.0, maxValue: canReset ? 0.0 : 104.0)))
switch codeType {
case .word, .phrase:
self.codeInputView.isHidden = true
self.textField.isHidden = false
self.textSeparatorNode.isHidden = false
items.append(AuthorizationLayoutItem(node: self.textField, size: CGSize(width: maximumWidth - 88.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 18.0, maxValue: 30.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.textSeparatorNode, size: CGSize(width: maximumWidth - 48.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
default:
self.codeInputView.isHidden = false
self.textField.isHidden = true
self.textSeparatorNode.isHidden = true
items.append(AuthorizationLayoutItem(node: self.codeInputView, size: codeFieldSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 30.0, maxValue: 30.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: canReset || pendingDate != nil ? 0.0 : 104.0, maxValue: canReset ? 0.0 : 104.0)))
}
if canReset {
self.resetNode.setAttributedTitle(NSAttributedString(string: self.strings.Login_Email_CantAccess, font: Font.regular(17.0), textColor: self.theme.list.itemAccentColor, paragraphAlignment: .center), for: [])
@@ -614,7 +696,29 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
} else {
self.signInWithAppleButton?.isHidden = true
self.dividerNode.isHidden = true
self.proceedNode.isHidden = true
switch codeType {
case .word, .phrase:
additionalBottomInset = 120.0
self.nextOptionButtonNode.isHidden = false
items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
if layout.size.width > 320.0 {
self.proceedNode.isHidden = false
} else {
self.proceedNode.isHidden = true
}
let 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)
case .email:
self.nextOptionButtonNode.isHidden = true
self.proceedNode.isHidden = true
default:
self.nextOptionButtonNode.isHidden = false
self.proceedNode.isHidden = true
items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
}
if case .email = codeType {
self.nextOptionButtonNode.isHidden = true
@@ -644,31 +748,58 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
}
func activateInput() {
let _ = self.codeInputView.becomeFirstResponder()
switch self.codeType {
case .word, .phrase:
self.textField.textField.becomeFirstResponder()
default:
let _ = self.codeInputView.becomeFirstResponder()
}
}
func animateError() {
self.codeInputView.layer.addShakeAnimation()
switch self.codeType {
case .word, .phrase:
self.textField.layer.addShakeAnimation()
default:
self.codeInputView.layer.addShakeAnimation()
}
}
func animateError(text: String) {
self.codeInputView.animateError()
self.codeInputView.layer.addShakeAnimation(amplitude: -30.0, duration: 0.5, count: 6, decay: true)
let errorOriginY: CGFloat
let errorOriginOffset: CGFloat
switch self.codeType {
case .word, .phrase:
self.textField.layer.addShakeAnimation()
let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .easeInOut)
transition.updateBackgroundColor(node: self.textSeparatorNode, color: self.theme.list.itemDestructiveColor)
errorOriginY = self.textField.frame.maxY
errorOriginOffset = 5.0
default:
self.codeInputView.animateError()
self.codeInputView.layer.addShakeAnimation(amplitude: -30.0, duration: 0.5, count: 6, decay: true)
errorOriginY = self.codeInputView.frame.maxY
errorOriginOffset = 11.0
}
self.errorTextNode.attributedText = NSAttributedString(string: text, font: Font.regular(17.0), textColor: self.theme.list.itemDestructiveColor, paragraphAlignment: .center)
self.errorTextNode.attributedText = NSAttributedString(string: text, font: Font.regular(13.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))
let yOffset: CGFloat = layout.size.width > 320.0 ? 28.0 : 15.0
self.errorTextNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - errorTextSize.width) / 2.0), y: self.codeInputView.frame.maxY + yOffset), size: errorTextSize)
let yOffset: CGFloat = layout.size.width > 320.0 ? errorOriginOffset + 13.0 : errorOriginOffset
self.errorTextNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - errorTextSize.width) / 2.0), y: errorOriginY + yOffset), 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) {
Queue.mainQueue().after(1.6) {
self.errorTextNode.alpha = 0.0
self.errorTextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15)
let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .easeInOut)
transition.updateBackgroundColor(node: self.textSeparatorNode, color: self.theme.list.itemPlainSeparatorColor)
}
}
@@ -678,12 +809,14 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
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) {
self.textChanged(text: textField.text ?? "")
@objc private func textDidChange() {
let text = self.textField.textField.text ?? ""
self.proceedNode.isEnabled = !text.isEmpty
self.updateNextEnabled?(!text.isEmpty)
}
private func textChanged(text: String) {
private func codeChanged(text: String) {
self.updateNextEnabled?(!text.isEmpty)
if let codeType = self.codeType {
var codeLength: Int32?
@@ -715,20 +848,36 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
if self.inProgress {
return false
}
var result = ""
for c in string {
if c.unicodeScalars.count == 1 {
let scalar = c.unicodeScalars.first!
if scalar >= "0" && scalar <= "9" {
result.append(c)
var updated = textField.text ?? ""
updated.replaceSubrange(updated.index(updated.startIndex, offsetBy: range.lowerBound) ..< updated.index(updated.startIndex, offsetBy: range.upperBound), with: string)
if let codeType = self.codeType {
switch codeType {
case let .word(startsWith):
if let startsWith, startsWith.count == 1, !updated.isEmpty && !updated.hasPrefix(startsWith) {
if self.errorTextNode.alpha.isZero {
//TODO:localize
self.animateError(text: "Incorrect, please try again")
}
return false
}
case let .phrase(startsWith):
if let startsWith, !updated.isEmpty {
let firstWord = updated.components(separatedBy: " ").first ?? ""
if !firstWord.isEmpty && !startsWith.hasPrefix(firstWord) {
if self.errorTextNode.alpha.isZero {
//TODO:localize
self.animateError(text: "Incorrect, please try again")
}
return false
}
}
default:
break
}
}
if result != string {
textField.text = result
self.codeFieldTextChanged(textField)
return false
}
return true
}
@@ -737,8 +886,15 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
}
@objc func proceedPressed() {
if case let .fragment(url, _) = self.codeType {
switch self.codeType {
case let .fragment(url, _):
self.openFragment?(url)
case .word, .phrase:
if let text = self.textField.textField.text, !text.isEmpty {
self.loginWithCode?(text)
}
default:
break
}
}

View File

@@ -54,6 +54,10 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
private var didSetReady = false
fileprivate var engine: TelegramEngineUnauthorized {
return TelegramEngineUnauthorized(account: self.account)
}
public init(sharedContext: SharedAccountContext, account: UnauthorizedAccount, otherAccountPhoneNumbers: ((String, AccountRecordId, Bool)?, [(String, AccountRecordId, Bool)]), presentationData: PresentationData, openUrl: @escaping (String) -> Void, apiId: Int32, apiHash: String, authorizationCompleted: @escaping () -> Void) {
self.sharedContext = sharedContext
self.account = account
@@ -74,7 +78,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
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()
self.stateDisposable = (self.engine.auth.state()
|> map { state -> InnerState in
if case .authorized = state {
return .authorized
@@ -127,7 +131,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
let countryCode = AuthorizationSequenceController.defaultCountryCode()
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: isTestingEnvironment, masterDatacenterId: masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: isTestingEnvironment, masterDatacenterId: masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
}
}
}
@@ -157,7 +161,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
transaction.removeAuth()
}).startStandalone()
} else {
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .empty)).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .empty)).startStandalone()
}
})
if let splashController = splashController {
@@ -299,9 +303,6 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
if c.data?.2 == type {
currentController = c
}
// else if case let .email(_, _, _, newPendingDate, _, _) = type, let previousType = c.data?.2, case let .email(_, _, _, previousPendingDate, _, _) = previousType, newPendingDate != nil && previousPendingDate == nil {
// currentController = c
// }
break
}
}
@@ -315,7 +316,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
let countryCode = AuthorizationSequenceController.defaultCountryCode()
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
})
controller.retryResetEmail = { [weak self] in
if let self {
@@ -381,7 +382,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
case .codeExpired:
text = self.presentationData.strings.Login_CodeExpired
let account = self.account
let _ = TelegramEngineUnauthorized(account: self.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
let _ = self.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
}
controller.presentInGlobalOverlay(standardTextAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: {})]))
@@ -430,7 +431,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
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)).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
case .timeout:
text = strongSelf.presentationData.strings.Login_NetworkError
case .invalidEmailToken:
@@ -490,7 +491,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
return
}
let account = strongSelf.account
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
})]), on: .root, blockInteraction: false, completion: {})
})
], actionLayout: .vertical, dismissOnOutsideTap: true)
@@ -522,7 +523,14 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
controller.inProgress = false
if case .invalidCode = error {
controller.animateError(text: strongSelf.presentationData.strings.Login_WrongCodeError)
let text: String
switch type {
case .word, .phrase:
text = strongSelf.presentationData.strings.Login_WrongPhraseError
default:
text = strongSelf.presentationData.strings.Login_WrongCodeError
}
controller.animateError(text: text)
} else {
var resetCode = false
let text: String
@@ -538,7 +546,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
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)).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
case .invalidEmailToken:
text = strongSelf.presentationData.strings.Login_InvalidEmailTokenError
case .invalidEmailAddress:
@@ -562,7 +570,11 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
if let strongSelf = self {
if nextType == nil {
if let controller {
AuthorizationSequenceController.presentDidNotGetCodeUI(controller: controller, presentationData: strongSelf.presentationData, number: number)
let carrier = CTCarrier()
let mnc = carrier.mobileNetworkCode ?? "none"
let _ = strongSelf.engine.auth.reportMissingCode(phoneNumber: number, phoneCodeHash: phoneCodeHash, mnc: mnc).start()
AuthorizationSequenceController.presentDidNotGetCodeUI(controller: controller, presentationData: strongSelf.presentationData, phoneNumber: number, mnc: mnc)
}
} else {
controller?.inProgress = true
@@ -607,7 +619,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
controller.reset = { [weak self] in
if let strongSelf = self {
let account = strongSelf.account
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
}
}
controller.signInWithApple = { [weak self] in
@@ -659,7 +671,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
let countryCode = AuthorizationSequenceController.defaultCountryCode()
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
})
}
controller.proceedWithEmail = { [weak self, weak controller] email in
@@ -783,7 +795,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
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)).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
case .invalidEmailToken:
text = strongSelf.presentationData.strings.Login_InvalidEmailTokenError
case .invalidEmailAddress:
@@ -832,7 +844,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
let countryCode = AuthorizationSequenceController.defaultCountryCode()
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
})
controller.loginWithPassword = { [weak self, weak controller] password in
if let strongSelf = self {
@@ -864,19 +876,19 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
controller.forgot = { [weak self, weak controller] in
if let strongSelf = self, let strongController = controller {
strongController.inProgress = true
strongSelf.actionDisposable.set((TelegramEngineUnauthorized(account: strongSelf.account).auth.requestTwoStepVerificationPasswordRecoveryCode()
strongSelf.actionDisposable.set((strongSelf.engine.auth.requestTwoStepVerificationPasswordRecoveryCode()
|> deliverOnMainQueue).startStrict(next: { pattern in
if let strongSelf = self, let strongController = controller {
strongController.inProgress = false
let _ = (TelegramEngineUnauthorized(account: strongSelf.account).auth.state()
let _ = (strongSelf.engine.auth.state()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { state in
guard let strongSelf = self else {
return
}
if case let .unauthorized(state) = state, case let .passwordEntry(hint, number, code, _, syncContacts) = state.contents {
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordRecovery(hint: hint, number: number, code: code, emailPattern: pattern, syncContacts: syncContacts))).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordRecovery(hint: hint, number: number, code: code, emailPattern: pattern, syncContacts: syncContacts))).startStandalone()
}
})
}
@@ -937,7 +949,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
if let currentController = currentController {
controller = currentController
} else {
controller = TwoFactorDataInputScreen(sharedContext: self.sharedContext, engine: .unauthorized(TelegramEngineUnauthorized(account: self.account)), mode: .passwordRecoveryEmail(emailPattern: emailPattern, mode: .notAuthorized(syncContacts: syncContacts), doneText: self.presentationData.strings.TwoFactorSetup_Done_Action), stateUpdated: { _ in
controller = TwoFactorDataInputScreen(sharedContext: self.sharedContext, engine: .unauthorized(self.engine), mode: .passwordRecoveryEmail(emailPattern: emailPattern, mode: .notAuthorized(syncContacts: syncContacts), doneText: self.presentationData.strings.TwoFactorSetup_Done_Action), stateUpdated: { _ in
}, presentation: .default)
}
controller.passwordRecoveryFailed = { [weak self] in
@@ -945,14 +957,14 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
return
}
let _ = (TelegramEngineUnauthorized(account: strongSelf.account).auth.state()
let _ = (strongSelf.engine.auth.state()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { state in
guard let strongSelf = self else {
return
}
if case let .unauthorized(state) = state, case let .passwordRecovery(hint, number, code, _, syncContacts) = state.contents {
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code, suggestReset: true, syncContacts: syncContacts))).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code, suggestReset: true, syncContacts: syncContacts))).startStandalone()
}
})
}
@@ -977,7 +989,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
let countryCode = AuthorizationSequenceController.defaultCountryCode()
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
})
controller.reset = { [weak self, weak controller] in
if let strongSelf = self, let strongController = controller {
@@ -1011,7 +1023,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
controller.logout = { [weak self] in
if let strongSelf = self {
let account = strongSelf.account
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).startStandalone()
}
}
}
@@ -1037,7 +1049,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
let countryCode = AuthorizationSequenceController.defaultCountryCode()
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
let _ = strongSelf.engine.auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).startStandalone()
}, displayCancel: displayCancel)
controller.openUrl = { [weak self] url in
guard let self else {
@@ -1056,7 +1068,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
let avatarVideo: Signal<UploadedPeerPhotoData?, NoError>?
if let avatarAsset = avatarAsset as? AVAsset {
let account = strongSelf.account
let engine = strongSelf.engine
avatarVideo = Signal<TelegramMediaResource?, NoError> { subscriber in
let entityRenderer: LegacyPaintEntityRenderer? = avatarAdjustments.flatMap { adjustments in
if let paintingData = adjustments.paintingData, paintingData.hasAnimation {
@@ -1075,7 +1087,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
if stat(result.fileURL.path, &value) == 0 {
if let data = try? Data(contentsOf: result.fileURL) {
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
engine.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
subscriber.putNext(resource)
EngineTempBox.shared.dispose(tempFile)
@@ -1096,7 +1108,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
|> mapToSignal { resource -> Signal<UploadedPeerPhotoData?, NoError> in
if let resource = resource {
return TelegramEngineUnauthorized(account: account).auth.uploadedPeerVideo(resource: resource) |> map(Optional.init)
return engine.auth.uploadedPeerVideo(resource: resource) |> map(Optional.init)
} else {
return .single(nil)
}
@@ -1320,9 +1332,14 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
return countryCode
}
public static func presentDidNotGetCodeUI(controller: ViewController, presentationData: PresentationData, number: String) {
public static func presentDidNotGetCodeUI(
controller: ViewController,
presentationData: PresentationData,
phoneNumber: String,
mnc: String
) {
if MFMailComposeViewController.canSendMail() {
let formattedNumber = formatPhoneNumber(number)
let formattedNumber = formatPhoneNumber(phoneNumber)
var emailBody = ""
emailBody.append(presentationData.strings.Login_EmailCodeBody(formattedNumber).string)
@@ -1331,8 +1348,6 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
let systemVersion = UIDevice.current.systemVersion
let locale = Locale.current.identifier
let carrier = CTCarrier()
let mnc = carrier.mobileNetworkCode ?? "none"
emailBody.append("Telegram: \(appVersion)\n")
emailBody.append("OS: \(systemVersion)\n")
emailBody.append("Locale: \(locale)\n")