mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Updated code input
This commit is contained in:
parent
313dca7e41
commit
42b5d07888
@ -144,7 +144,8 @@ public func layoutAuthorizationItems(bounds: CGRect, items: [AuthorizationLayout
|
||||
}
|
||||
|
||||
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!
|
||||
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
|
||||
|
@ -14,7 +14,11 @@ public func authorizationCurrentOptionText(_ type: SentAuthorizationCodeType, st
|
||||
let body = MarkdownAttributeSet(font: Font.regular(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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -909,7 +909,7 @@ private final class MonthComponent: CombinedComponent {
|
||||
if case .none = transition.animation {
|
||||
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.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)
|
||||
})
|
||||
|
21
submodules/CodeInputView/BUILD
Normal file
21
submodules/CodeInputView/BUILD
Normal 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",
|
||||
],
|
||||
)
|
293
submodules/CodeInputView/Sources/CodeInputView.swift
Normal file
293
submodules/CodeInputView/Sources/CodeInputView.swift
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
@ -148,7 +148,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) }
|
||||
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($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[-181407105] = { return Api.InputFile.parse_inputFile($0) }
|
||||
dict[-95482955] = { return Api.InputFile.parse_inputFileBig($0) }
|
||||
|
@ -1037,16 +1037,17 @@ public struct auth {
|
||||
|
||||
}
|
||||
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?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .authorization(let flags, let tmpSessions, let user):
|
||||
case .authorization(let flags, let otherwiseReloginDays, let tmpSessions, let user):
|
||||
if boxed {
|
||||
buffer.appendInt32(-855308010)
|
||||
buffer.appendInt32(872119224)
|
||||
}
|
||||
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)}
|
||||
user.serialize(buffer, true)
|
||||
break
|
||||
@ -1062,8 +1063,8 @@ public struct auth {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .authorization(let flags, let tmpSessions, let user):
|
||||
return ("authorization", [("flags", flags), ("tmpSessions", tmpSessions), ("user", user)])
|
||||
case .authorization(let flags, let otherwiseReloginDays, let tmpSessions, let user):
|
||||
return ("authorization", [("flags", flags), ("otherwiseReloginDays", otherwiseReloginDays), ("tmpSessions", tmpSessions), ("user", user)])
|
||||
case .authorizationSignUpRequired(let flags, let termsOfService):
|
||||
return ("authorizationSignUpRequired", [("flags", flags), ("termsOfService", termsOfService)])
|
||||
}
|
||||
@ -1073,16 +1074,19 @@ public struct auth {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() }
|
||||
var _3: Api.User?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() }
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
||||
var _4: Api.User?
|
||||
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 _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.auth.Authorization.authorization(flags: _1!, tmpSessions: _2, user: _3!)
|
||||
let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.auth.Authorization.authorization(flags: _1!, otherwiseReloginDays: _2, tmpSessions: _3, user: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -429,7 +429,25 @@ private func cleanupAccount(networkArguments: NetworkInitializationArguments, ac
|
||||
|> `catch` { _ -> Signal<Api.auth.LoggedOut?, NoError> in
|
||||
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))
|
||||
return accountManager.transaction { transaction -> Void in
|
||||
transaction.updateRecord(id, { _ in
|
||||
|
@ -24,12 +24,15 @@ public struct AccountManagerModifier<Types: AccountManagerTypes> {
|
||||
public let getNotice: (NoticeEntryKey) -> CodableEntry?
|
||||
public let setNotice: (NoticeEntryKey, CodableEntry?) -> Void
|
||||
public let clearNotices: () -> Void
|
||||
public let getStoredLoginTokens: () -> [Data]
|
||||
public let setStoredLoginTokens: ([Data]) -> Void
|
||||
}
|
||||
|
||||
final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
private let queue: Queue
|
||||
private let basePath: String
|
||||
private let atomicStatePath: String
|
||||
private let loginTokensPath: String
|
||||
private let temporarySessionId: Int64
|
||||
private let guardValueBox: ValueBox?
|
||||
private let valueBox: ValueBox
|
||||
@ -76,6 +79,7 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
self.queue = queue
|
||||
self.basePath = basePath
|
||||
self.atomicStatePath = "\(basePath)/atomic-state"
|
||||
self.loginTokensPath = "\(basePath)/login-tokens"
|
||||
self.temporarySessionId = temporarySessionId
|
||||
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 {
|
||||
@ -209,6 +213,10 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
self.currentUpdatedNoticeEntryKeys.insert(key)
|
||||
}, clearNotices: {
|
||||
self.noticeTable.clear()
|
||||
}, getStoredLoginTokens: {
|
||||
return self.getLoginTokens()
|
||||
}, setStoredLoginTokens: { list in
|
||||
self.setLoginTokens(list: list)
|
||||
})
|
||||
|
||||
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() {
|
||||
if self.currentAtomicStateUpdated {
|
||||
self.syncAtomicStateToFile()
|
||||
|
@ -72,51 +72,87 @@ 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> {
|
||||
return accountManager.transaction { transaction -> [Data] in
|
||||
return transaction.getStoredLoginTokens()
|
||||
}
|
||||
|> castError(AuthorizationCodeRequestError.self)
|
||||
|> mapToSignal { authTokens -> Signal<UnauthorizedAccount, AuthorizationCodeRequestError> in
|
||||
var flags: Int32 = 0
|
||||
flags |= 1 << 5 //allowMissedCall
|
||||
let sendCode = Api.functions.auth.sendCode(phoneNumber: phoneNumber, apiId: apiId, apiHash: apiHash, settings: .codeSettings(flags: flags, logoutTokens: nil))
|
||||
flags |= 1 << 6 //tokens
|
||||
let sendCode = Api.functions.auth.sendCode(phoneNumber: phoneNumber, apiId: apiId, apiHash: apiHash, settings: .codeSettings(flags: flags, logoutTokens: authTokens.map { Buffer(data: $0) }))
|
||||
|
||||
enum SendCodeResult {
|
||||
case password(hint: String?)
|
||||
case sentCode(Api.auth.SentCode)
|
||||
}
|
||||
|
||||
let codeAndAccount = account.network.request(sendCode, automaticFloodWait: false)
|
||||
|> map { result in
|
||||
return (result, account)
|
||||
|> map { result -> (SendCodeResult, UnauthorizedAccount) in
|
||||
return (.sentCode(result), account)
|
||||
}
|
||||
|> `catch` { error -> Signal<(Api.auth.SentCode, UnauthorizedAccount), MTRpcError> in
|
||||
|> `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<(Api.auth.SentCode, UnauthorizedAccount), MTRpcError> in
|
||||
|> mapToSignalPromotingError { updatedAccount -> Signal<(SendCodeResult, UnauthorizedAccount), MTRpcError> in
|
||||
return updatedAccount.network.request(sendCode, automaticFloodWait: false)
|
||||
|> map { sentCode in
|
||||
return (sentCode, updatedAccount)
|
||||
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 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))
|
||||
}
|
||||
}
|
||||
|> mapToSignal { result -> Signal<(SendCodeResult, UnauthorizedAccount), AuthorizationCodeRequestError> in
|
||||
switch result {
|
||||
case let .password(_, _, _, _, hint, _, _, _, _, _):
|
||||
return .single((.password(hint: hint), account))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .fail(.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
|
||||
|> 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)
|
||||
@ -124,12 +160,14 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func resendAuthorizationCode(account: UnauthorizedAccount) -> Signal<Void, AuthorizationCodeRequestError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, AuthorizationCodeRequestError> in
|
||||
@ -257,7 +295,7 @@ public func authorizeWithCode(accountManager: AccountManager<TelegramAccountMana
|
||||
return .single(.loggedIn)
|
||||
case let .authorization(authorization):
|
||||
switch authorization {
|
||||
case let .authorization(_, _, user):
|
||||
case let .authorization(_, _, _, user):
|
||||
let user = TelegramUser(user: user)
|
||||
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
|
||||
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
|
||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
switch result {
|
||||
case let .authorization(_, _, user):
|
||||
case let .authorization(_, _, _, user):
|
||||
let user = TelegramUser(user: user)
|
||||
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
|
||||
/*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> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
switch recoveredAccountData.authorization {
|
||||
case let .authorization(_, _, user):
|
||||
case let .authorization(_, _, _, user):
|
||||
let user = TelegramUser(user: user)
|
||||
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
|
||||
switch result {
|
||||
case let .authorization(_, _, user):
|
||||
case let .authorization(_, _, _, user):
|
||||
let user = TelegramUser(user: user)
|
||||
let appliedState = account.postbox.transaction { transaction -> Void in
|
||||
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
|
||||
|
@ -92,7 +92,7 @@ func _internal_exportAuthTransferToken(accountManager: AccountManager<TelegramAc
|
||||
switch result {
|
||||
case let .loginTokenSuccess(authorization):
|
||||
switch authorization {
|
||||
case let .authorization(_, _, user):
|
||||
case let .authorization(_, _, _, user):
|
||||
return updatedAccount.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
|
||||
let user = TelegramUser(user: user)
|
||||
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):
|
||||
switch authorization {
|
||||
case let .authorization(_, _, user):
|
||||
case let .authorization(_, _, _, user):
|
||||
return account.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
|
||||
let user = TelegramUser(user: user)
|
||||
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
|
||||
|
@ -246,6 +246,7 @@ swift_library(
|
||||
"//submodules/LottieMeshSwift:LottieMeshSwift",
|
||||
"//submodules/MeshAnimationCache:MeshAnimationCache",
|
||||
"//submodules/DirectMediaImageCache:DirectMediaImageCache",
|
||||
"//submodules/CodeInputView:CodeInputView",
|
||||
] + select({
|
||||
"@build_bazel_rules_apple//apple:ios_armv7": [],
|
||||
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
|
||||
|
@ -102,9 +102,10 @@ final class AuthorizationSequenceCodeEntryController: ViewController {
|
||||
func updateData(number: String, codeType: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, timeout: Int32?, termsOfService: (UnauthorizedAccountTermsOfService, Bool)?) {
|
||||
self.termsOfService = termsOfService
|
||||
if self.data?.0 != number || self.data?.1 != codeType || self.data?.2 != nextType || self.data?.3 != timeout {
|
||||
if case .otherSession = codeType {
|
||||
switch codeType {
|
||||
case .otherSession, .missedCall:
|
||||
self.title = number
|
||||
} else {
|
||||
default:
|
||||
self.title = nil
|
||||
}
|
||||
self.data = (number, codeType, nextType, timeout)
|
||||
|
@ -7,6 +7,7 @@ import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
import TextFormat
|
||||
import AuthorizationUI
|
||||
import CodeInputView
|
||||
|
||||
final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextFieldDelegate {
|
||||
private let strings: PresentationStrings
|
||||
@ -15,10 +16,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let titleIconNode: ASImageNode
|
||||
private let currentOptionNode: ASTextNode
|
||||
private let currentOptionInfoNode: ASTextNode
|
||||
private let nextOptionNode: HighlightableButtonNode
|
||||
|
||||
private let codeField: TextFieldNode
|
||||
private let codeSeparatorNode: ASDisplayNode
|
||||
private let codeInputView: CodeInputView
|
||||
//private let codeField: TextFieldNode
|
||||
//private let codeSeparatorNode: ASDisplayNode
|
||||
|
||||
private var codeType: SentAuthorizationCodeType?
|
||||
|
||||
@ -38,7 +41,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
}
|
||||
|
||||
var currentCode: String {
|
||||
return self.codeField.textField.text ?? ""
|
||||
return self.codeInputView.text
|
||||
//return self.codeField.textField.text ?? ""
|
||||
}
|
||||
|
||||
var loginWithCode: ((String) -> Void)?
|
||||
@ -48,7 +52,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
|
||||
var inProgress: Bool = false {
|
||||
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.displayWithoutProcessing = true
|
||||
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.isUserInteractionEnabled = false
|
||||
self.currentOptionNode.displaysAsynchronously = false
|
||||
|
||||
self.currentOptionInfoNode = ASTextNode()
|
||||
self.currentOptionInfoNode.isUserInteractionEnabled = false
|
||||
self.currentOptionInfoNode.displaysAsynchronously = false
|
||||
|
||||
self.nextOptionNode = HighlightableButtonNode()
|
||||
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)
|
||||
self.nextOptionNode.setAttributedTitle(nextOptionText, for: [])
|
||||
self.nextOptionNode.isUserInteractionEnabled = nextOptionActive
|
||||
|
||||
self.codeSeparatorNode = ASDisplayNode()
|
||||
/*self.codeSeparatorNode = ASDisplayNode()
|
||||
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.textAlignment = .center
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
@ -113,16 +100,14 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
} else {
|
||||
self.codeField.textField.keyboardType = .numberPad
|
||||
}
|
||||
#if swift(>=4.2)
|
||||
if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
|
||||
self.codeField.textField.textContentType = .oneTimeCode
|
||||
}
|
||||
#endif
|
||||
self.codeField.textField.returnKeyType = .done
|
||||
self.codeField.textField.textColor = self.theme.list.itemPrimaryTextColor
|
||||
self.codeField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
|
||||
self.codeField.textField.tintColor = self.theme.list.itemAccentColor
|
||||
self.codeField.textField.tintColor = self.theme.list.itemAccentColor*/
|
||||
|
||||
super.init()
|
||||
|
||||
@ -132,18 +117,26 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
|
||||
self.backgroundColor = self.theme.list.plainBackgroundColor
|
||||
|
||||
self.addSubnode(self.codeSeparatorNode)
|
||||
self.addSubnode(self.codeField)
|
||||
self.addSubnode(self.codeInputView)
|
||||
//self.addSubnode(self.codeSeparatorNode)
|
||||
//self.addSubnode(self.codeField)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.titleIconNode)
|
||||
self.addSubnode(self.currentOptionNode)
|
||||
self.addSubnode(self.currentOptionInfoNode)
|
||||
self.addSubnode(self.nextOptionNode)
|
||||
|
||||
self.codeField.textField.delegate = self
|
||||
self.codeField.textField.addTarget(self, action: #selector(self.codeFieldTextChanged(_:)), for: .editingChanged)
|
||||
self.codeInputView.updated = { [weak self] in
|
||||
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)
|
||||
}
|
||||
@ -153,8 +146,10 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
}
|
||||
|
||||
func updateCode(_ code: String) {
|
||||
self.codeField.textField.text = code
|
||||
self.codeFieldTextChanged(self.codeField.textField)
|
||||
self.codeInputView.text = code
|
||||
self.textChanged(text: code)
|
||||
//self.codeField.textField.text = code
|
||||
//self.codeFieldTextChanged(self.codeField.textField)
|
||||
if let codeType = self.codeType {
|
||||
var codeLength: Int32?
|
||||
switch codeType {
|
||||
@ -162,6 +157,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
codeLength = length
|
||||
case let .otherSession(length):
|
||||
codeLength = length
|
||||
case let .missedCall(_, length):
|
||||
codeLength = length
|
||||
case let .sms(length):
|
||||
codeLength = length
|
||||
default:
|
||||
@ -178,6 +175,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
self.phoneNumber = number
|
||||
|
||||
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 {
|
||||
self.currentTimeoutTime = timeout
|
||||
let disposable = ((Signal<Int, NoError>.single(1) |> delay(1.0, queue: Queue.mainQueue())) |> restart).start(next: { [weak self] _ in
|
||||
@ -218,13 +221,23 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
}
|
||||
|
||||
if max(layout.size.width, layout.size.height) > 1023.0 {
|
||||
if let codeType = self.codeType, case .otherSession = codeType {
|
||||
if let codeType = self.codeType {
|
||||
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 {
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.phoneNumber, font: Font.light(40.0), textColor: self.theme.list.itemPrimaryTextColor)
|
||||
}
|
||||
} else {
|
||||
if let codeType = self.codeType, case .otherSession = codeType {
|
||||
if let codeType = self.codeType {
|
||||
switch codeType {
|
||||
case .otherSession:
|
||||
let fontSize: CGFloat
|
||||
if layout.size.width > 330.0 {
|
||||
fontSize = 22.0
|
||||
@ -232,6 +245,18 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
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 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 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] = []
|
||||
if let codeType = self.codeType, case .otherSession = codeType {
|
||||
if let codeType = self.codeType {
|
||||
switch codeType {
|
||||
case .otherSession:
|
||||
self.titleIconNode.isHidden = false
|
||||
|
||||
if self.titleIconNode.image == nil {
|
||||
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 ")
|
||||
})
|
||||
}
|
||||
|
||||
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.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)))
|
||||
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 {
|
||||
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.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)))
|
||||
}
|
||||
@ -266,15 +395,21 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
}
|
||||
|
||||
func activateInput() {
|
||||
self.codeField.textField.becomeFirstResponder()
|
||||
let _ = self.codeInputView.becomeFirstResponder()
|
||||
//self.codeField.textField.becomeFirstResponder()
|
||||
}
|
||||
|
||||
func animateError() {
|
||||
self.codeField.layer.addShakeAnimation()
|
||||
self.codeInputView.layer.addShakeAnimation()
|
||||
//self.codeField.layer.addShakeAnimation()
|
||||
}
|
||||
|
||||
@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 {
|
||||
var codeLength: Int32?
|
||||
switch codeType {
|
||||
@ -282,12 +417,14 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
codeLength = length
|
||||
case let .otherSession(length):
|
||||
codeLength = length
|
||||
case let .missedCall(_, length):
|
||||
codeLength = length
|
||||
case let .sms(length):
|
||||
codeLength = length
|
||||
default:
|
||||
break
|
||||
}
|
||||
if let codeLength = codeLength, let text = textField.text, text.count == Int(codeLength) {
|
||||
if let codeLength = codeLength, text.count == Int(codeLength) {
|
||||
self.loginWithCode?(text)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user