Update password setup animations

This commit is contained in:
Ali
2019-11-12 17:40:24 +04:00
parent acf59258e0
commit c08b3c6f81
3 changed files with 191 additions and 112 deletions

View File

@@ -20,8 +20,6 @@ public enum TwoFactorDataInputMode {
case passwordHint(password: String)
}
public final class TwoFactorDataInputScreen: ViewController {
private let context: AccountContext
private var presentationData: PresentationData
@@ -471,7 +469,7 @@ private func generateTextHiddenImage(color: UIColor, on: Bool) -> UIImage? {
private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelegate {
private let theme: PresentationTheme
let mode: TwoFactorDataInputTextNodeType
private let focused: (TwoFactorDataInputTextNode) -> Void
private let focusUpdated: (TwoFactorDataInputTextNode, Bool) -> Void
private let next: (TwoFactorDataInputTextNode) -> Void
private let updated: (TwoFactorDataInputTextNode) -> Void
private let toggleTextHidden: (TwoFactorDataInputTextNode) -> Void
@@ -481,6 +479,12 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
private let hideButtonNode: HighlightableButtonNode
private let clearButtonNode: HighlightableButtonNode
fileprivate var ignoreTextChanged: Bool = false
var isFocused: Bool {
return self.inputNode.textField.isFirstResponder
}
var text: String {
get {
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.mode = mode
self.focused = focused
self.focusUpdated = focusUpdated
self.next = next
self.updated = updated
self.toggleTextHidden = toggleTextHidden
@@ -564,11 +568,21 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
func textFieldDidBeginEditing(_ textField: UITextField) {
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) {
self.focusUpdated(self, false)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
@@ -581,13 +595,15 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
}
@objc private func textFieldChanged(_ textField: UITextField) {
switch self.mode {
case .password:
break
default:
self.clearButtonNode.isHidden = self.text.isEmpty
if !self.ignoreTextChanged {
switch self.mode {
case .password:
break
default:
self.clearButtonNode.isHidden = self.text.isEmpty
}
self.updated(self)
}
self.updated(self)
}
@objc private func hidePressed() {
@@ -615,7 +631,19 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
func updateTextHidden(_ value: Bool) {
self.hideButtonNode.setImage(generateTextHiddenImage(color: self.theme.actionSheet.inputClearButtonColor, on: !value), for: [])
let text = self.inputNode.textField.text ?? ""
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 next: ((TwoFactorDataInputTextNode) -> Void)?
var focused: ((TwoFactorDataInputTextNode) -> Void)?
var focusUpdated: ((TwoFactorDataInputTextNode, Bool) -> Void)?
var updated: ((TwoFactorDataInputTextNode) -> Void)?
var toggleTextHidden: ((TwoFactorDataInputTextNode) -> Void)?
@@ -707,8 +735,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
changeEmailActionText = ""
resendCodeActionText = ""
inputNodes = [
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: false), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderPassword, focused: { node in
focused?(node)
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: false), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderPassword, focusUpdated: { node, focused in
focusUpdated?(node, focused)
}, next: { node in
next?(node)
}, updated: { node in
@@ -716,8 +744,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
}, toggleTextHidden: { node in
toggleTextHidden?(node)
}),
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: true), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderConfirmPassword, focused: { node in
focused?(node)
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: true), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderConfirmPassword, focusUpdated: { node, focused in
focusUpdated?(node, focused)
}, next: { node in
next?(node)
}, updated: { node in
@@ -734,8 +762,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
changeEmailActionText = ""
resendCodeActionText = ""
inputNodes = [
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .email, placeholder: presentationData.strings.TwoFactorSetup_Email_Placeholder, focused: { node in
focused?(node)
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .email, placeholder: presentationData.strings.TwoFactorSetup_Email_Placeholder, focusUpdated: { node, focused in
focusUpdated?(node, focused)
}, next: { node in
next?(node)
}, updated: { node in
@@ -761,8 +789,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
changeEmailActionText = presentationData.strings.TwoFactorSetup_EmailVerification_ChangeAction
resendCodeActionText = presentationData.strings.TwoFactorSetup_EmailVerification_ResendAction
inputNodes = [
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .code, placeholder: presentationData.strings.TwoFactorSetup_EmailVerification_Placeholder, focused: { node in
focused?(node)
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .code, placeholder: presentationData.strings.TwoFactorSetup_EmailVerification_Placeholder, focusUpdated: { node, focused in
focusUpdated?(node, focused)
}, next: { node in
next?(node)
}, updated: { node in
@@ -781,8 +809,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
changeEmailActionText = ""
resendCodeActionText = ""
inputNodes = [
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .hint, placeholder: presentationData.strings.TwoFactorSetup_Hint_Placeholder, focused: { node in
focused?(node)
TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .hint, placeholder: presentationData.strings.TwoFactorSetup_Hint_Placeholder, focusUpdated: { node, focused in
focusUpdated?(node, focused)
}, next: { node in
next?(node)
}, 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
let updateAnimations: () -> Void = { [weak self] in
guard let strongSelf = self else {
return
}
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
/*switch strongSelf.mode {
switch strongSelf.mode {
case .password:
if !hasText {
if strongSelf.animationNode.currentItemName == animationPeek.name {
strongSelf.animationNode.switchTo(animationHideOutro)
strongSelf.animationNode.switchTo(animationIdle)
if strongSelf.inputNodes[1].isFocused {
let textLength = strongSelf.inputNodes[1].text.count
let maxWidth = strongSelf.inputNodes[1].bounds.width
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 {
strongSelf.animationNode.switchTo(animationIdle)
}
} else if textHidden {
if strongSelf.animationNode.currentItemName == animationPeek.name {
strongSelf.animationNode.switchTo(animationHideNoIntro)
} else {
strongSelf.animationNode.switchTo(animationHide)
strongSelf.monkeyNode?.setState(.peeking)
}
} else {
if strongSelf.animationNode.currentItemName != animationPeek.name {
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)
}
}
strongSelf.monkeyNode?.setState(.idle)
}
case .emailAddress:
let textLength = strongSelf.inputNodes[0].text.count
let maxWidth = strongSelf.inputNodes[0].bounds.width
if textLength == 0 || maxWidth.isZero {
strongSelf.animationNode.trackTo(frameIndex: 0)
} else {
if strongSelf.inputNodes[0].isFocused {
let textLength = strongSelf.inputNodes[0].text.count
let maxWidth = strongSelf.inputNodes[0].bounds.width
let textNode = ImmediateTextNode()
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 maxTextLength = 20
let lowerBound = 14
let upperBound = 160
var trackingOffset = textSize.width / maxWidth
trackingOffset = max(0.0, min(1.0, trackingOffset))
let frameIndex = lowerBound + Int(trackingOffset * CGFloat(upperBound - lowerBound))
strongSelf.animationNode.trackTo(frameIndex: frameIndex)
strongSelf.monkeyNode?.setState(.tracking(trackingOffset))
} else {
strongSelf.monkeyNode?.setState(.idle)
}
default:
break
}*/
}
}
focusUpdated = { [weak self] node, _ in
DispatchQueue.main.async {
guard let strongSelf = self else {
return
}
updateAnimations()
}
}
updated = { [weak self] _ in
guard let strongSelf = self else {
@@ -1068,7 +1093,13 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
let sideInset: CGFloat = 32.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 titleInputSpacing: CGFloat = 26.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)
if let animatedStickerNode = self.animatedStickerNode {
animatedStickerNode.updateLayout(size: iconFrame.size)
transition.updateFrame(node: animatedStickerNode, frame: iconFrame)
} else if let monkeyNode = self.monkeyNode {
transition.updateFrame(node: monkeyNode, frame: iconFrame)