Updated code input

This commit is contained in:
Ali 2021-11-24 00:42:18 +04:00
parent 313dca7e41
commit 42b5d07888
14 changed files with 683 additions and 140 deletions

View File

@ -144,7 +144,8 @@ public func layoutAuthorizationItems(bounds: CGRect, items: [AuthorizationLayout
} }
var verticalOrigin: CGFloat = bounds.minY + floor((bounds.size.height - totalHeight) / 2.0) var verticalOrigin: CGFloat = bounds.minY + floor((bounds.size.height - totalHeight) / 2.0)
for item in solvedItems { for i in 0 ..< solvedItems.count {
let item = solvedItems[i]
verticalOrigin += item.spacingBefore! verticalOrigin += item.spacingBefore!
transition.updateFrame(node: item.item.node, frame: CGRect(origin: CGPoint(x: floor((bounds.size.width - item.item.size.width) / 2.0), y: verticalOrigin), size: item.item.size)) transition.updateFrame(node: item.item.node, frame: CGRect(origin: CGPoint(x: floor((bounds.size.width - item.item.size.width) / 2.0), y: verticalOrigin), size: item.item.size))
verticalOrigin += item.item.size.height verticalOrigin += item.item.size.height

View File

@ -14,7 +14,11 @@ public func authorizationCurrentOptionText(_ type: SentAuthorizationCodeType, st
let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: primaryColor) let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: primaryColor)
let bold = MarkdownAttributeSet(font: Font.semibold(16.0), textColor: primaryColor) let bold = MarkdownAttributeSet(font: Font.semibold(16.0), textColor: primaryColor)
return parseMarkdownIntoAttributedString(strings.Login_CodeSentInternal, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center) return parseMarkdownIntoAttributedString(strings.Login_CodeSentInternal, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center)
case .call, .flashCall, .missedCall: case .missedCall:
let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: primaryColor)
let bold = MarkdownAttributeSet(font: Font.semibold(16.0), textColor: primaryColor)
return parseMarkdownIntoAttributedString("Within a few seconds you should\nreceive a short call from:", attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center)
case .call, .flashCall:
return NSAttributedString(string: strings.ChangePhoneNumberCode_Called, font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center) return NSAttributedString(string: strings.ChangePhoneNumberCode_Called, font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center)
} }
} }

View File

@ -909,7 +909,7 @@ private final class MonthComponent: CombinedComponent {
if case .none = transition.animation { if case .none = transition.animation {
return return
} }
let delay = Double(delayIndex) * 0.1 let delay = Double(min(delayIndex, 6)) * 0.1
view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.05, delay: delay) view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.05, delay: delay)
view.layer.animateFrame(from: CGRect(origin: view.frame.origin, size: CGSize(width: leftRadius, height: view.frame.height)), to: view.frame, duration: 0.25, delay: delay, timingFunction: kCAMediaTimingFunctionSpring) view.layer.animateFrame(from: CGRect(origin: view.frame.origin, size: CGSize(width: leftRadius, height: view.frame.height)), to: view.frame, duration: 0.25, delay: delay, timingFunction: kCAMediaTimingFunctionSpring)
}) })

View File

@ -0,0 +1,21 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "CodeInputView",
module_name = "CodeInputView",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/PhoneNumberFormat:PhoneNumberFormat",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,293 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import PhoneNumberFormat
public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
public struct Theme: Equatable {
public var inactiveBorder: UInt32
public var activeBorder: UInt32
public var foreground: UInt32
public var isDark: Bool
public init(
inactiveBorder: UInt32,
activeBorder: UInt32,
foreground: UInt32,
isDark: Bool
) {
self.inactiveBorder = inactiveBorder
self.activeBorder = activeBorder
self.foreground = foreground
self.isDark = isDark
}
}
private final class ItemView: ASDisplayNode {
private let backgroundView: UIImageView
private let textNode: ImmediateTextNode
private var borderColorValue: UInt32?
private var text: String = ""
override init() {
self.backgroundView = UIImageView()
self.textNode = ImmediateTextNode()
super.init()
self.addSubnode(self.textNode)
self.view.addSubview(self.backgroundView)
self.clipsToBounds = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(borderColor: UInt32) {
if self.borderColorValue != borderColor {
self.borderColorValue = borderColor
self.backgroundView.image = generateStretchableFilledCircleImage(diameter: 10.0, color: nil, strokeColor: UIColor(argb: borderColor), strokeWidth: 1.0, backgroundColor: nil)
}
}
func update(textColor: UInt32, text: String, size: CGSize, animated: Bool) {
let previousText = self.text
self.text = text
if animated && previousText.isEmpty != text.isEmpty {
if !text.isEmpty {
self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
self.textNode.layer.animatePosition(from: CGPoint(x: 0.0, y: size.height / 2.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
} 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?.removeFromSuperview()
})
copyView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: size.height / 2.0), duration: 0.2, removeOnCompletion: false, additive: true)
}
}
}
self.textNode.attributedText = NSAttributedString(string: text, font: Font.monospace(21.0), textColor: UIColor(argb: textColor))
let textSize = self.textNode.updateLayout(size)
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
self.backgroundView.frame = CGRect(origin: CGPoint(), size: size)
}
}
private let prefixLabel: ImmediateTextNode
private let textField: UITextField
private var focusIndex: Int?
private var itemViews: [ItemView] = []
public var updated: (() -> Void)?
private var theme: Theme?
private var count: Int?
private var textValue: String = ""
public var text: String {
get {
return self.textValue
} set(value) {
self.textValue = value
self.textField.text = value
}
}
override public init() {
self.prefixLabel = ImmediateTextNode()
self.textField = UITextField()
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.textField.keyboardType = .asciiCapableNumberPad
} else {
self.textField.keyboardType = .numberPad
}
if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
self.textField.textContentType = .oneTimeCode
}
self.textField.returnKeyType = .done
self.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
super.init()
self.addSubnode(self.prefixLabel)
self.view.addSubview(self.textField)
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
self.textField.delegate = self
self.textField.addTarget(self, action: #selector(self.textFieldChanged(_:)), for: .editingChanged)
}
required public init?(coder: NSCoder) {
preconditionFailure()
}
@objc private func tapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
self.textField.becomeFirstResponder()
}
}
@objc func textFieldChanged(_ textField: UITextField) {
self.textValue = textField.text ?? ""
self.updateItemViews(animated: true)
self.updated?()
}
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let count = self.count else {
return false
}
var text = textField.text ?? ""
guard let stringRange = Range(range, in: text) else {
return false
}
text.replaceSubrange(stringRange, with: string)
if !text.allSatisfy({ $0.isNumber && $0.isASCII }) {
return false
}
if text.count > count {
return false
}
return true
}
private func currentCaretIndex() -> Int? {
if let selectedTextRange = self.textField.selectedTextRange {
let index = self.textField.offset(from: self.textField.beginningOfDocument, to: selectedTextRange.end)
return index
} else {
return nil
}
}
public func textFieldDidBeginEditing(_ textField: UITextField) {
self.focusIndex = self.currentCaretIndex()
self.updateItemViews(animated: true)
}
public func textFieldDidEndEditing(_ textField: UITextField) {
self.focusIndex = nil
self.updateItemViews(animated: true)
}
public func textFieldDidChangeSelection(_ textField: UITextField) {
self.focusIndex = self.currentCaretIndex()
self.updateItemViews(animated: true)
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
return false
}
private func updateItemViews(animated: Bool) {
guard let theme = self.theme else {
return
}
for i in 0 ..< self.itemViews.count {
let itemView = self.itemViews[i]
let itemSize = itemView.bounds.size
itemView.update(borderColor: self.focusIndex == i ? theme.activeBorder : theme.inactiveBorder)
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, animated: animated)
}
}
public func update(theme: Theme, prefix: String, count: Int, width: CGFloat) -> CGSize {
self.theme = theme
self.count = count
if theme.isDark {
self.textField.keyboardAppearance = .dark
} else {
self.textField.keyboardAppearance = .light
}
let height: CGFloat = 28.0
self.prefixLabel.attributedText = NSAttributedString(string: prefix, font: Font.monospace(21.0), textColor: UIColor(argb: theme.foreground))
let prefixSize = self.prefixLabel.updateLayout(CGSize(width: width, height: 100.0))
let prefixSpacing: CGFloat = prefix.isEmpty ? 0.0 : 8.0
let itemSize = CGSize(width: 25.0, height: height)
let itemSpacing: CGFloat = 5.0
let itemsWidth: CGFloat = itemSize.width * CGFloat(count) + itemSpacing * CGFloat(count - 1)
let contentWidth: CGFloat = prefixSize.width + prefixSpacing + itemsWidth
let contentOriginX: CGFloat = floor((width - contentWidth) / 2.0)
self.prefixLabel.frame = CGRect(origin: CGPoint(x: contentOriginX, y: floorToScreenPixels((height - prefixSize.height) / 2.0)), size: prefixSize)
for i in 0 ..< count {
let itemView: ItemView
if self.itemViews.count > i {
itemView = self.itemViews[i]
} else {
itemView = ItemView()
self.itemViews.append(itemView)
self.addSubnode(itemView)
}
itemView.update(borderColor: self.focusIndex == i ? theme.activeBorder : theme.inactiveBorder)
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, animated: false)
itemView.frame = CGRect(origin: CGPoint(x: contentOriginX + prefixSize.width + prefixSpacing + CGFloat(i) * (itemSize.width + itemSpacing), y: 0.0), size: itemSize)
}
if self.itemViews.count > count {
for i in count ..< self.itemViews.count {
self.itemViews[i].removeFromSupernode()
}
self.itemViews.removeSubrange(count...)
}
return CGSize(width: width, height: height)
}
public override func becomeFirstResponder() -> Bool {
return self.textField.becomeFirstResponder()
}
public override func canBecomeFirstResponder() -> Bool {
return self.textField.canBecomeFirstResponder
}
public override func resignFirstResponder() -> Bool {
return self.textField.resignFirstResponder()
}
public override func canResignFirstResponder() -> Bool {
return self.textField.canResignFirstResponder
}
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.bounds.contains(point) {
return self.view
} else {
return nil
}
}
}

