mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Update password setup animations
This commit is contained in:
parent
acf59258e0
commit
c08b3c6f81
@ -14,7 +14,7 @@ private final class ManagedAnimationState {
|
|||||||
let frameCount: Int
|
let frameCount: Int
|
||||||
let fps: Double
|
let fps: Double
|
||||||
|
|
||||||
var startTime: Double?
|
var relativeTime: Double = 0.0
|
||||||
var frameIndex: Int?
|
var frameIndex: Int?
|
||||||
|
|
||||||
private let renderContext: DrawingContext
|
private let renderContext: DrawingContext
|
||||||
@ -73,7 +73,8 @@ class ManagedAnimationNode: ASDisplayNode {
|
|||||||
private let imageNode: ASImageNode
|
private let imageNode: ASImageNode
|
||||||
private let displayLink: CADisplayLink
|
private let displayLink: CADisplayLink
|
||||||
|
|
||||||
private var state: ManagedAnimationState?
|
fileprivate var state: ManagedAnimationState?
|
||||||
|
fileprivate var trackStack: [ManagedAnimationItem] = []
|
||||||
|
|
||||||
init(size: CGSize) {
|
init(size: CGSize) {
|
||||||
self.intrinsicSize = size
|
self.intrinsicSize = size
|
||||||
@ -110,30 +111,40 @@ class ManagedAnimationNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateAnimation() {
|
private func advanceState() {
|
||||||
|
guard !self.trackStack.isEmpty else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = self.trackStack.removeFirst()
|
||||||
|
|
||||||
|
if let state = self.state, state.item.name == item.name {
|
||||||
|
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: state)
|
||||||
|
} else {
|
||||||
|
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func updateAnimation() {
|
||||||
|
if self.state == nil {
|
||||||
|
self.advanceState()
|
||||||
|
}
|
||||||
|
|
||||||
guard let state = self.state else {
|
guard let state = self.state else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let timestamp = CACurrentMediaTime()
|
let timestamp = CACurrentMediaTime()
|
||||||
|
|
||||||
var startTime: Double
|
|
||||||
if let current = state.startTime {
|
|
||||||
startTime = current
|
|
||||||
} else {
|
|
||||||
startTime = timestamp
|
|
||||||
state.startTime = startTime
|
|
||||||
}
|
|
||||||
|
|
||||||
let fps = state.fps
|
let fps = state.fps
|
||||||
let frameRange = state.item.frames
|
let frameRange = state.item.frames
|
||||||
|
|
||||||
let duration: Double = 0.3
|
let duration: Double = 0.3
|
||||||
var t = (timestamp - startTime) / duration
|
var t = state.relativeTime / duration
|
||||||
t = max(0.0, t)
|
t = max(0.0, t)
|
||||||
t = min(1.0, t)
|
t = min(1.0, t)
|
||||||
let frameOffset = Int(Double(frameRange.startFrame) * (1.0 - t) + Double(frameRange.startFrame) * t)
|
let frameOffset = Int(Double(frameRange.startFrame) * (1.0 - t) + Double(frameRange.endFrame) * t)
|
||||||
let lowerBound = min(frameRange.startFrame, state.frameCount - 1)
|
let lowerBound: Int = 0
|
||||||
let upperBound = min(frameRange.endFrame, state.frameCount - 1)
|
let upperBound = state.frameCount - 1
|
||||||
let frameIndex = max(lowerBound, min(upperBound, frameOffset))
|
let frameIndex = max(lowerBound, min(upperBound, frameOffset))
|
||||||
|
|
||||||
if state.frameIndex != frameIndex {
|
if state.frameIndex != frameIndex {
|
||||||
@ -142,14 +153,19 @@ class ManagedAnimationNode: ASDisplayNode {
|
|||||||
self.imageNode.image = image
|
self.imageNode.image = image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var animationAdvancement: Double = 1.0 / 60.0
|
||||||
|
animationAdvancement *= Double(self.trackStack.count + 1)
|
||||||
|
|
||||||
|
state.relativeTime += animationAdvancement
|
||||||
|
|
||||||
|
if state.relativeTime >= duration {
|
||||||
|
self.advanceState()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func trackTo(item: ManagedAnimationItem, frameIndex: Int) {
|
func trackTo(item: ManagedAnimationItem) {
|
||||||
if let state = self.state, state.item.name == item.name {
|
self.trackStack.append(item)
|
||||||
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: state)
|
|
||||||
} else {
|
|
||||||
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: nil)
|
|
||||||
}
|
|
||||||
self.updateAnimation()
|
self.updateAnimation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,62 +238,93 @@ enum ManagedMonkeyAnimationState: Equatable {
|
|||||||
)*/
|
)*/
|
||||||
|
|
||||||
final class ManagedMonkeyAnimationNode: ManagedAnimationNode {
|
final class ManagedMonkeyAnimationNode: ManagedAnimationNode {
|
||||||
private var state: ManagedMonkeyAnimationState = .idle
|
private var monkeyState: ManagedMonkeyAnimationState = .idle
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
super.init(size: CGSize(width: 136.0, height: 136.0))
|
super.init(size: CGSize(width: 136.0, height: 136.0))
|
||||||
|
|
||||||
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyIdle", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 0)), frameIndex: 0)
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyIdle", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setState(_ state: ManagedMonkeyAnimationState) {
|
func setState(_ monkeyState: ManagedMonkeyAnimationState) {
|
||||||
let previousState = self.state
|
let previousState = self.monkeyState
|
||||||
self.state = state
|
self.monkeyState = monkeyState
|
||||||
|
|
||||||
|
func enqueueTracking(_ value: CGFloat) {
|
||||||
|
let lowerBound = 18
|
||||||
|
let upperBound = 160
|
||||||
|
let frameIndex = lowerBound + Int(value * CGFloat(upperBound - lowerBound))
|
||||||
|
if let state = self.state, state.item.name == "TwoFactorSetupMonkeyTracking" {
|
||||||
|
let item = ManagedAnimationItem(name: "TwoFactorSetupMonkeyTracking", frames: ManagedAnimationFrameRange(startFrame: state.frameIndex ?? 0, endFrame: frameIndex))
|
||||||
|
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: state)
|
||||||
|
self.updateAnimation()
|
||||||
|
} else {
|
||||||
|
self.trackStack = self.trackStack.filter {
|
||||||
|
$0.name != "TwoFactorSetupMonkeyTracking"
|
||||||
|
}
|
||||||
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyTracking", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: frameIndex)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func enqueueClearTracking() {
|
||||||
|
if let state = self.state, state.item.name == "TwoFactorSetupMonkeyTracking" {
|
||||||
|
let item = ManagedAnimationItem(name: "TwoFactorSetupMonkeyTracking", frames: ManagedAnimationFrameRange(startFrame: state.frameIndex ?? 0, endFrame: 0))
|
||||||
|
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: state)
|
||||||
|
self.updateAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch previousState {
|
switch previousState {
|
||||||
case .idle:
|
case .idle:
|
||||||
switch state {
|
switch monkeyState {
|
||||||
case .idle:
|
case .idle:
|
||||||
break
|
break
|
||||||
case .eyesClosed:
|
case .eyesClosed:
|
||||||
break
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 41)))
|
||||||
case .peeking:
|
case .peeking:
|
||||||
break
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyCloseAndPeek", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 41)))
|
||||||
case let .tracking(value):
|
case let .tracking(value):
|
||||||
break
|
enqueueTracking(value)
|
||||||
}
|
}
|
||||||
case .eyesClosed:
|
case .eyesClosed:
|
||||||
switch state {
|
switch monkeyState {
|
||||||
case .idle:
|
case .idle:
|
||||||
break
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose", frames: ManagedAnimationFrameRange(startFrame: 41, endFrame: 0)))
|
||||||
case .eyesClosed:
|
case .eyesClosed:
|
||||||
break
|
break
|
||||||
case .peeking:
|
case .peeking:
|
||||||
break
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyPeek", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 14)))
|
||||||
case let .tracking(value):
|
case let .tracking(value):
|
||||||
break
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose", frames: ManagedAnimationFrameRange(startFrame: 41, endFrame: 0)))
|
||||||
|
enqueueTracking(value)
|
||||||
}
|
}
|
||||||
case .peeking:
|
case .peeking:
|
||||||
switch state {
|
switch monkeyState {
|
||||||
case .idle:
|
case .idle:
|
||||||
break
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyCloseAndPeek", frames: ManagedAnimationFrameRange(startFrame: 41, endFrame: 0)))
|
||||||
case .eyesClosed:
|
case .eyesClosed:
|
||||||
break
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyPeek", frames: ManagedAnimationFrameRange(startFrame: 14, endFrame: 0)))
|
||||||
case .peeking:
|
case .peeking:
|
||||||
break
|
break
|
||||||
case let .tracking(value):
|
case let .tracking(value):
|
||||||
break
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyCloseAndPeek", frames: ManagedAnimationFrameRange(startFrame: 41, endFrame: 0)))
|
||||||
|
enqueueTracking(value)
|
||||||
}
|
}
|
||||||
case let .tracking(previousValue):
|
case let .tracking(currentValue):
|
||||||
switch state {
|
switch monkeyState {
|
||||||
case .idle:
|
case .idle:
|
||||||
break
|
enqueueClearTracking()
|
||||||
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyIdle", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 0)))
|
||||||
case .eyesClosed:
|
case .eyesClosed:
|
||||||
break
|
enqueueClearTracking()
|
||||||
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 41)))
|
||||||
case .peeking:
|
case .peeking:
|
||||||
break
|
enqueueClearTracking()
|
||||||
|
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyCloseAndPeek", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 41)))
|
||||||
case let .tracking(value):
|
case let .tracking(value):
|
||||||
break
|
if abs(currentValue - value) > CGFloat.ulpOfOne {
|
||||||
|
enqueueTracking(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@ public enum TwoFactorDataInputMode {
|
|||||||
case passwordHint(password: String)
|
case passwordHint(password: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public final class TwoFactorDataInputScreen: ViewController {
|
public final class TwoFactorDataInputScreen: ViewController {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
@ -471,7 +469,7 @@ private func generateTextHiddenImage(color: UIColor, on: Bool) -> UIImage? {
|
|||||||
private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelegate {
|
private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelegate {
|
||||||
private let theme: PresentationTheme
|
private let theme: PresentationTheme
|
||||||
let mode: TwoFactorDataInputTextNodeType
|
let mode: TwoFactorDataInputTextNodeType
|
||||||
private let focused: (TwoFactorDataInputTextNode) -> Void
|
private let focusUpdated: (TwoFactorDataInputTextNode, Bool) -> Void
|
||||||
private let next: (TwoFactorDataInputTextNode) -> Void
|
private let next: (TwoFactorDataInputTextNode) -> Void
|
||||||
private let updated: (TwoFactorDataInputTextNode) -> Void
|
private let updated: (TwoFactorDataInputTextNode) -> Void
|
||||||
private let toggleTextHidden: (TwoFactorDataInputTextNode) -> Void
|
private let toggleTextHidden: (TwoFactorDataInputTextNode) -> Void
|
||||||
@ -481,6 +479,12 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
|
|||||||
private let hideButtonNode: HighlightableButtonNode
|
private let hideButtonNode: HighlightableButtonNode
|
||||||
private let clearButtonNode: HighlightableButtonNode
|
private let clearButtonNode: HighlightableButtonNode
|
||||||
|
|
||||||
|
fileprivate var ignoreTextChanged: Bool = false
|
||||||
|
|
||||||
|
var isFocused: Bool {
|
||||||
|
return self.inputNode.textField.isFirstResponder
|
||||||
|
}
|
||||||
|
|
||||||
var text: String {
|
var text: String {
|
||||||
get {
|
get {
|
||||||
return self.inputNode.textField.text ?? ""
|
return self.inputNode.textField.text ?? ""
|
||||||
@ -490,10 +494,10 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(theme: PresentationTheme, mode: TwoFactorDataInputTextNodeType, placeholder: String, focused: @escaping (TwoFactorDataInputTextNode) -> Void, next: @escaping (TwoFactorDataInputTextNode) -> Void, updated: @escaping (TwoFactorDataInputTextNode) -> Void, toggleTextHidden: @escaping (TwoFactorDataInputTextNode) -> Void) {
|
init(theme: PresentationTheme, mode: TwoFactorDataInputTextNodeType, placeholder: String, focusUpdated: @escaping (TwoFactorDataInputTextNode, Bool) -> Void, next: @escaping (TwoFactorDataInputTextNode) -> Void, updated: @escaping (TwoFactorDataInputTextNode) -> Void, toggleTextHidden: @escaping (TwoFactorDataInputTextNode) -> Void) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.focused = focused
|
self.focusUpdated = focusUpdated
|
||||||
self.next = next
|
self.next = next
|
||||||
self.updated = updated
|
self.updated = updated
|
||||||
self.toggleTextHidden = toggleTextHidden
|
self.toggleTextHidden = toggleTextHidden
|
||||||
@ -564,11 +568,21 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
|
|||||||
|
|
||||||
func textFieldDidBeginEditing(_ textField: UITextField) {
|
func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||||
let text = self.text
|
let text = self.text
|
||||||
let isEmpty = text.isEmpty
|
|
||||||
self.focused(self)
|
if self.inputNode.textField.isSecureTextEntry {
|
||||||
|
let previousIgnoreTextChanged = self.ignoreTextChanged
|
||||||
|
self.ignoreTextChanged = true
|
||||||
|
self.inputNode.textField.text = ""
|
||||||
|
self.inputNode.textField.insertText(text + " ")
|
||||||
|
self.inputNode.textField.deleteBackward()
|
||||||
|
self.ignoreTextChanged = previousIgnoreTextChanged
|
||||||
|
}
|
||||||
|
|
||||||
|
self.focusUpdated(self, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func textFieldDidEndEditing(_ textField: UITextField) {
|
func textFieldDidEndEditing(_ textField: UITextField) {
|
||||||
|
self.focusUpdated(self, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||||
@ -581,13 +595,15 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc private func textFieldChanged(_ textField: UITextField) {
|
@objc private func textFieldChanged(_ textField: UITextField) {
|
||||||
switch self.mode {
|
if !self.ignoreTextChanged {
|
||||||
case .password:
|
switch self.mode {
|
||||||
break
|
case .password:
|
||||||
default:
|
break
|
||||||
self.clearButtonNode.isHidden = self.text.isEmpty
|
default:
|
||||||
|
self.clearButtonNode.isHidden = self.text.isEmpty
|
||||||
|
}
|
||||||
|
self.updated(self)
|
||||||
}
|
}
|
||||||
self.updated(self)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func hidePressed() {
|
@objc private func hidePressed() {
|
||||||
@ -615,7 +631,19 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
|
|||||||
|
|
||||||
func updateTextHidden(_ value: Bool) {
|
func updateTextHidden(_ value: Bool) {
|
||||||
self.hideButtonNode.setImage(generateTextHiddenImage(color: self.theme.actionSheet.inputClearButtonColor, on: !value), for: [])
|
self.hideButtonNode.setImage(generateTextHiddenImage(color: self.theme.actionSheet.inputClearButtonColor, on: !value), for: [])
|
||||||
|
let text = self.inputNode.textField.text ?? ""
|
||||||
self.inputNode.textField.isSecureTextEntry = value
|
self.inputNode.textField.isSecureTextEntry = value
|
||||||
|
if value {
|
||||||
|
if self.inputNode.textField.isFirstResponder {
|
||||||
|
let previousIgnoreTextChanged = self.ignoreTextChanged
|
||||||
|
self.ignoreTextChanged = true
|
||||||
|
self.inputNode.textField.text = ""
|
||||||
|
self.inputNode.textField.becomeFirstResponder()
|
||||||
|
self.inputNode.textField.insertText(text + " ")
|
||||||
|
self.inputNode.textField.deleteBackward()
|
||||||
|
self.ignoreTextChanged = previousIgnoreTextChanged
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,7 +722,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
|
|
||||||
var inputNodes: [TwoFactorDataInputTextNode] = []
|
var inputNodes: [TwoFactorDataInputTextNode] = []
|
||||||
var next: ((TwoFactorDataInputTextNode) -> Void)?
|
var next: ((TwoFactorDataInputTextNode) -> Void)?
|
||||||
var focused: ((TwoFactorDataInputTextNode) -> Void)?
|
var focusUpdated: ((TwoFactorDataInputTextNode, Bool) -> Void)?
|
||||||
var updated: ((TwoFactorDataInputTextNode) -> Void)?
|
var updated: ((TwoFactorDataInputTextNode) -> Void)?
|
||||||
var toggleTextHidden: ((TwoFactorDataInputTextNode) -> Void)?
|
var toggleTextHidden: ((TwoFactorDataInputTextNode) -> Void)?
|
||||||
|
|
||||||
@ -707,8 +735,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
changeEmailActionText = ""
|
changeEmailActionText = ""
|
||||||
resendCodeActionText = ""
|
resendCodeActionText = ""
|
||||||
inputNodes = [
|
inputNodes = [
|
||||||
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: false), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderPassword, focused: { node in
|
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: false), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderPassword, focusUpdated: { node, focused in
|
||||||
focused?(node)
|
focusUpdated?(node, focused)
|
||||||
}, next: { node in
|
}, next: { node in
|
||||||
next?(node)
|
next?(node)
|
||||||
}, updated: { node in
|
}, updated: { node in
|
||||||
@ -716,8 +744,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
}, toggleTextHidden: { node in
|
}, toggleTextHidden: { node in
|
||||||
toggleTextHidden?(node)
|
toggleTextHidden?(node)
|
||||||
}),
|
}),
|
||||||
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: true), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderConfirmPassword, focused: { node in
|
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: true), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderConfirmPassword, focusUpdated: { node, focused in
|
||||||
focused?(node)
|
focusUpdated?(node, focused)
|
||||||
}, next: { node in
|
}, next: { node in
|
||||||
next?(node)
|
next?(node)
|
||||||
}, updated: { node in
|
}, updated: { node in
|
||||||
@ -734,8 +762,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
changeEmailActionText = ""
|
changeEmailActionText = ""
|
||||||
resendCodeActionText = ""
|
resendCodeActionText = ""
|
||||||
inputNodes = [
|
inputNodes = [
|
||||||
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .email, placeholder: presentationData.strings.TwoFactorSetup_Email_Placeholder, focused: { node in
|
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .email, placeholder: presentationData.strings.TwoFactorSetup_Email_Placeholder, focusUpdated: { node, focused in
|
||||||
focused?(node)
|
focusUpdated?(node, focused)
|
||||||
}, next: { node in
|
}, next: { node in
|
||||||
next?(node)
|
next?(node)
|
||||||
}, updated: { node in
|
}, updated: { node in
|
||||||
@ -761,8 +789,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
changeEmailActionText = presentationData.strings.TwoFactorSetup_EmailVerification_ChangeAction
|
changeEmailActionText = presentationData.strings.TwoFactorSetup_EmailVerification_ChangeAction
|
||||||
resendCodeActionText = presentationData.strings.TwoFactorSetup_EmailVerification_ResendAction
|
resendCodeActionText = presentationData.strings.TwoFactorSetup_EmailVerification_ResendAction
|
||||||
inputNodes = [
|
inputNodes = [
|
||||||
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .code, placeholder: presentationData.strings.TwoFactorSetup_EmailVerification_Placeholder, focused: { node in
|
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .code, placeholder: presentationData.strings.TwoFactorSetup_EmailVerification_Placeholder, focusUpdated: { node, focused in
|
||||||
focused?(node)
|
focusUpdated?(node, focused)
|
||||||
}, next: { node in
|
}, next: { node in
|
||||||
next?(node)
|
next?(node)
|
||||||
}, updated: { node in
|
}, updated: { node in
|
||||||
@ -781,8 +809,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
changeEmailActionText = ""
|
changeEmailActionText = ""
|
||||||
resendCodeActionText = ""
|
resendCodeActionText = ""
|
||||||
inputNodes = [
|
inputNodes = [
|
||||||
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .hint, placeholder: presentationData.strings.TwoFactorSetup_Hint_Placeholder, focused: { node in
|
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .hint, placeholder: presentationData.strings.TwoFactorSetup_Hint_Placeholder, focusUpdated: { node, focused in
|
||||||
focused?(node)
|
focusUpdated?(node, focused)
|
||||||
}, next: { node in
|
}, next: { node in
|
||||||
next?(node)
|
next?(node)
|
||||||
}, updated: { node in
|
}, updated: { node in
|
||||||
@ -917,67 +945,64 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
focused = { [weak self] node in
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var textHidden = true
|
var textHidden = true
|
||||||
let updateAnimations: () -> Void = { [weak self] in
|
let updateAnimations: () -> Void = { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
switch strongSelf.mode {
|
||||||
/*switch strongSelf.mode {
|
|
||||||
case .password:
|
case .password:
|
||||||
if !hasText {
|
if strongSelf.inputNodes[1].isFocused {
|
||||||
if strongSelf.animationNode.currentItemName == animationPeek.name {
|
let textLength = strongSelf.inputNodes[1].text.count
|
||||||
strongSelf.animationNode.switchTo(animationHideOutro)
|
let maxWidth = strongSelf.inputNodes[1].bounds.width
|
||||||
strongSelf.animationNode.switchTo(animationIdle)
|
|
||||||
|
let textNode = ImmediateTextNode()
|
||||||
|
textNode.attributedText = NSAttributedString(string: strongSelf.inputNodes[1].text, font: Font.regular(17.0), textColor: .black)
|
||||||
|
let textSize = textNode.updateLayout(CGSize(width: 1000.0, height: 100.0))
|
||||||
|
|
||||||
|
let maxTextLength = 20
|
||||||
|
var trackingOffset = textSize.width / maxWidth
|
||||||
|
trackingOffset = max(0.0, min(1.0, trackingOffset))
|
||||||
|
strongSelf.monkeyNode?.setState(.tracking(trackingOffset))
|
||||||
|
} else if strongSelf.inputNodes[0].isFocused {
|
||||||
|
let hasText = !strongSelf.inputNodes[0].text.isEmpty
|
||||||
|
if !hasText {
|
||||||
|
strongSelf.monkeyNode?.setState(.idle)
|
||||||
|
} else if textHidden {
|
||||||
|
strongSelf.monkeyNode?.setState(.eyesClosed)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.animationNode.switchTo(animationIdle)
|
strongSelf.monkeyNode?.setState(.peeking)
|
||||||
}
|
|
||||||
} else if textHidden {
|
|
||||||
if strongSelf.animationNode.currentItemName == animationPeek.name {
|
|
||||||
strongSelf.animationNode.switchTo(animationHideNoIntro)
|
|
||||||
} else {
|
|
||||||
strongSelf.animationNode.switchTo(animationHide)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if strongSelf.animationNode.currentItemName != animationPeek.name {
|
strongSelf.monkeyNode?.setState(.idle)
|
||||||
if strongSelf.animationNode.currentItemName == animationHide.name {
|
|
||||||
strongSelf.animationNode.switchTo(animationPeek, noOutro: true)
|
|
||||||
} else if strongSelf.animationNode.currentItemName == animationIdle.name {
|
|
||||||
strongSelf.animationNode.switchTo(animationHideNoOutro)
|
|
||||||
strongSelf.animationNode.switchTo(animationPeek)
|
|
||||||
} else {
|
|
||||||
strongSelf.animationNode.switchTo(animationPeek, noOutro: strongSelf.animationNode.currentItemName == animationHide.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case .emailAddress:
|
case .emailAddress:
|
||||||
let textLength = strongSelf.inputNodes[0].text.count
|
if strongSelf.inputNodes[0].isFocused {
|
||||||
let maxWidth = strongSelf.inputNodes[0].bounds.width
|
let textLength = strongSelf.inputNodes[0].text.count
|
||||||
if textLength == 0 || maxWidth.isZero {
|
let maxWidth = strongSelf.inputNodes[0].bounds.width
|
||||||
strongSelf.animationNode.trackTo(frameIndex: 0)
|
|
||||||
} else {
|
|
||||||
let textNode = ImmediateTextNode()
|
let textNode = ImmediateTextNode()
|
||||||
textNode.attributedText = NSAttributedString(string: strongSelf.inputNodes[0].text, font: Font.regular(17.0), textColor: .black)
|
textNode.attributedText = NSAttributedString(string: strongSelf.inputNodes[0].text, font: Font.regular(17.0), textColor: .black)
|
||||||
let textSize = textNode.updateLayout(CGSize(width: 1000.0, height: 100.0))
|
let textSize = textNode.updateLayout(CGSize(width: 1000.0, height: 100.0))
|
||||||
|
|
||||||
let maxTextLength = 20
|
let maxTextLength = 20
|
||||||
let lowerBound = 14
|
|
||||||
let upperBound = 160
|
|
||||||
var trackingOffset = textSize.width / maxWidth
|
var trackingOffset = textSize.width / maxWidth
|
||||||
trackingOffset = max(0.0, min(1.0, trackingOffset))
|
trackingOffset = max(0.0, min(1.0, trackingOffset))
|
||||||
let frameIndex = lowerBound + Int(trackingOffset * CGFloat(upperBound - lowerBound))
|
strongSelf.monkeyNode?.setState(.tracking(trackingOffset))
|
||||||
strongSelf.animationNode.trackTo(frameIndex: frameIndex)
|
} else {
|
||||||
|
strongSelf.monkeyNode?.setState(.idle)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}*/
|
}
|
||||||
|
}
|
||||||
|
focusUpdated = { [weak self] node, _ in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateAnimations()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updated = { [weak self] _ in
|
updated = { [weak self] _ in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -1068,7 +1093,13 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
|
|
||||||
let sideInset: CGFloat = 32.0
|
let sideInset: CGFloat = 32.0
|
||||||
let buttonSideInset: CGFloat = 48.0
|
let buttonSideInset: CGFloat = 48.0
|
||||||
let iconSpacing: CGFloat = 2.0
|
let iconSpacing: CGFloat
|
||||||
|
switch self.mode {
|
||||||
|
case .passwordHint, .emailConfirmation:
|
||||||
|
iconSpacing = 6.0
|
||||||
|
default:
|
||||||
|
iconSpacing = 2.0
|
||||||
|
}
|
||||||
let titleSpacing: CGFloat = 19.0
|
let titleSpacing: CGFloat = 19.0
|
||||||
let titleInputSpacing: CGFloat = 26.0
|
let titleInputSpacing: CGFloat = 26.0
|
||||||
let textSpacing: CGFloat = 30.0
|
let textSpacing: CGFloat = 30.0
|
||||||
@ -1118,6 +1149,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
|
|
||||||
let iconFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize)
|
let iconFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize)
|
||||||
if let animatedStickerNode = self.animatedStickerNode {
|
if let animatedStickerNode = self.animatedStickerNode {
|
||||||
|
animatedStickerNode.updateLayout(size: iconFrame.size)
|
||||||
transition.updateFrame(node: animatedStickerNode, frame: iconFrame)
|
transition.updateFrame(node: animatedStickerNode, frame: iconFrame)
|
||||||
} else if let monkeyNode = self.monkeyNode {
|
} else if let monkeyNode = self.monkeyNode {
|
||||||
transition.updateFrame(node: monkeyNode, frame: iconFrame)
|
transition.updateFrame(node: monkeyNode, frame: iconFrame)
|
||||||
|
@ -641,14 +641,14 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
|||||||
case .set:
|
case .set:
|
||||||
break
|
break
|
||||||
case let .notSet(pendingEmail):
|
case let .notSet(pendingEmail):
|
||||||
break
|
|
||||||
//intro = pendingEmail == nil
|
//intro = pendingEmail == nil
|
||||||
/*if pendingEmail == nil {
|
if pendingEmail == nil {
|
||||||
let controller = TwoFactorAuthSplashScreen(context: context, mode: .intro)
|
let controller = TwoFactorAuthSplashScreen(context: context, mode: .intro)
|
||||||
pushControllerImpl?(controller, true)
|
pushControllerImpl?(controller, true)
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if intro {
|
if intro {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user