Authorization improvements

This commit is contained in:
Ilya Laktyushin 2022-08-17 15:20:25 +03:00
parent b5737f0eea
commit 27272d8ea9
9 changed files with 328 additions and 104 deletions

View File

@ -14,7 +14,8 @@ public struct AuthorizationLayoutItemSpacing {
} }
public struct AuthorizationLayoutItem { public struct AuthorizationLayoutItem {
public var node: ASDisplayNode public var node: ASDisplayNode?
public var view: UIView?
public var size: CGSize public var size: CGSize
public var spacingBefore: AuthorizationLayoutItemSpacing public var spacingBefore: AuthorizationLayoutItemSpacing
public var spacingAfter: AuthorizationLayoutItemSpacing public var spacingAfter: AuthorizationLayoutItemSpacing
@ -25,6 +26,14 @@ public struct AuthorizationLayoutItem {
self.spacingBefore = spacingBefore self.spacingBefore = spacingBefore
self.spacingAfter = spacingAfter self.spacingAfter = spacingAfter
} }
public init(view: UIView, size: CGSize, spacingBefore: AuthorizationLayoutItemSpacing, spacingAfter: AuthorizationLayoutItemSpacing) {
self.view = view
self.size = size
self.spacingBefore = spacingBefore
self.spacingAfter = spacingAfter
}
} }
public final class SolvedAuthorizationLayoutItem { public final class SolvedAuthorizationLayoutItem {
@ -147,7 +156,12 @@ public func layoutAuthorizationItems(bounds: CGRect, items: [AuthorizationLayout
for i in 0 ..< solvedItems.count { for i in 0 ..< solvedItems.count {
let item = solvedItems[i] 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)) let itemFrame = CGRect(origin: CGPoint(x: floor((bounds.size.width - item.item.size.width) / 2.0), y: verticalOrigin), size: item.item.size)
if let view = item.item.view {
transition.updateFrame(view: view, frame: itemFrame)
} else if let node = item.item.node {
transition.updateFrame(node: node, frame: itemFrame)
}
verticalOrigin += item.item.size.height verticalOrigin += item.item.size.height
verticalOrigin += item.spacingAfter! verticalOrigin += item.spacingAfter!
} }

View File

@ -364,7 +364,7 @@ public func sendLoginEmailCode(account: UnauthorizedAccount, email: String) -> S
|> ignoreValues |> ignoreValues
} }
public func verifyLoginEmail(account: UnauthorizedAccount, code: AuthorizationCode.EmailVerification) -> Signal<Never, AuthorizationEmailVerificationError> { public func verifyLoginEmailSetup(account: UnauthorizedAccount, code: AuthorizationCode.EmailVerification) -> Signal<Never, AuthorizationEmailVerificationError> {
return account.postbox.transaction { transaction -> Signal<Never, AuthorizationEmailVerificationError> in return account.postbox.transaction { transaction -> Signal<Never, AuthorizationEmailVerificationError> in
if let state = transaction.getState() as? UnauthorizedAccountState { if let state = transaction.getState() as? UnauthorizedAccountState {
switch state.contents { switch state.contents {

View File

@ -16,6 +16,8 @@ final class AuthorizationSequenceCodeEntryController: ViewController {
private let openUrl: (String) -> Void private let openUrl: (String) -> Void
var loginWithCode: ((String) -> Void)? var loginWithCode: ((String) -> Void)?
var signInWithApple: (() -> Void)?
var reset: (() -> Void)? var reset: (() -> Void)?
var requestNextOption: (() -> Void)? var requestNextOption: (() -> Void)?
@ -24,6 +26,8 @@ final class AuthorizationSequenceCodeEntryController: ViewController {
private let hapticFeedback = HapticFeedback() private let hapticFeedback = HapticFeedback()
private var appleSignInAllowed = false
var inProgress: Bool = false { var inProgress: Bool = false {
didSet { didSet {
if self.inProgress { if self.inProgress {
@ -76,6 +80,10 @@ final class AuthorizationSequenceCodeEntryController: ViewController {
self?.continueWithCode(code) self?.continueWithCode(code)
} }
self.controllerNode.signInWithApple = { [weak self] in
self?.signInWithApple?()
}
self.controllerNode.requestNextOption = { [weak self] in self.controllerNode.requestNextOption = { [weak self] in
self?.requestNextOption?() self?.requestNextOption?()
} }
@ -89,7 +97,11 @@ final class AuthorizationSequenceCodeEntryController: ViewController {
} }
if let (number, codeType, nextType, timeout) = self.data { if let (number, codeType, nextType, timeout) = self.data {
self.controllerNode.updateData(number: number, codeType: codeType, nextType: nextType, timeout: timeout) var appleSignInAllowed = false
if case let .email(_, _, _, appleSignInAllowedValue, _) = codeType {
appleSignInAllowed = appleSignInAllowedValue
}
self.controllerNode.updateData(number: number, codeType: codeType, nextType: nextType, timeout: timeout, appleSignInAllowed: appleSignInAllowed)
} }
} }
@ -113,8 +125,14 @@ final class AuthorizationSequenceCodeEntryController: ViewController {
self.title = nil self.title = nil
} }
self.data = (number, codeType, nextType, timeout) self.data = (number, codeType, nextType, timeout)
var appleSignInAllowed = false
if case let .email(_, _, _, appleSignInAllowedValue, _) = codeType {
appleSignInAllowed = appleSignInAllowedValue
}
if self.isNodeLoaded { if self.isNodeLoaded {
self.controllerNode.updateData(number: number, codeType: codeType, nextType: nextType, timeout: timeout) self.controllerNode.updateData(number: number, codeType: codeType, nextType: nextType, timeout: timeout, appleSignInAllowed: appleSignInAllowed)
self.requestLayout(transition: .immediate) self.requestLayout(transition: .immediate)
} }
} }

View File

@ -7,6 +7,7 @@ import SwiftSignalKit
import TelegramPresentationData import TelegramPresentationData
import TextFormat import TextFormat
import AuthorizationUI import AuthorizationUI
import AuthenticationServices
import CodeInputView import CodeInputView
import PhoneNumberFormat import PhoneNumberFormat
import AnimatedStickerNode import AnimatedStickerNode
@ -25,6 +26,9 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
private let nextOptionTitleNode: ImmediateTextNode private let nextOptionTitleNode: ImmediateTextNode
private let nextOptionButtonNode: HighlightableButtonNode private let nextOptionButtonNode: HighlightableButtonNode
private let dividerNode: AuthorizationDividerNode
private var signInWithAppleButton: UIControl?
private let codeInputView: CodeInputView private let codeInputView: CodeInputView
private var codeType: SentAuthorizationCodeType? private var codeType: SentAuthorizationCodeType?
@ -34,6 +38,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
private var layoutArguments: (ContainerViewLayout, CGFloat)? private var layoutArguments: (ContainerViewLayout, CGFloat)?
private var appleSignInAllowed = false
var phoneNumber: String = "" { var phoneNumber: String = "" {
didSet { didSet {
if self.phoneNumber != oldValue { if self.phoneNumber != oldValue {
@ -49,6 +55,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
} }
var loginWithCode: ((String) -> Void)? var loginWithCode: ((String) -> Void)?
var signInWithApple: (() -> Void)?
var requestNextOption: (() -> Void)? var requestNextOption: (() -> Void)?
var requestAnotherOption: (() -> Void)? var requestAnotherOption: (() -> Void)?
var updateNextEnabled: ((Bool) -> Void)? var updateNextEnabled: ((Bool) -> Void)?
@ -106,6 +114,13 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.codeInputView.textField.keyboardType = .numberPad self.codeInputView.textField.keyboardType = .numberPad
} }
self.dividerNode = AuthorizationDividerNode(theme: self.theme, strings: self.strings)
if #available(iOS 13.0, *) {
self.signInWithAppleButton = ASAuthorizationAppleIDButton(authorizationButtonType: .signIn, authorizationButtonStyle: theme.overallDarkAppearance ? .white : .black)
(self.signInWithAppleButton as? ASAuthorizationAppleIDButton)?.cornerRadius = 11
}
/*self.codeField = TextFieldNode() /*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
@ -140,6 +155,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.addSubnode(self.currentOptionInfoNode) self.addSubnode(self.currentOptionInfoNode)
self.addSubnode(self.nextOptionButtonNode) self.addSubnode(self.nextOptionButtonNode)
self.addSubnode(self.animationNode) self.addSubnode(self.animationNode)
self.addSubnode(self.dividerNode)
self.codeInputView.updated = { [weak self] in self.codeInputView.updated = { [weak self] in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -154,12 +170,21 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
//self.codeField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_Code, font: Font.regular(24.0), textColor: self.theme.list.itemPlaceholderTextColor) //self.codeField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_Code, font: Font.regular(24.0), textColor: self.theme.list.itemPlaceholderTextColor)
self.nextOptionButtonNode.addTarget(self, action: #selector(self.nextOptionNodePressed), forControlEvents: .touchUpInside) self.nextOptionButtonNode.addTarget(self, action: #selector(self.nextOptionNodePressed), forControlEvents: .touchUpInside)
self.signInWithAppleButton?.addTarget(self, action: #selector(self.signInWithApplePressed), for: .touchUpInside)
} }
deinit { deinit {
self.countdownDisposable.dispose() self.countdownDisposable.dispose()
} }
override func didLoad() {
super.didLoad()
if let signInWithAppleButton = self.signInWithAppleButton {
self.view.addSubview(signInWithAppleButton)
}
}
func updateCode(_ code: String) { func updateCode(_ code: String) {
self.codeInputView.text = code self.codeInputView.text = code
self.textChanged(text: code) self.textChanged(text: code)
@ -189,10 +214,17 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
self.codeInputView.text = "" self.codeInputView.text = ""
} }
func updateData(number: String, codeType: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, timeout: Int32?) { func updateData(number: String, codeType: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, timeout: Int32?, appleSignInAllowed: Bool) {
self.codeType = codeType self.codeType = codeType
self.phoneNumber = number self.phoneNumber = number
var appleSignInAllowed = appleSignInAllowed
if #available(iOS 13.0, *) {
} else {
appleSignInAllowed = false
}
self.appleSignInAllowed = appleSignInAllowed
self.currentOptionNode.attributedText = authorizationCurrentOptionText(codeType, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor) self.currentOptionNode.attributedText = authorizationCurrentOptionText(codeType, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor)
if case .missedCall = codeType { if case .missedCall = codeType {
self.currentOptionInfoNode.attributedText = NSAttributedString(string: self.strings.Login_CodePhonePatternInfoText, font: Font.regular(16.0), textColor: self.theme.list.itemPrimaryTextColor, paragraphAlignment: .center) self.currentOptionInfoNode.attributedText = NSAttributedString(string: self.strings.Login_CodePhonePatternInfoText, font: Font.regular(16.0), textColor: self.theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
@ -395,8 +427,22 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
/*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.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.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)))*/
if self.appleSignInAllowed, let signInWithAppleButton = self.signInWithAppleButton {
self.nextOptionButtonNode.isHidden = true
signInWithAppleButton.isHidden = false
let dividerSize = self.dividerNode.updateLayout(width: layout.size.width)
items.append(AuthorizationLayoutItem(node: self.dividerNode, size: dividerSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
let buttonSize = CGSize(width: layout.size.width - 48.0, height: 50.0)
items.append(AuthorizationLayoutItem(view: signInWithAppleButton, size: buttonSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 10.0, maxValue: 10.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
} else {
self.signInWithAppleButton?.isHidden = true
self.dividerNode.isHidden = true
self.nextOptionButtonNode.isHidden = false
items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, 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)))
@ -476,4 +522,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
@objc func nextOptionNodePressed() { @objc func nextOptionNodePressed() {
self.requestAnotherOption?() self.requestAnotherOption?()
} }
@objc func signInWithApplePressed() {
self.signInWithApple?()
}
} }

View File

@ -294,7 +294,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
} }
if case let .email(_, _, _, _, setup) = type, setup, case let .emailVerification(emailCode) = authorizationCode { if case let .email(_, _, _, _, setup) = type, setup, case let .emailVerification(emailCode) = authorizationCode {
strongSelf.actionDisposable.set(((verifyLoginEmail(account: strongSelf.account, code: emailCode)) strongSelf.actionDisposable.set(((verifyLoginEmailSetup(account: strongSelf.account, code: emailCode))
|> deliverOnMainQueue).start(error: { error in |> deliverOnMainQueue).start(error: { error in
Queue.mainQueue().async { Queue.mainQueue().async {
if let strongSelf = self, let controller = controller { if let strongSelf = self, let controller = controller {
@ -475,10 +475,28 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).start() let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).start()
} }
} }
controller.signInWithApple = { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.signInWithAppleSetup = false
if #available(iOS 13.0, *) {
let appleIdProvider = ASAuthorizationAppleIDProvider()
let request = appleIdProvider.createRequest()
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = strongSelf
authorizationController.presentationContextProvider = strongSelf
authorizationController.performRequests()
}
}
controller.updateData(number: formatPhoneNumber(number), codeType: type, nextType: nextType, timeout: timeout, termsOfService: termsOfService) controller.updateData(number: formatPhoneNumber(number), codeType: type, nextType: nextType, timeout: timeout, termsOfService: termsOfService)
return controller return controller
} }
private var signInWithAppleSetup = false
private func emailSetupController(appleSignInAllowed: Bool) -> AuthorizationSequenceEmailEntryController { private func emailSetupController(appleSignInAllowed: Bool) -> AuthorizationSequenceEmailEntryController {
var currentController: AuthorizationSequenceEmailEntryController? var currentController: AuthorizationSequenceEmailEntryController?
for c in self.viewControllers { for c in self.viewControllers {
@ -533,6 +551,8 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
return return
} }
strongSelf.signInWithAppleSetup = true
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
let appleIdProvider = ASAuthorizationAppleIDProvider() let appleIdProvider = ASAuthorizationAppleIDProvider()
let request = appleIdProvider.createRequest() let request = appleIdProvider.createRequest()
@ -559,8 +579,9 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
return return
} }
self.actionDisposable.set((verifyLoginEmail(account: self.account, code: .appleToken(token)) if self.signInWithAppleSetup {
|> deliverOnMainQueue).start(error: { [weak self] error in self.actionDisposable.set((verifyLoginEmailSetup(account: self.account, code: .appleToken(token))
|> deliverOnMainQueue).start(error: { [weak self, weak lastController] error in
if let strongSelf = self, let lastController = lastController { if let strongSelf = self, let lastController = lastController {
let text: String let text: String
switch error { switch error {
@ -576,6 +597,49 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
lastController.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) lastController.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
} }
})) }))
} else {
self.actionDisposable.set(
authorizeWithCode(accountManager: self.sharedContext.accountManager, account: self.account, code: .emailVerification(.appleToken(token)), termsOfService: nil, forcedPasswordSetupNotice: { value in
guard let entry = CodableEntry(ApplicationSpecificCounterNotice(value: value)) else {
return nil
}
return (ApplicationSpecificNotice.forcedPasswordSetupKey(), entry)
}).start(next: { [weak self] result in
guard let strongSelf = self else {
return
}
// lastController?.inProgress = false
switch result {
case let .signUp(data):
let _ = beginSignUp(account: strongSelf.account, data: data).start()
case .loggedIn:
break
}
}, error: { [weak self, weak lastController] error in
Queue.mainQueue().async {
if let strongSelf = self, let lastController = lastController {
// controller.inProgress = false
let text: String
switch error {
case .limitExceeded:
text = strongSelf.presentationData.strings.Login_CodeFloodError
case .invalidCode:
text = strongSelf.presentationData.strings.Login_InvalidCodeError
case .generic:
text = strongSelf.presentationData.strings.Login_UnknownError
case .codeExpired:
text = strongSelf.presentationData.strings.Login_CodeExpired
let account = strongSelf.account
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty)).start()
}
lastController.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
}
})
)
}
default: default:
break break
} }

View File

@ -9,6 +9,44 @@ import AnimatedStickerNode
import TelegramAnimatedStickerNode import TelegramAnimatedStickerNode
import SolidRoundedButtonNode import SolidRoundedButtonNode
final class AuthorizationDividerNode: ASDisplayNode {
private let titleNode: ImmediateTextNode
private let leftLineNode: ASDisplayNode
private let rightLineNode: ASDisplayNode
init(theme: PresentationTheme, strings: PresentationStrings) {
self.titleNode = ImmediateTextNode()
self.titleNode.maximumNumberOfLines = 1
self.titleNode.attributedText = NSAttributedString(string: "or", font: Font.regular(17.0), textColor: theme.list.itemSecondaryTextColor)
self.leftLineNode = ASDisplayNode()
self.leftLineNode.backgroundColor = theme.list.itemSecondaryTextColor
self.rightLineNode = ASDisplayNode()
self.rightLineNode.backgroundColor = theme.list.itemSecondaryTextColor
super.init()
self.addSubnode(self.titleNode)
self.addSubnode(self.leftLineNode)
self.addSubnode(self.rightLineNode)
}
func updateLayout(width: CGFloat) -> CGSize {
let lineSize = CGSize(width: 33.0, height: UIScreenPixel)
let spacing: CGFloat = 7.0
let titleSize = self.titleNode.updateLayout(CGSize(width: width - (lineSize.width + spacing) * 2.0, height: .greatestFiniteMagnitude))
let height: CGFloat = 40.0
let titleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - lineSize.width) / 2.0), y: floor((height - titleSize.height) / 2.0)), size: titleSize)
self.titleNode.frame = titleFrame
self.leftLineNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX - spacing - lineSize.width, y: floorToScreenPixels(height / 2.0)), size: lineSize)
self.rightLineNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + spacing, y: floorToScreenPixels(height / 2.0)), size: lineSize)
return CGSize(width: width, height: height)
}
}
final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UITextFieldDelegate { final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UITextFieldDelegate {
private let strings: PresentationStrings private let strings: PresentationStrings
private let theme: PresentationTheme private let theme: PresentationTheme
@ -17,6 +55,7 @@ final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UIText
private let titleNode: ASTextNode private let titleNode: ASTextNode
private let noticeNode: ASTextNode private let noticeNode: ASTextNode
private let dividerNode: AuthorizationDividerNode
private var signInWithAppleButton: UIControl? private var signInWithAppleButton: UIControl?
private let proceedNode: SolidRoundedButtonNode private let proceedNode: SolidRoundedButtonNode
@ -82,6 +121,8 @@ final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UIText
self.codeField.textField.tintColor = self.theme.list.itemAccentColor self.codeField.textField.tintColor = self.theme.list.itemAccentColor
self.codeField.textField.placeholder = "Enter Your Email" self.codeField.textField.placeholder = "Enter Your Email"
self.dividerNode = AuthorizationDividerNode(theme: self.theme, strings: self.strings)
super.init() super.init()
self.setViewBlock({ self.setViewBlock({
@ -98,6 +139,7 @@ final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UIText
self.addSubnode(self.proceedNode) self.addSubnode(self.proceedNode)
self.addSubnode(self.noticeNode) self.addSubnode(self.noticeNode)
self.addSubnode(self.animationNode) self.addSubnode(self.animationNode)
self.addSubnode(self.dividerNode)
self.codeField.textField.addTarget(self, action: #selector(self.textDidChange), for: .editingChanged) self.codeField.textField.addTarget(self, action: #selector(self.textDidChange), for: .editingChanged)
self.proceedNode.pressed = { [weak self] in self.proceedNode.pressed = { [weak self] in
@ -169,17 +211,23 @@ final class AuthorizationSequenceEmailEntryControllerNode: ASDisplayNode, UIText
items.append(AuthorizationLayoutItem(node: self.codeField, size: CGSize(width: layout.size.width - 88.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 32.0, maxValue: 60.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: 32.0, maxValue: 60.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 48.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 48.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.proceedNode, size: proceedSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 48.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) if let _ = self.signInWithAppleButton, self.appleSignInAllowed {
self.dividerNode.isHidden = false
let dividerSize = self.dividerNode.updateLayout(width: layout.size.width)
items.append(AuthorizationLayoutItem(node: self.dividerNode, size: dividerSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 48.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
} else {
self.dividerNode.isHidden = true
}
items.append(AuthorizationLayoutItem(node: self.proceedNode, size: proceedSize, spacingBefore: self.dividerNode.isHidden ? AuthorizationLayoutItemSpacing(weight: 48.0, maxValue: 100.0) : AuthorizationLayoutItemSpacing(weight: 10.0, maxValue: 10.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 20.0)), items: items, transition: transition, failIfDoesNotFit: false) let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 20.0)), items: items, transition: transition, failIfDoesNotFit: false)
if let signInWithAppleButton = self.signInWithAppleButton { if let signInWithAppleButton = self.signInWithAppleButton, self.appleSignInAllowed {
if self.appleSignInAllowed {
signInWithAppleButton.isHidden = false signInWithAppleButton.isHidden = false
transition.updateFrame(view: signInWithAppleButton, frame: self.proceedNode.frame) transition.updateFrame(view: signInWithAppleButton, frame: self.proceedNode.frame)
} else { } else {
signInWithAppleButton.isHidden = true self.signInWithAppleButton?.isHidden = true
}
} }
} }

View File

@ -235,8 +235,6 @@ private final class ContactSyncNode: ASDisplayNode {
} }
} }
final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode { final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
private let sharedContext: SharedAccountContext private let sharedContext: SharedAccountContext
private var account: UnauthorizedAccount private var account: UnauthorizedAccount

View File

@ -50,7 +50,7 @@ final class AuthorizationSequenceSignUpController: ViewController {
self.statusBar.statusBarStyle = presentationData.theme.intro.statusBarStyle.style self.statusBar.statusBarStyle = presentationData.theme.intro.statusBarStyle.style
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed)) // self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
self.attemptNavigation = { _ in self.attemptNavigation = { _ in
return false return false

View File

@ -5,6 +5,8 @@ import Display
import TelegramPresentationData import TelegramPresentationData
import TextFormat import TextFormat
import Markdown import Markdown
import AuthorizationUI
import SolidRoundedButtonNode
private func roundCorners(diameter: CGFloat) -> UIImage { private func roundCorners(diameter: CGFloat) -> UIImage {
UIGraphicsBeginImageContextWithOptions(CGSize(width: diameter, height: diameter), false, 0.0) UIGraphicsBeginImageContextWithOptions(CGSize(width: diameter, height: diameter), false, 0.0)
@ -34,6 +36,7 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
private let lastSeparatorNode: ASDisplayNode private let lastSeparatorNode: ASDisplayNode
private let currentPhotoNode: ASImageNode private let currentPhotoNode: ASImageNode
private let addPhotoButton: HighlightableButtonNode private let addPhotoButton: HighlightableButtonNode
private let proceedNode: SolidRoundedButtonNode
private var layoutArguments: (ContainerViewLayout, CGFloat)? private var layoutArguments: (ContainerViewLayout, CGFloat)?
@ -75,20 +78,20 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
self.titleNode = ASTextNode() self.titleNode = ASTextNode()
self.titleNode.isUserInteractionEnabled = false self.titleNode.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = false self.titleNode.displaysAsynchronously = false
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_InfoTitle, font: Font.light(30.0), textColor: theme.list.itemPrimaryTextColor) self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_InfoTitle, font: Font.semibold(28.0), textColor: theme.list.itemPrimaryTextColor)
self.currentOptionNode = ASTextNode() self.currentOptionNode = ASTextNode()
self.currentOptionNode.isUserInteractionEnabled = false self.currentOptionNode.isUserInteractionEnabled = false
self.currentOptionNode.displaysAsynchronously = false self.currentOptionNode.displaysAsynchronously = false
self.currentOptionNode.attributedText = NSAttributedString(string: self.strings.Login_InfoHelp, font: Font.regular(16.0), textColor: theme.list.itemPlaceholderTextColor, paragraphAlignment: .center) self.currentOptionNode.attributedText = NSAttributedString(string: self.strings.Login_InfoHelp, font: Font.regular(16.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
self.termsNode = ImmediateTextNode() self.termsNode = ImmediateTextNode()
self.termsNode.textAlignment = .center self.termsNode.textAlignment = .center
self.termsNode.maximumNumberOfLines = 0 self.termsNode.maximumNumberOfLines = 0
self.termsNode.displaysAsynchronously = false self.termsNode.displaysAsynchronously = false
let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: theme.list.itemPrimaryTextColor) let body = MarkdownAttributeSet(font: Font.regular(13.0), textColor: theme.list.itemSecondaryTextColor)
let link = MarkdownAttributeSet(font: Font.regular(16.0), textColor: theme.list.itemAccentColor, additionalAttributes: [TelegramTextAttributes.URL: ""]) let link = MarkdownAttributeSet(font: Font.regular(13.0), textColor: theme.list.itemAccentColor, additionalAttributes: [TelegramTextAttributes.URL: ""])
self.termsNode.attributedText = parseMarkdownIntoAttributedString(strings.Login_TermsOfServiceLabel.replacingOccurrences(of: "]", with: "]()"), attributes: MarkdownAttributes(body: body, bold: body, link: link, linkAttribute: { _ in nil }), textAlignment: .center) self.termsNode.attributedText = parseMarkdownIntoAttributedString(strings.Login_TermsOfServiceLabel.replacingOccurrences(of: "\n", with: " ").replacingOccurrences(of: "]", with: "]()"), attributes: MarkdownAttributes(body: body, bold: body, link: link, linkAttribute: { _ in nil }), textAlignment: .center)
self.firstSeparatorNode = ASDisplayNode() self.firstSeparatorNode = ASDisplayNode()
self.firstSeparatorNode.isLayerBacked = true self.firstSeparatorNode.isLayerBacked = true
@ -132,12 +135,14 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
self.currentPhotoNode.displayWithoutProcessing = true self.currentPhotoNode.displayWithoutProcessing = true
self.addPhotoButton = HighlightableButtonNode() self.addPhotoButton = HighlightableButtonNode()
self.addPhotoButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIconLarge"), color: self.theme.list.itemPlaceholderTextColor), for: .normal) self.addPhotoButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIconLarge"), color: self.theme.list.itemAccentColor), for: .normal)
self.addPhotoButton.setBackgroundImage(generateCircleImage(diameter: 110.0, lineWidth: 1.0, color: self.theme.list.itemPlaceholderTextColor), for: .normal) self.addPhotoButton.setBackgroundImage(generateFilledCircleImage(diameter: 110.0, color: self.theme.list.itemAccentColor.withAlphaComponent(0.1), strokeColor: nil, strokeWidth: nil, backgroundColor: nil), for: .normal)
self.addPhotoButton.addSubnode(self.currentPhotoNode) self.addPhotoButton.addSubnode(self.currentPhotoNode)
self.addPhotoButton.allowsGroupOpacity = true self.addPhotoButton.allowsGroupOpacity = true
self.proceedNode = SolidRoundedButtonNode(title: "Continue", theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
super.init() super.init()
self.setViewBlock({ self.setViewBlock({
@ -158,6 +163,7 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
self.addSubnode(self.termsNode) self.addSubnode(self.termsNode)
self.termsNode.isHidden = true self.termsNode.isHidden = true
self.addSubnode(self.addPhotoButton) self.addSubnode(self.addPhotoButton)
self.addSubnode(self.proceedNode)
self.addPhotoButton.addTarget(self, action: #selector(self.addPhotoPressed), forControlEvents: .touchUpInside) self.addPhotoButton.addTarget(self, action: #selector(self.addPhotoPressed), forControlEvents: .touchUpInside)
@ -174,6 +180,13 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
self?.openTermsOfService?() self?.openTermsOfService?()
} }
} }
self.proceedNode.pressed = { [weak self] in
if let strongSelf = self {
let name = strongSelf.currentName
strongSelf.signUpWithName?(name.0, name.1)
}
}
} }
func updateData(firstName: String, lastName: String, hasTermsOfService: Bool) { func updateData(firstName: String, lastName: String, hasTermsOfService: Bool) {
@ -194,90 +207,109 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
insets.bottom += max(inputHeight, layout.standardInputHeight) insets.bottom += max(inputHeight, layout.standardInputHeight)
} }
let availableHeight = max(1.0, layout.size.height - insets.top - insets.bottom) self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_InfoTitle, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
if max(layout.size.width, layout.size.height) > 1023.0 {
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_InfoTitle, font: Font.light(40.0), textColor: self.theme.list.itemPrimaryTextColor)
} else {
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_InfoTitle, font: Font.light(30.0), textColor: self.theme.list.itemPrimaryTextColor)
}
let titleSize = self.titleNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude)) let titleSize = self.titleNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let additionalTitleSpacing: CGFloat
if titleSize.width > layout.size.width - 160.0 {
additionalTitleSpacing = 44.0
} else {
additionalTitleSpacing = 0.0
}
let minimalTitleSpacing: CGFloat = 10.0 // let additionalTitleSpacing: CGFloat
let maxTitleSpacing: CGFloat = 22.0 // if titleSize.width > layout.size.width - 160.0 {
let fieldHeight: CGFloat = 57.0 // additionalTitleSpacing = 44.0
let inputFieldsHeight: CGFloat = fieldHeight * 2.0 // } else {
let leftInset: CGFloat = 130.0 // additionalTitleSpacing = 0.0
// }
let minimalNoticeSpacing: CGFloat = 11.0 let fieldHeight: CGFloat = 54.0
let maxNoticeSpacing: CGFloat = 35.0
let sideInset: CGFloat = 24.0
let innerInset: CGFloat = 16.0
// let minimalNoticeSpacing: CGFloat = 11.0
// let maxNoticeSpacing: CGFloat = 35.0
let noticeSize = self.currentOptionNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude)) let noticeSize = self.currentOptionNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude))
let termsSize = self.termsNode.updateLayout(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude)) let termsSize = self.termsNode.updateLayout(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude))
//
// let noticeHeight: CGFloat = noticeSize.height + (self.termsNode.isHidden ? 0.0 : (termsSize.height + 4.0))
//
// let minimalTermsOfServiceSpacing: CGFloat = 6.0
// let maxTermsOfServiceSpacing: CGFloat = 20.0
// let minTrailingSpacing: CGFloat = 10.0
//
// let inputHeight = inputFieldsHeight
// let essentialHeight = additionalTitleSpacing + titleSize.height + minimalTitleSpacing + inputHeight + minimalNoticeSpacing + noticeHeight
// let additionalHeight = minimalTermsOfServiceSpacing + minTrailingSpacing
//
// let navigationHeight: CGFloat
// if essentialHeight + additionalHeight > availableHeight || availableHeight * 0.66 - inputHeight < additionalHeight {
// navigationHeight = min(floor(availableHeight * 0.3), availableHeight - inputFieldsHeight)
// } else {
// navigationHeight = floor(availableHeight * 0.3)
// }
//
// let titleOffset: CGFloat
// if navigationHeight * 0.5 < titleSize.height + minimalTitleSpacing {
// titleOffset = max(navigationBarHeight, floor((navigationHeight - titleSize.height) / 2.0))
// } else {
// titleOffset = max(navigationBarHeight, max(navigationHeight * 0.5, navigationHeight - maxTitleSpacing - titleSize.height))
// }
// transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - titleSize.width) / 2.0), y: titleOffset), size: titleSize))
//
// let avatarSize: CGSize = CGSize(width: 110.0, height: 110.0)
// let addPhotoButtonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - avatarSize.width) / 2.0), y: navigationHeight + 10.0), size: avatarSize)
// transition.updateFrame(node: self.addPhotoButton, frame: addPhotoButtonFrame)
// self.currentPhotoNode.frame = CGRect(origin: CGPoint(), size: addPhotoButtonFrame.size)
//
//
//
// let firstFieldFrame = CGRect(origin: CGPoint(x: sideInset + innerInset, y: navigationHeight + 3.0), size: CGSize(width: layout.size.width - (sideInset + innerInset) * 2.0, height: fieldHeight))
// transition.updateFrame(node: self.firstNameField, frame: firstFieldFrame)
//
// let lastFieldFrame = CGRect(origin: CGPoint(x: firstFieldFrame.minX, y: firstFieldFrame.maxY), size: CGSize(width: firstFieldFrame.size.width, height: fieldHeight))
// transition.updateFrame(node: self.lastNameField, frame: lastFieldFrame)
//
// transition.updateFrame(node: self.firstSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: firstFieldFrame.maxY), size: CGSize(width: layout.size.width - sideInset * 2.0, height: UIScreenPixel)))
// transition.updateFrame(node: self.lastSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: lastFieldFrame.maxY), size: CGSize(width: layout.size.width - sideInset * 2.0, height: UIScreenPixel)))
//
// let additionalAvailableHeight = max(1.0, availableHeight - lastFieldFrame.maxY)
// let additionalAvailableSpacing = max(1.0, additionalAvailableHeight - noticeHeight)
// let noticeSpacingFactor = maxNoticeSpacing / (maxNoticeSpacing + maxTermsOfServiceSpacing + minTrailingSpacing)
// let termsOfServiceSpacingFactor = maxTermsOfServiceSpacing / (maxNoticeSpacing + maxTermsOfServiceSpacing + minTrailingSpacing)
//
// let noticeSpacing: CGFloat
// let termsOfServiceSpacing: CGFloat
// if additionalAvailableHeight <= maxNoticeSpacing + noticeHeight + maxTermsOfServiceSpacing + minTrailingSpacing {
// termsOfServiceSpacing = min(floor(termsOfServiceSpacingFactor * additionalAvailableSpacing), maxTermsOfServiceSpacing)
// noticeSpacing = floor((additionalAvailableHeight - termsOfServiceSpacing - noticeHeight) / 2.0)
// } else {
// noticeSpacing = min(floor(noticeSpacingFactor * additionalAvailableSpacing), maxNoticeSpacing)
// termsOfServiceSpacing = min(floor(termsOfServiceSpacingFactor * additionalAvailableSpacing), maxTermsOfServiceSpacing)
// }
//
// let currentOptionFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - noticeSize.width) / 2.0), y: lastFieldFrame.maxY + max(0.0, noticeSpacing)), size: noticeSize)
// transition.updateFrame(node: self.currentOptionNode, frame: currentOptionFrame)
// let termsFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - termsSize.width) / 2.0), y: layout.size.height - insets.bottom - termsSize.height - 4.0), size: termsSize)
// transition.updateFrame(node: self.termsNode, frame: termsFrame)
//
let noticeHeight: CGFloat = noticeSize.height + (self.termsNode.isHidden ? 0.0 : (termsSize.height + 4.0)) let avatarSize: CGSize = CGSize(width: 110.0, height: 110.0)
var items: [AuthorizationLayoutItem] = []
items.append(AuthorizationLayoutItem(node: self.addPhotoButton, size: avatarSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 16.0, maxValue: 16.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
self.currentPhotoNode.frame = CGRect(origin: CGPoint(), size: avatarSize)
let minimalTermsOfServiceSpacing: CGFloat = 6.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)))
let maxTermsOfServiceSpacing: CGFloat = 20.0 items.append(AuthorizationLayoutItem(node: self.currentOptionNode, size: noticeSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 20.0, maxValue: 20.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
let minTrailingSpacing: CGFloat = 10.0
let inputHeight = inputFieldsHeight items.append(AuthorizationLayoutItem(node: self.firstNameField, size: CGSize(width: layout.size.width - (sideInset + innerInset) * 2.0, height: fieldHeight), spacingBefore: AuthorizationLayoutItemSpacing(weight: 32.0, maxValue: 60.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
let essentialHeight = additionalTitleSpacing + titleSize.height + minimalTitleSpacing + inputHeight + minimalNoticeSpacing + noticeHeight items.append(AuthorizationLayoutItem(node: self.firstSeparatorNode, size: CGSize(width: layout.size.width - sideInset * 2.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
let additionalHeight = minimalTermsOfServiceSpacing + minTrailingSpacing
let navigationHeight: CGFloat items.append(AuthorizationLayoutItem(node: self.lastNameField, size: CGSize(width: layout.size.width - (sideInset + innerInset) * 2.0, height: fieldHeight), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
if essentialHeight + additionalHeight > availableHeight || availableHeight * 0.66 - inputHeight < additionalHeight { items.append(AuthorizationLayoutItem(node: self.lastSeparatorNode, size: CGSize(width: layout.size.width - sideInset * 2.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
navigationHeight = min(floor(availableHeight * 0.3), availableHeight - inputFieldsHeight)
} else {
navigationHeight = floor(availableHeight * 0.3)
}
let titleOffset: CGFloat items.append(AuthorizationLayoutItem(node: self.termsNode, size: termsSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 48.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
if navigationHeight * 0.5 < titleSize.height + minimalTitleSpacing {
titleOffset = max(navigationBarHeight, floor((navigationHeight - titleSize.height) / 2.0))
} else {
titleOffset = max(navigationBarHeight, max(navigationHeight * 0.5, navigationHeight - maxTitleSpacing - titleSize.height))
}
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: titleOffset), size: titleSize))
let addPhotoButtonFrame = CGRect(origin: CGPoint(x: 10.0, y: navigationHeight + 10.0), size: CGSize(width: 110.0, height: 110.0)) let proceedHeight = self.proceedNode.updateLayout(width: layout.size.width - 48.0, transition: transition)
transition.updateFrame(node: self.addPhotoButton, frame: addPhotoButtonFrame) let proceedSize = CGSize(width: layout.size.width - 48.0, height: proceedHeight)
self.currentPhotoNode.frame = CGRect(origin: CGPoint(), size: addPhotoButtonFrame.size) items.append(AuthorizationLayoutItem(node: self.proceedNode, size: proceedSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 20.0, maxValue: 20.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
let firstFieldFrame = CGRect(origin: CGPoint(x: leftInset, y: navigationHeight + 3.0), size: CGSize(width: layout.size.width - leftInset, height: fieldHeight)) let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 20.0)), items: items, transition: transition, failIfDoesNotFit: false)
transition.updateFrame(node: self.firstNameField, frame: firstFieldFrame)
let lastFieldFrame = CGRect(origin: CGPoint(x: firstFieldFrame.minX, y: firstFieldFrame.maxY), size: CGSize(width: firstFieldFrame.size.width, height: fieldHeight))
transition.updateFrame(node: self.lastNameField, frame: lastFieldFrame)
transition.updateFrame(node: self.firstSeparatorNode, frame: CGRect(origin: CGPoint(x: leftInset, y: firstFieldFrame.maxY), size: CGSize(width: layout.size.width - leftInset, height: UIScreenPixel)))
transition.updateFrame(node: self.lastSeparatorNode, frame: CGRect(origin: CGPoint(x: leftInset, y: lastFieldFrame.maxY), size: CGSize(width: layout.size.width - leftInset, height: UIScreenPixel)))
let additionalAvailableHeight = max(1.0, availableHeight - lastFieldFrame.maxY)
let additionalAvailableSpacing = max(1.0, additionalAvailableHeight - noticeHeight)
let noticeSpacingFactor = maxNoticeSpacing / (maxNoticeSpacing + maxTermsOfServiceSpacing + minTrailingSpacing)
let termsOfServiceSpacingFactor = maxTermsOfServiceSpacing / (maxNoticeSpacing + maxTermsOfServiceSpacing + minTrailingSpacing)
let noticeSpacing: CGFloat
let termsOfServiceSpacing: CGFloat
if additionalAvailableHeight <= maxNoticeSpacing + noticeHeight + maxTermsOfServiceSpacing + minTrailingSpacing {
termsOfServiceSpacing = min(floor(termsOfServiceSpacingFactor * additionalAvailableSpacing), maxTermsOfServiceSpacing)
noticeSpacing = floor((additionalAvailableHeight - termsOfServiceSpacing - noticeHeight) / 2.0)
} else {
noticeSpacing = min(floor(noticeSpacingFactor * additionalAvailableSpacing), maxNoticeSpacing)
termsOfServiceSpacing = min(floor(termsOfServiceSpacingFactor * additionalAvailableSpacing), maxTermsOfServiceSpacing)
}
let currentOptionFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - noticeSize.width) / 2.0), y: lastFieldFrame.maxY + max(0.0, noticeSpacing)), size: noticeSize)
transition.updateFrame(node: self.currentOptionNode, frame: currentOptionFrame)
let termsFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - termsSize.width) / 2.0), y: layout.size.height - insets.bottom - termsSize.height - 4.0), size: termsSize)
transition.updateFrame(node: self.termsNode, frame: termsFrame)
} }
func activateInput() { func activateInput() {