View File

@ -148,7 +148,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) } dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) }
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) } dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) }
dict[1571494644] = { return Api.ExportedMessageLink.parse_exportedMessageLink($0) } dict[1571494644] = { return Api.ExportedMessageLink.parse_exportedMessageLink($0) }
dict[-855308010] = { return Api.auth.Authorization.parse_authorization($0) } dict[872119224] = { return Api.auth.Authorization.parse_authorization($0) }
dict[1148485274] = { return Api.auth.Authorization.parse_authorizationSignUpRequired($0) } dict[1148485274] = { return Api.auth.Authorization.parse_authorizationSignUpRequired($0) }
dict[-181407105] = { return Api.InputFile.parse_inputFile($0) } dict[-181407105] = { return Api.InputFile.parse_inputFile($0) }
dict[-95482955] = { return Api.InputFile.parse_inputFileBig($0) } dict[-95482955] = { return Api.InputFile.parse_inputFileBig($0) }

View File

@ -1037,16 +1037,17 @@ public struct auth {
} }
public enum Authorization: TypeConstructorDescription { public enum Authorization: TypeConstructorDescription {
case authorization(flags: Int32, tmpSessions: Int32?, user: Api.User) case authorization(flags: Int32, otherwiseReloginDays: Int32?, tmpSessions: Int32?, user: Api.User)
case authorizationSignUpRequired(flags: Int32, termsOfService: Api.help.TermsOfService?) case authorizationSignUpRequired(flags: Int32, termsOfService: Api.help.TermsOfService?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .authorization(let flags, let tmpSessions, let user): case .authorization(let flags, let otherwiseReloginDays, let tmpSessions, let user):
if boxed { if boxed {
buffer.appendInt32(-855308010) buffer.appendInt32(872119224)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(otherwiseReloginDays!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(tmpSessions!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 0) != 0 {serializeInt32(tmpSessions!, buffer: buffer, boxed: false)}
user.serialize(buffer, true) user.serialize(buffer, true)
break break
@ -1062,8 +1063,8 @@ public struct auth {
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .authorization(let flags, let tmpSessions, let user): case .authorization(let flags, let otherwiseReloginDays, let tmpSessions, let user):
return ("authorization", [("flags", flags), ("tmpSessions", tmpSessions), ("user", user)]) return ("authorization", [("flags", flags), ("otherwiseReloginDays", otherwiseReloginDays), ("tmpSessions", tmpSessions), ("user", user)])
case .authorizationSignUpRequired(let flags, let termsOfService): case .authorizationSignUpRequired(let flags, let termsOfService):
return ("authorizationSignUpRequired", [("flags", flags), ("termsOfService", termsOfService)]) return ("authorizationSignUpRequired", [("flags", flags), ("termsOfService", termsOfService)])
} }
@ -1073,16 +1074,19 @@ public struct auth {
var _1: Int32? var _1: Int32?
_1 = reader.readInt32() _1 = reader.readInt32()
var _2: Int32? var _2: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() }
var _3: Api.User? var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
var _4: Api.User?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.User _4 = Api.parse(reader, signature: signature) as? Api.User
} }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil
let _c3 = _3 != nil let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
if _c1 && _c2 && _c3 { let _c4 = _4 != nil
return Api.auth.Authorization.authorization(flags: _1!, tmpSessions: _2, user: _3!) if _c1 && _c2 && _c3 && _c4 {
return Api.auth.Authorization.authorization(flags: _1!, otherwiseReloginDays: _2, tmpSessions: _3, user: _4!)
} }
else { else {
return nil return nil

View File

@ -429,7 +429,25 @@ private func cleanupAccount(networkArguments: NetworkInitializationArguments, ac
|> `catch` { _ -> Signal<Api.auth.LoggedOut?, NoError> in |> `catch` { _ -> Signal<Api.auth.LoggedOut?, NoError> in
return .single(nil) return .single(nil)
} }
|> mapToSignal { _ -> Signal<Void, NoError> in |> mapToSignal { result -> Signal<Void, NoError> in
let _ = (accountManager.transaction { transaction -> Void in
var tokens = transaction.getStoredLoginTokens()
switch result {
case let .loggedOut(_, futureAuthToken, futureAuthExpires):
if let futureAuthToken = futureAuthToken {
tokens.insert(futureAuthToken.makeData(), at: 0)
}
let _ = futureAuthExpires
default:
break
}
if tokens.count > 20 {
tokens.removeLast(tokens.count - 20)
}
transaction.setStoredLoginTokens(tokens)
}).start()
account.shouldBeServiceTaskMaster.set(.single(.never)) account.shouldBeServiceTaskMaster.set(.single(.never))
return accountManager.transaction { transaction -> Void in return accountManager.transaction { transaction -> Void in
transaction.updateRecord(id, { _ in transaction.updateRecord(id, { _ in

View File

@ -24,12 +24,15 @@ public struct AccountManagerModifier<Types: AccountManagerTypes> {
public let getNotice: (NoticeEntryKey) -> CodableEntry? public let getNotice: (NoticeEntryKey) -> CodableEntry?
public let setNotice: (NoticeEntryKey, CodableEntry?) -> Void public let setNotice: (NoticeEntryKey, CodableEntry?) -> Void
public let clearNotices: () -> Void public let clearNotices: () -> Void
public let getStoredLoginTokens: () -> [Data]
public let setStoredLoginTokens: ([Data]) -> Void
} }
final class AccountManagerImpl<Types: AccountManagerTypes> { final class AccountManagerImpl<Types: AccountManagerTypes> {
private let queue: Queue private let queue: Queue
private let basePath: String private let basePath: String
private let atomicStatePath: String private let atomicStatePath: String
private let loginTokensPath: String
private let temporarySessionId: Int64 private let temporarySessionId: Int64
private let guardValueBox: ValueBox? private let guardValueBox: ValueBox?
private let valueBox: ValueBox private let valueBox: ValueBox
@ -76,6 +79,7 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
self.queue = queue self.queue = queue
self.basePath = basePath self.basePath = basePath
self.atomicStatePath = "\(basePath)/atomic-state" self.atomicStatePath = "\(basePath)/atomic-state"
self.loginTokensPath = "\(basePath)/login-tokens"
self.temporarySessionId = temporarySessionId self.temporarySessionId = temporarySessionId
let _ = try? FileManager.default.createDirectory(atPath: basePath, withIntermediateDirectories: true, attributes: nil) let _ = try? FileManager.default.createDirectory(atPath: basePath, withIntermediateDirectories: true, attributes: nil)
guard let guardValueBox = SqliteValueBox(basePath: basePath + "/guard_db", queue: queue, isTemporary: isTemporary, isReadOnly: false, useCaches: useCaches, encryptionParameters: nil, upgradeProgress: { _ in }) else { guard let guardValueBox = SqliteValueBox(basePath: basePath + "/guard_db", queue: queue, isTemporary: isTemporary, isReadOnly: false, useCaches: useCaches, encryptionParameters: nil, upgradeProgress: { _ in }) else {
@ -209,6 +213,10 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
self.currentUpdatedNoticeEntryKeys.insert(key) self.currentUpdatedNoticeEntryKeys.insert(key)
}, clearNotices: { }, clearNotices: {
self.noticeTable.clear() self.noticeTable.clear()
}, getStoredLoginTokens: {
return self.getLoginTokens()
}, setStoredLoginTokens: { list in
self.setLoginTokens(list: list)
}) })
let result = f(transaction) let result = f(transaction)
@ -243,6 +251,23 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
} }
} }
private func getLoginTokens() -> [Data] {
guard let data = try? Data(contentsOf: URL(fileURLWithPath: self.loginTokensPath)) else {
return []
}
guard let list = try? JSONDecoder().decode([Data].self, from: data) else {
return []
}
return list
}
private func setLoginTokens(list: [Data]) {
if let data = try? JSONEncoder().encode(list) {
if let _ = try? data.write(to: URL(fileURLWithPath: self.loginTokensPath), options: [.atomic]) {
}
}
}
private func beforeCommit() { private func beforeCommit() {
if self.currentAtomicStateUpdated { if self.currentAtomicStateUpdated {
self.syncAtomicStateToFile() self.syncAtomicStateToFile()

View File

@ -72,61 +72,99 @@ private func ~=<T: RegularExpressionMatchable>(pattern: Regex, matchable: T) ->
} }
public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccountManagerTypes>, account: UnauthorizedAccount, phoneNumber: String, apiId: Int32, apiHash: String, syncContacts: Bool) -> Signal<UnauthorizedAccount, AuthorizationCodeRequestError> { public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccountManagerTypes>, account: UnauthorizedAccount, phoneNumber: String, apiId: Int32, apiHash: String, syncContacts: Bool) -> Signal<UnauthorizedAccount, AuthorizationCodeRequestError> {
var flags: Int32 = 0 return accountManager.transaction { transaction -> [Data] in
flags |= 1 << 5 //allowMissedCall return transaction.getStoredLoginTokens()
let sendCode = Api.functions.auth.sendCode(phoneNumber: phoneNumber, apiId: apiId, apiHash: apiHash, settings: .codeSettings(flags: flags, logoutTokens: nil))
let codeAndAccount = account.network.request(sendCode, automaticFloodWait: false)
|> map { result in
return (result, account)
} }
|> `catch` { error -> Signal<(Api.auth.SentCode, UnauthorizedAccount), MTRpcError> in |> castError(AuthorizationCodeRequestError.self)
switch MatchString(error.errorDescription ?? "") { |> mapToSignal { authTokens -> Signal<UnauthorizedAccount, AuthorizationCodeRequestError> in
case Regex("(PHONE_|USER_|NETWORK_)MIGRATE_(\\d+)"): var flags: Int32 = 0
let range = error.errorDescription.range(of: "MIGRATE_")! flags |= 1 << 5 //allowMissedCall
let updatedMasterDatacenterId = Int32(error.errorDescription[range.upperBound ..< error.errorDescription.endIndex])! flags |= 1 << 6 //tokens
let updatedAccount = account.changedMasterDatacenterId(accountManager: accountManager, masterDatacenterId: updatedMasterDatacenterId) let sendCode = Api.functions.auth.sendCode(phoneNumber: phoneNumber, apiId: apiId, apiHash: apiHash, settings: .codeSettings(flags: flags, logoutTokens: authTokens.map { Buffer(data: $0) }))
return updatedAccount
|> mapToSignalPromotingError { updatedAccount -> Signal<(Api.auth.SentCode, UnauthorizedAccount), MTRpcError> in enum SendCodeResult {
return updatedAccount.network.request(sendCode, automaticFloodWait: false) case password(hint: String?)
|> map { sentCode in case sentCode(Api.auth.SentCode)
return (sentCode, updatedAccount) }
let codeAndAccount = account.network.request(sendCode, automaticFloodWait: false)
|> map { result -> (SendCodeResult, UnauthorizedAccount) in
return (.sentCode(result), account)
}
|> `catch` { error -> Signal<(SendCodeResult, UnauthorizedAccount), MTRpcError> in
switch MatchString(error.errorDescription ?? "") {
case Regex("(PHONE_|USER_|NETWORK_)MIGRATE_(\\d+)"):
let range = error.errorDescription.range(of: "MIGRATE_")!
let updatedMasterDatacenterId = Int32(error.errorDescription[range.upperBound ..< error.errorDescription.endIndex])!
let updatedAccount = account.changedMasterDatacenterId(accountManager: accountManager, masterDatacenterId: updatedMasterDatacenterId)
return updatedAccount
|> mapToSignalPromotingError { updatedAccount -> Signal<(SendCodeResult, UnauthorizedAccount), MTRpcError> in
return updatedAccount.network.request(sendCode, automaticFloodWait: false)
|> map { sentCode in
return (.sentCode(sentCode), updatedAccount)
}
}
case _:
return .fail(error)
}
}
|> `catch` { error -> Signal<(SendCodeResult, UnauthorizedAccount), AuthorizationCodeRequestError> in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .fail(.limitExceeded)
} else if error.errorDescription == "PHONE_NUMBER_INVALID" {
return .fail(.invalidPhoneNumber)
} else if error.errorDescription == "PHONE_NUMBER_FLOOD" {
return .fail(.phoneLimitExceeded)
} else if error.errorDescription == "PHONE_NUMBER_BANNED" {
return .fail(.phoneBanned)
} else if error.errorDescription == "SESSION_PASSWORD_NEEDED" {
return account.network.request(Api.functions.account.getPassword(), automaticFloodWait: false)
|> mapError { error -> AuthorizationCodeRequestError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else {
return .generic(info: (Int(error.errorCode), error.errorDescription))
} }
} }
case _: |> mapToSignal { result -> Signal<(SendCodeResult, UnauthorizedAccount), AuthorizationCodeRequestError> in
return .fail(error) switch result {
} case let .password(_, _, _, _, hint, _, _, _, _, _):
} return .single((.password(hint: hint), account))
|> mapError { error -> AuthorizationCodeRequestError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else if error.errorDescription == "PHONE_NUMBER_INVALID" {
return .invalidPhoneNumber
} else if error.errorDescription == "PHONE_NUMBER_FLOOD" {
return .phoneLimitExceeded
} else if error.errorDescription == "PHONE_NUMBER_BANNED" {
return .phoneBanned
} else {
return .generic(info: (Int(error.errorCode), error.errorDescription))
}
}
|> timeout(20.0, queue: Queue.concurrentDefaultQueue(), alternate: .fail(.timeout))
return codeAndAccount
|> mapToSignal { sentCode, account -> Signal<UnauthorizedAccount, AuthorizationCodeRequestError> in
return account.postbox.transaction { transaction -> UnauthorizedAccount in
switch sentCode {
case let .sentCode(_, type, phoneCodeHash, nextType, timeout):
var parsedNextType: AuthorizationCodeNextType?
if let nextType = nextType {
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
} }
}
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: timeout, nextType: parsedNextType, syncContacts: syncContacts))) } else {
return .fail(.generic(info: (Int(error.errorCode), error.errorDescription)))
} }
return account
} }
|> mapError { _ -> AuthorizationCodeRequestError in |> timeout(20.0, queue: Queue.concurrentDefaultQueue(), alternate: .fail(.timeout))
return codeAndAccount
|> mapToSignal { result, account -> Signal<UnauthorizedAccount, AuthorizationCodeRequestError> in
return account.postbox.transaction { transaction -> UnauthorizedAccount in
switch result {
case let .password(hint):
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint ?? "", number: nil, code: nil, suggestReset: false, syncContacts: syncContacts)))
case let .sentCode(sentCode):
switch sentCode {
case let .sentCode(_, type, phoneCodeHash, nextType, timeout):
/*#if DEBUG
var type = type
type = .sentCodeTypeMissedCall(prefix: "+44 1234 8", length: 5)
var nextType = nextType
nextType = nil
#endif*/
var parsedNextType: AuthorizationCodeNextType?
if let nextType = nextType {
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
}
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: timeout, nextType: parsedNextType, syncContacts: syncContacts)))
}
}
return account
}
|> mapError { _ -> AuthorizationCodeRequestError in
}
} }
} }
} }
@ -257,7 +295,7 @@ public func authorizeWithCode(accountManager: AccountManager<TelegramAccountMana
return .single(.loggedIn) return .single(.loggedIn)
case let .authorization(authorization): case let .authorization(authorization):
switch authorization { switch authorization {
case let .authorization(_, _, user): case let .authorization(_, _, _, user):
let user = TelegramUser(user: user) let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts) initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts)
@ -314,7 +352,7 @@ public func authorizeWithPassword(accountManager: AccountManager<TelegramAccount
|> mapToSignal { result -> Signal<Void, AuthorizationPasswordVerificationError> in |> mapToSignal { result -> Signal<Void, AuthorizationPasswordVerificationError> in
return account.postbox.transaction { transaction -> Signal<Void, NoError> in return account.postbox.transaction { transaction -> Signal<Void, NoError> in
switch result { switch result {
case let .authorization(_, _, user): case let .authorization(_, _, _, user):
let user = TelegramUser(user: user) let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
/*transaction.updatePeersInternal([user], update: { current, peer -> Peer? in /*transaction.updatePeersInternal([user], update: { current, peer -> Peer? in
@ -380,7 +418,7 @@ public final class RecoveredAccountData {
public func loginWithRecoveredAccountData(accountManager: AccountManager<TelegramAccountManagerTypes>, account: UnauthorizedAccount, recoveredAccountData: RecoveredAccountData, syncContacts: Bool) -> Signal<Never, NoError> { public func loginWithRecoveredAccountData(accountManager: AccountManager<TelegramAccountManagerTypes>, account: UnauthorizedAccount, recoveredAccountData: RecoveredAccountData, syncContacts: Bool) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in return account.postbox.transaction { transaction -> Signal<Void, NoError> in
switch recoveredAccountData.authorization { switch recoveredAccountData.authorization {
case let .authorization(_, _, user): case let .authorization(_, _, _, user):
let user = TelegramUser(user: user) let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
@ -516,7 +554,7 @@ public func signUpWithName(accountManager: AccountManager<TelegramAccountManager
} }
|> mapToSignal { result -> Signal<Void, SignUpError> in |> mapToSignal { result -> Signal<Void, SignUpError> in
switch result { switch result {
case let .authorization(_, _, user): case let .authorization(_, _, _, user):
let user = TelegramUser(user: user) let user = TelegramUser(user: user)
let appliedState = account.postbox.transaction { transaction -> Void in let appliedState = account.postbox.transaction { transaction -> Void in
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)

View File

@ -92,7 +92,7 @@ func _internal_exportAuthTransferToken(accountManager: AccountManager<TelegramAc
switch result { switch result {
case let .loginTokenSuccess(authorization): case let .loginTokenSuccess(authorization):
switch authorization { switch authorization {
case let .authorization(_, _, user): case let .authorization(_, _, _, user):
return updatedAccount.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in return updatedAccount.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
let user = TelegramUser(user: user) let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: updatedAccount.testingEnvironment, masterDatacenterId: updatedAccount.masterDatacenterId, peerId: user.id, state: nil) let state = AuthorizedAccountState(isTestingEnvironment: updatedAccount.testingEnvironment, masterDatacenterId: updatedAccount.masterDatacenterId, peerId: user.id, state: nil)
@ -116,7 +116,7 @@ func _internal_exportAuthTransferToken(accountManager: AccountManager<TelegramAc
} }
case let .loginTokenSuccess(authorization): case let .loginTokenSuccess(authorization):
switch authorization { switch authorization {
case let .authorization(_, _, user): case let .authorization(_, _, _, user):
return account.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in return account.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
let user = TelegramUser(user: user) let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)

View File

@ -246,6 +246,7 @@ swift_library(
"//submodules/LottieMeshSwift:LottieMeshSwift", "//submodules/LottieMeshSwift:LottieMeshSwift",
"//submodules/MeshAnimationCache:MeshAnimationCache", "//submodules/MeshAnimationCache:MeshAnimationCache",
"//submodules/DirectMediaImageCache:DirectMediaImageCache", "//submodules/DirectMediaImageCache:DirectMediaImageCache",
"//submodules/CodeInputView:CodeInputView",
] + select({ ] + select({
"@build_bazel_rules_apple//apple:ios_armv7": [], "@build_bazel_rules_apple//apple:ios_armv7": [],
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets, "@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,

View File

@ -102,9 +102,10 @@ final class AuthorizationSequenceCodeEntryController: ViewController {
func updateData(number: String, codeType: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, timeout: Int32?, termsOfService: (UnauthorizedAccountTermsOfService, Bool)?) { func updateData(number: String, codeType: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, timeout: Int32?, termsOfService: (UnauthorizedAccountTermsOfService, Bool)?) {
self.termsOfService = termsOfService self.termsOfService = termsOfService
if self.data?.0 != number || self.data?.1 != codeType || self.data?.2 != nextType || self.data?.3 != timeout { if self.data?.0 != number || self.data?.1 != codeType || self.data?.2 != nextType || self.data?.3 != timeout {
if case .otherSession = codeType { switch codeType {
case .otherSession, .missedCall:
self.title = number self.title = number
} else { default:
self.title = nil self.title = nil
} }
self.data = (number, codeType, nextType, timeout) self.data = (number, codeType, nextType, timeout)

View File

@ -7,6 +7,7 @@ import SwiftSignalKit
import TelegramPresentationData import TelegramPresentationData
import TextFormat import TextFormat
import AuthorizationUI import AuthorizationUI
import CodeInputView
final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextFieldDelegate { final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextFieldDelegate {
private let strings: PresentationStrings private let strings: PresentationStrings
@ -15,10 +16,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
private let titleNode: ImmediateTextNode private let titleNode: ImmediateTextNode
private let titleIconNode: ASImageNode private let titleIconNode: ASImageNode
private let currentOptionNode: ASTextNode private let currentOptionNode: ASTextNode
private let currentOptionInfoNode: ASTextNode
private let nextOptionNode: HighlightableButtonNode private let nextOptionNode: HighlightableButtonNode
private let codeField: TextFieldNode private let codeInputView: CodeInputView
private let codeSeparatorNode: ASDisplayNode //private let codeField: TextFieldNode
//private let codeSeparatorNode: ASDisplayNode
private var codeType: SentAuthorizationCodeType? private var codeType: SentAuthorizationCodeType?
@ -38,7 +41,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
} }
var currentCode: String { var currentCode: String {
return self.codeField.textField.text ?? "" return self.codeInputView.text
//return self.codeField.textField.text ?? ""
} }
var loginWithCode: ((String) -> Void)? var loginWithCode: ((String) -> Void)?
@ -48,7 +52,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
var inProgress: Bool = false { var inProgress: Bool = false {
didSet { didSet {
self.codeField.alpha = self.inProgress ? 0.6 : 1.0 self.codeInputView.alpha = self.inProgress ? 0.6 : 1.0
//self.codeField.alpha = self.inProgress ? 0.6 : 1.0
} }
} }
@ -66,46 +71,28 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.titleIconNode.isLayerBacked = true self.titleIconNode.isLayerBacked = true
self.titleIconNode.displayWithoutProcessing = true self.titleIconNode.displayWithoutProcessing = true
self.titleIconNode.displaysAsynchronously = false self.titleIconNode.displaysAsynchronously = false
self.titleIconNode.image = generateImage(CGSize(width: 81.0, height: 52.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.list.itemPrimaryTextColor.cgColor)
context.setStrokeColor(theme.list.itemPrimaryTextColor.cgColor)
context.setLineWidth(2.97)
let _ = try? drawSvgPath(context, path: "M9.87179487,9.04664384 C9.05602951,9.04664384 8.39525641,9.70682916 8.39525641,10.5205479 L8.39525641,44.0547945 C8.39525641,44.8685133 9.05602951,45.5286986 9.87179487,45.5286986 L65.1538462,45.5286986 C65.9696115,45.5286986 66.6303846,44.8685133 66.6303846,44.0547945 L66.6303846,10.5205479 C66.6303846,9.70682916 65.9696115,9.04664384 65.1538462,9.04664384 L9.87179487,9.04664384 S ")
let _ = try? drawSvgPath(context, path: "M0,44.0547945 L75.025641,44.0547945 C75.025641,45.2017789 74.2153348,46.1893143 73.0896228,46.4142565 L66.1123641,47.8084669 C65.4749109,47.9358442 64.8264231,48 64.1763458,48 L10.8492952,48 C10.1992179,48 9.55073017,47.9358442 8.91327694,47.8084669 L1.93601826,46.4142565 C0.810306176,46.1893143 0,45.2017789 0,44.0547945 Z ")
let _ = try? drawSvgPath(context, path: "M2.96153846,16.4383562 L14.1495726,16.4383562 C15.7851852,16.4383562 17.1111111,17.7631027 17.1111111,19.3972603 L17.1111111,45.0410959 C17.1111111,46.6752535 15.7851852,48 14.1495726,48 L2.96153846,48 C1.32592593,48 0,46.6752535 0,45.0410959 L0,19.3972603 C0,17.7631027 1.32592593,16.4383562 2.96153846,16.4383562 Z ")
context.setStrokeColor(theme.list.plainBackgroundColor.cgColor)
context.setLineWidth(1.65)
let _ = try? drawSvgPath(context, path: "M2.96153846,15.6133562 L14.1495726,15.6133562 C16.2406558,15.6133562 17.9361111,17.3073033 17.9361111,19.3972603 L17.9361111,45.0410959 C17.9361111,47.1310529 16.2406558,48.825 14.1495726,48.825 L2.96153846,48.825 C0.870455286,48.825 -0.825,47.1310529 -0.825,45.0410959 L-0.825,19.3972603 C-0.825,17.3073033 0.870455286,15.6133562 2.96153846,15.6133562 S ")
context.setFillColor(theme.list.plainBackgroundColor.cgColor)
let _ = try? drawSvgPath(context, path: "M1.64529915,20.3835616 L15.465812,20.3835616 L15.465812,44.0547945 L1.64529915,44.0547945 Z ")
context.setFillColor(theme.list.itemAccentColor.cgColor)
let _ = try? drawSvgPath(context, path: "M66.4700855,0.0285884455 C60.7084674,0.0285884455 55.9687848,4.08259697 55.9687848,9.14830256 C55.9687848,12.0875991 57.5993165,14.6795278 60.0605723,16.3382966 C60.0568181,16.4358994 60.0611217,16.5884309 59.9318097,17.067302 C59.7721478,17.6586615 59.4575977,18.4958519 58.8015608,19.4258487 L58.3294314,20.083383 L59.1449275,20.0976772 C61.9723538,20.1099725 63.6110772,18.2528913 63.8662207,17.9535438 C64.7014993,18.1388449 65.5698144,18.2680167 66.4700855,18.2680167 C72.2312622,18.2680167 76.9713861,14.2140351 76.9713861,9.14830256 C76.9713861,4.08256999 72.2312622,0.0285884455 66.4700855,0.0285884455 Z ")
let _ = try? drawSvgPath(context, path: "M64.1551769,18.856071 C63.8258967,19.1859287 63.4214479,19.5187 62.9094963,19.840779 C61.8188563,20.5269227 60.5584776,20.9288319 59.1304689,20.9225505 L56.7413094,20.8806727 L57.6592902,19.6022014 L58.127415,18.9502938 C58.6361919,18.2290526 58.9525079,17.5293964 59.1353377,16.8522267 C59.1487516,16.8025521 59.1603548,16.7584153 59.1703974,16.7187893 C56.653362,14.849536 55.1437848,12.1128655 55.1437848,9.14830256 C55.1437848,3.61947515 60.2526259,-0.796411554 66.4700855,-0.796411554 C72.6872626,-0.796411554 77.7963861,3.61958236 77.7963861,9.14830256 C77.7963861,14.6770228 72.6872626,19.0930167 66.4700855,19.0930167 C65.7185957,19.0930167 64.9627196,19.0118067 64.1551769,18.856071 S ")
})
self.currentOptionNode = ASTextNode() self.currentOptionNode = ASTextNode()
self.currentOptionNode.isUserInteractionEnabled = false self.currentOptionNode.isUserInteractionEnabled = false
self.currentOptionNode.displaysAsynchronously = false self.currentOptionNode.displaysAsynchronously = false
self.currentOptionInfoNode = ASTextNode()
self.currentOptionInfoNode.isUserInteractionEnabled = false
self.currentOptionInfoNode.displaysAsynchronously = false
self.nextOptionNode = HighlightableButtonNode() self.nextOptionNode = HighlightableButtonNode()
self.nextOptionNode.displaysAsynchronously = false self.nextOptionNode.displaysAsynchronously = false
let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: .sms(length: 5), nextType: .call, timeout: 60, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor) let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: .sms(length: 5), nextType: .call, timeout: 60, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor)
self.nextOptionNode.setAttributedTitle(nextOptionText, for: []) self.nextOptionNode.setAttributedTitle(nextOptionText, for: [])
self.nextOptionNode.isUserInteractionEnabled = nextOptionActive self.nextOptionNode.isUserInteractionEnabled = nextOptionActive
self.codeSeparatorNode = ASDisplayNode() /*self.codeSeparatorNode = ASDisplayNode()
self.codeSeparatorNode.isLayerBacked = true self.codeSeparatorNode.isLayerBacked = true
self.codeSeparatorNode.backgroundColor = self.theme.list.itemPlainSeparatorColor self.codeSeparatorNode.backgroundColor = self.theme.list.itemPlainSeparatorColor*/
self.codeField = TextFieldNode() self.codeInputView = CodeInputView()
/*self.codeField = TextFieldNode()
self.codeField.textField.font = Font.regular(24.0) self.codeField.textField.font = Font.regular(24.0)
self.codeField.textField.textAlignment = .center self.codeField.textField.textAlignment = .center
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
@ -113,16 +100,14 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
} else { } else {
self.codeField.textField.keyboardType = .numberPad self.codeField.textField.keyboardType = .numberPad
} }
#if swift(>=4.2)
if #available(iOSApplicationExtension 12.0, iOS 12.0, *) { if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
self.codeField.textField.textContentType = .oneTimeCode self.codeField.textField.textContentType = .oneTimeCode
} }
#endif
self.codeField.textField.returnKeyType = .done self.codeField.textField.returnKeyType = .done
self.codeField.textField.textColor = self.theme.list.itemPrimaryTextColor self.codeField.textField.textColor = self.theme.list.itemPrimaryTextColor
self.codeField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance self.codeField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward] self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
self.codeField.textField.tintColor = self.theme.list.itemAccentColor self.codeField.textField.tintColor = self.theme.list.itemAccentColor*/
super.init() super.init()
@ -132,18 +117,26 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.backgroundColor = self.theme.list.plainBackgroundColor self.backgroundColor = self.theme.list.plainBackgroundColor
self.addSubnode(self.codeSeparatorNode) self.addSubnode(self.codeInputView)
self.addSubnode(self.codeField) //self.addSubnode(self.codeSeparatorNode)
//self.addSubnode(self.codeField)
self.addSubnode(self.titleNode) self.addSubnode(self.titleNode)
self.addSubnode(self.titleIconNode) self.addSubnode(self.titleIconNode)
self.addSubnode(self.currentOptionNode) self.addSubnode(self.currentOptionNode)
self.addSubnode(self.currentOptionInfoNode)
self.addSubnode(self.nextOptionNode) self.addSubnode(self.nextOptionNode)
self.codeField.textField.delegate = self self.codeInputView.updated = { [weak self] in
self.codeField.textField.addTarget(self, action: #selector(self.codeFieldTextChanged(_:)), for: .editingChanged) guard let strongSelf = self else {
return
}
strongSelf.textChanged(text: strongSelf.codeInputView.text)
}
self.codeField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_Code, font: Font.regular(24.0), textColor: self.theme.list.itemPlaceholderTextColor //self.codeField.textField.delegate = self
) //self.codeField.textField.addTarget(self, action: #selector(self.codeFieldTextChanged(_:)), for: .editingChanged)
//self.codeField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_Code, font: Font.regular(24.0), textColor: self.theme.list.itemPlaceholderTextColor)
self.nextOptionNode.addTarget(self, action: #selector(self.nextOptionNodePressed), forControlEvents: .touchUpInside) self.nextOptionNode.addTarget(self, action: #selector(self.nextOptionNodePressed), forControlEvents: .touchUpInside)
} }
@ -153,8 +146,10 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
} }
func updateCode(_ code: String) { func updateCode(_ code: String) {
self.codeField.textField.text = code self.codeInputView.text = code
self.codeFieldTextChanged(self.codeField.textField) self.textChanged(text: code)
//self.codeField.textField.text = code
//self.codeFieldTextChanged(self.codeField.textField)
if let codeType = self.codeType { if let codeType = self.codeType {
var codeLength: Int32? var codeLength: Int32?
switch codeType { switch codeType {
@ -162,6 +157,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
codeLength = length codeLength = length
case let .otherSession(length): case let .otherSession(length):
codeLength = length codeLength = length
case let .missedCall(_, length):
codeLength = length
case let .sms(length): case let .sms(length):
codeLength = length codeLength = length
default: default:
@ -178,6 +175,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.phoneNumber = number self.phoneNumber = number
self.currentOptionNode.attributedText = authorizationCurrentOptionText(codeType, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor) self.currentOptionNode.attributedText = authorizationCurrentOptionText(codeType, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor)
if case .missedCall = codeType {
//TODO:localize
self.currentOptionInfoNode.attributedText = NSAttributedString(string: "Please enter the last five digits\nof the missed call number.", font: Font.regular(16.0), textColor: self.theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
} else {
self.currentOptionInfoNode.attributedText = NSAttributedString(string: "", font: Font.regular(15.0), textColor: self.theme.list.itemPrimaryTextColor)
}
if let timeout = timeout { if let timeout = timeout {
self.currentTimeoutTime = timeout self.currentTimeoutTime = timeout
let disposable = ((Signal<Int, NoError>.single(1) |> delay(1.0, queue: Queue.mainQueue())) |> restart).start(next: { [weak self] _ in let disposable = ((Signal<Int, NoError>.single(1) |> delay(1.0, queue: Queue.mainQueue())) |> restart).start(next: { [weak self] _ in
@ -218,20 +221,42 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
} }
if max(layout.size.width, layout.size.height) > 1023.0 { if max(layout.size.width, layout.size.height) > 1023.0 {
if let codeType = self.codeType, case .otherSession = codeType { if let codeType = self.codeType {
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_CheckOtherSessionMessages, font: Font.medium(32.0), textColor: self.theme.list.itemPrimaryTextColor) switch codeType {
case .otherSession:
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_CheckOtherSessionMessages, font: Font.medium(32.0), textColor: self.theme.list.itemPrimaryTextColor)
case .missedCall:
//TODO:localize
self.titleNode.attributedText = NSAttributedString(string: "Enter the missing digits", font: Font.medium(32.0), textColor: self.theme.list.itemPrimaryTextColor)
default:
self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.light(40.0), textColor: self.theme.list.itemPrimaryTextColor)
}
} else { } else {
self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.light(40.0), textColor: self.theme.list.itemPrimaryTextColor) self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.light(40.0), textColor: self.theme.list.itemPrimaryTextColor)
} }
} else { } else {
if let codeType = self.codeType, case .otherSession = codeType { if let codeType = self.codeType {
let fontSize: CGFloat switch codeType {
if layout.size.width > 330.0 { case .otherSession:
fontSize = 22.0 let fontSize: CGFloat
} else { if layout.size.width > 330.0 {
fontSize = 18.0 fontSize = 22.0
} else {
fontSize = 18.0
}
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_CheckOtherSessionMessages, font: Font.semibold(fontSize), textColor: self.theme.list.itemPrimaryTextColor)
case .missedCall:
let fontSize: CGFloat
if layout.size.width > 330.0 {
fontSize = 22.0
} else {
fontSize = 18.0
}
//TODO:localize
self.titleNode.attributedText = NSAttributedString(string: "Enter the missing digits", font: Font.semibold(fontSize), textColor: self.theme.list.itemPrimaryTextColor)
default:
self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.light(30.0), textColor: self.theme.list.itemPrimaryTextColor)
} }
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_CheckOtherSessionMessages, font: Font.semibold(fontSize), textColor: self.theme.list.itemPrimaryTextColor)
} else { } else {
self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.light(30.0), textColor: self.theme.list.itemPrimaryTextColor) self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.light(30.0), textColor: self.theme.list.itemPrimaryTextColor)
} }
@ -240,24 +265,128 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude)) let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let currentOptionSize = self.currentOptionNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude)) let currentOptionSize = self.currentOptionNode.measure(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 nextOptionSize = self.nextOptionNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude)) let nextOptionSize = self.nextOptionNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let codeLength: Int
var codePrefix: String = ""
switch self.codeType {
case .flashCall:
codeLength = 6
case let .call(length):
codeLength = Int(length)
case let .otherSession(length):
codeLength = Int(length)
case let .missedCall(prefix, length):
codePrefix = prefix
codeLength = Int(length)
case let .sms(length):
codeLength = Int(length)
case .none:
codeLength = 6
}
let codeFieldSize = self.codeInputView.update(
theme: CodeInputView.Theme(
inactiveBorder: self.theme.list.itemPlainSeparatorColor.argb,
activeBorder: self.theme.list.itemAccentColor.argb,
foreground: self.theme.list.itemPrimaryTextColor.argb,
isDark: self.theme.overallDarkAppearance
),
prefix: codePrefix,
count: codeLength,
width: layout.size.width - 28.0
)
var items: [AuthorizationLayoutItem] = [] var items: [AuthorizationLayoutItem] = []
if let codeType = self.codeType, case .otherSession = codeType { if let codeType = self.codeType {
self.titleIconNode.isHidden = false switch codeType {
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))) case .otherSession:
items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 18.0, maxValue: 18.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) self.titleIconNode.isHidden = false
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.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))) if self.titleIconNode.image == nil {
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))) self.titleIconNode.image = generateImage(CGSize(width: 81.0, height: 52.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
items.append(AuthorizationLayoutItem(node: self.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
context.setFillColor(theme.list.itemPrimaryTextColor.cgColor)
context.setStrokeColor(theme.list.itemPrimaryTextColor.cgColor)
context.setLineWidth(2.97)
let _ = try? drawSvgPath(context, path: "M9.87179487,9.04664384 C9.05602951,9.04664384 8.39525641,9.70682916 8.39525641,10.5205479 L8.39525641,44.0547945 C8.39525641,44.8685133 9.05602951,45.5286986 9.87179487,45.5286986 L65.1538462,45.5286986 C65.9696115,45.5286986 66.6303846,44.8685133 66.6303846,44.0547945 L66.6303846,10.5205479 C66.6303846,9.70682916 65.9696115,9.04664384 65.1538462,9.04664384 L9.87179487,9.04664384 S ")
let _ = try? drawSvgPath(context, path: "M0,44.0547945 L75.025641,44.0547945 C75.025641,45.2017789 74.2153348,46.1893143 73.0896228,46.4142565 L66.1123641,47.8084669 C65.4749109,47.9358442 64.8264231,48 64.1763458,48 L10.8492952,48 C10.1992179,48 9.55073017,47.9358442 8.91327694,47.8084669 L1.93601826,46.4142565 C0.810306176,46.1893143 0,45.2017789 0,44.0547945 Z ")
let _ = try? drawSvgPath(context, path: "M2.96153846,16.4383562 L14.1495726,16.4383562 C15.7851852,16.4383562 17.1111111,17.7631027 17.1111111,19.3972603 L17.1111111,45.0410959 C17.1111111,46.6752535 15.7851852,48 14.1495726,48 L2.96153846,48 C1.32592593,48 0,46.6752535 0,45.0410959 L0,19.3972603 C0,17.7631027 1.32592593,16.4383562 2.96153846,16.4383562 Z ")
context.setStrokeColor(theme.list.plainBackgroundColor.cgColor)
context.setLineWidth(1.65)
let _ = try? drawSvgPath(context, path: "M2.96153846,15.6133562 L14.1495726,15.6133562 C16.2406558,15.6133562 17.9361111,17.3073033 17.9361111,19.3972603 L17.9361111,45.0410959 C17.9361111,47.1310529 16.2406558,48.825 14.1495726,48.825 L2.96153846,48.825 C0.870455286,48.825 -0.825,47.1310529 -0.825,45.0410959 L-0.825,19.3972603 C-0.825,17.3073033 0.870455286,15.6133562 2.96153846,15.6133562 S ")
context.setFillColor(theme.list.plainBackgroundColor.cgColor)
let _ = try? drawSvgPath(context, path: "M1.64529915,20.3835616 L15.465812,20.3835616 L15.465812,44.0547945 L1.64529915,44.0547945 Z ")
context.setFillColor(theme.list.itemAccentColor.cgColor)
let _ = try? drawSvgPath(context, path: "M66.4700855,0.0285884455 C60.7084674,0.0285884455 55.9687848,4.08259697 55.9687848,9.14830256 C55.9687848,12.0875991 57.5993165,14.6795278 60.0605723,16.3382966 C60.0568181,16.4358994 60.0611217,16.5884309 59.9318097,17.067302 C59.7721478,17.6586615 59.4575977,18.4958519 58.8015608,19.4258487 L58.3294314,20.083383 L59.1449275,20.0976772 C61.9723538,20.1099725 63.6110772,18.2528913 63.8662207,17.9535438 C64.7014993,18.1388449 65.5698144,18.2680167 66.4700855,18.2680167 C72.2312622,18.2680167 76.9713861,14.2140351 76.9713861,9.14830256 C76.9713861,4.08256999 72.2312622,0.0285884455 66.4700855,0.0285884455 Z ")
let _ = try? drawSvgPath(context, path: "M64.1551769,18.856071 C63.8258967,19.1859287 63.4214479,19.5187 62.9094963,19.840779 C61.8188563,20.5269227 60.5584776,20.9288319 59.1304689,20.9225505 L56.7413094,20.8806727 L57.6592902,19.6022014 L58.127415,18.9502938 C58.6361919,18.2290526 58.9525079,17.5293964 59.1353377,16.8522267 C59.1487516,16.8025521 59.1603548,16.7584153 59.1703974,16.7187893 C56.653362,14.849536 55.1437848,12.1128655 55.1437848,9.14830256 C55.1437848,3.61947515 60.2526259,-0.796411554 66.4700855,-0.796411554 C72.6872626,-0.796411554 77.7963861,3.61958236 77.7963861,9.14830256 C77.7963861,14.6770228 72.6872626,19.0930167 66.4700855,19.0930167 C65.7185957,19.0930167 64.9627196,19.0118067 64.1551769,18.856071 S ")
})
}
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.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
case .missedCall:
self.titleIconNode.isHidden = false
if self.titleIconNode.image == nil {
self.titleIconNode.image = generateImage(CGSize(width: 72.0, height: 72.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.list.itemAccentColor.cgColor)
let _ = try? drawSvgPath(context, path: "M42,10.5 C41.1716,10.5 40.5,11.1716 40.5,12 C40.5,12.8284 41.1716,13.5 42,13.5 L51.3787,13.5 L36,28.8787 L19.0607,11.9393 C18.4749,11.3536 17.5251,11.3536 16.9393,11.9393 C16.3536,12.5251 16.3536,13.4749 16.9393,14.0607 L34.9393,32.0607 C35.5251,32.6464 36.4749,32.6464 37.0607,32.0607 L53.5,15.6213 L53.5,25 C53.5,25.8284 54.1716,26.5 55,26.5 C55.8284,26.5 56.5,25.8284 56.5,25 L56.5,12 C56.5,11.1716 55.8284,10.5 55,10.5 L42,10.5 Z ")
context.setFillColor(theme.list.itemPrimaryTextColor.cgColor)
let _ = try? drawSvgPath(context, path: "M35.9832,37.4038 C46.3353,37.4066 56.7252,39.7842 62.0325,45.0915 C64.3893,47.4483 65.7444,50.3613 65.6897,53.8677 C65.6717,56.0012 64.9858,57.8376 63.8173,59.0061 C62.8158,60.0076 61.4987,60.5082 59.9403,60.248 L51.6994,58.3061 C49.2077,57.719 47.3333,55.6605 46.9816,53.1249 L46.264,47.9528 C46.2639,47.5446 46.1154,47.2478 45.8742,47.0065 C45.6515,46.7838 45.3175,46.6353 45.0206,46.5239 C43.3508,45.9298 39.7701,45.5763 35.9855,45.5753 C32.2194,45.5557 28.6389,45.9815 26.9694,46.5005 C26.6726,46.6117 26.3387,46.76 26.079,47.0197 C25.8194,47.2793 25.6525,47.5947 25.6526,48.0028 L24.9872,53.09 C24.6524,55.6494 22.7664,57.7335 20.253,58.3214 L11.8346,60.2905 C10.2949,60.5684 9.1074,60.0486 8.2166,59.1579 C6.9733,57.9145 6.3791,55.9107 6.3229,53.9628 C6.1921,50.4193 7.4343,47.5069 9.8639,45.0773 C15.1684,39.7728 25.6683,37.401 35.9832,37.4038 Z ")
})
}
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.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
default:
self.titleIconNode.isHidden = true
items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.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.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
}
} else { } else {
self.titleIconNode.isHidden = true self.titleIconNode.isHidden = true
items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.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.currentOptionNode, size: currentOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 10.0, maxValue: 10.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: 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.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
} }
@ -266,15 +395,21 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
} }
func activateInput() { func activateInput() {
self.codeField.textField.becomeFirstResponder() let _ = self.codeInputView.becomeFirstResponder()
//self.codeField.textField.becomeFirstResponder()
} }
func animateError() { func animateError() {
self.codeField.layer.addShakeAnimation() self.codeInputView.layer.addShakeAnimation()
//self.codeField.layer.addShakeAnimation()
} }
@objc func codeFieldTextChanged(_ textField: UITextField) { @objc func codeFieldTextChanged(_ textField: UITextField) {
self.updateNextEnabled?(!(textField.text ?? "").isEmpty) self.textChanged(text: textField.text ?? "")
}
private func textChanged(text: String) {
self.updateNextEnabled?(!text.isEmpty)
if let codeType = self.codeType { if let codeType = self.codeType {
var codeLength: Int32? var codeLength: Int32?
switch codeType { switch codeType {
@ -282,12 +417,14 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
codeLength = length codeLength = length
case let .otherSession(length): case let .otherSession(length):
codeLength = length codeLength = length
case let .missedCall(_, length):
codeLength = length
case let .sms(length): case let .sms(length):
codeLength = length codeLength = length
default: default:
break break
} }
if let codeLength = codeLength, let text = textField.text, text.count == Int(codeLength) { if let codeLength = codeLength, text.count == Int(codeLength) {
self.loginWithCode?(text) self.loginWithCode?(text)
} }
} }