From e1cb13110a54b94368c0f6c467fd63a2fbce1eb0 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 14 Dec 2022 14:25:33 +0400 Subject: [PATCH] Authorization code paste menu --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + ...orizationSequenceCodeEntryController.swift | 4 ++ ...ationSequenceCodeEntryControllerNode.swift | 66 ++++++++++++++----- .../CodeInputView/Sources/CodeInputView.swift | 13 ++++ 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 81a0208547..4ac130ef01 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8504,3 +8504,5 @@ Sorry for the inconvenience."; "Privacy.ProfilePhoto.PublicPhotoInfo" = "You can upload a public photo for those who are restricted from viewing your real profile photo."; "WebApp.AddToAttachmentAllowMessages" = "Allow **%@** to send me messages"; + +"Common.Paste" = "Paste"; diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryController.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryController.swift index 9452ad106a..68e5634970 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryController.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryController.swift @@ -109,6 +109,10 @@ public final class AuthorizationSequenceCodeEntryController: ViewController { self?.navigationItem.rightBarButtonItem?.isEnabled = value } + self.controllerNode.present = { [weak self] c, a in + self?.present(c, in: .window(.root), with: a) + } + if let (number, email, codeType, nextType, timeout) = self.data { var appleSignInAllowed = false if case let .email(_, _, _, appleSignInAllowedValue, _) = codeType { diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift index e2e7840121..d9f82016a7 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift @@ -14,6 +14,7 @@ import TelegramAnimatedStickerNode import SolidRoundedButtonNode import InvisibleInkDustNode import AuthorizationUtils +import TelegramStringFormatting final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextFieldDelegate { private let strings: PresentationStrings @@ -64,6 +65,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF var loginWithCode: ((String) -> Void)? var signInWithApple: (() -> Void)? var openFragment: ((String) -> Void)? + var present: (ViewController, Any?) -> Void = { _, _ in } var requestNextOption: (() -> Void)? var requestAnotherOption: (() -> Void)? @@ -170,6 +172,34 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF strongSelf.textChanged(text: strongSelf.codeInputView.text) } + self.codeInputView.longPressed = { [weak self] in + guard let strongSelf = self else { + return + } + + if let code = UIPasteboard.general.string, let codeLength = strongSelf.requiredCodeLength, code.count == Int(codeLength) { + let code = normalizeArabicNumeralString(code, type: .western) + guard code.rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789").inverted) == nil else { + return + } + + let controller = ContextMenuController(actions: [ContextMenuAction(content: .text(title: strongSelf.strings.Common_Paste, accessibilityLabel: strongSelf.strings.Common_Paste), action: { [weak self] in + self?.updateCode(code) + })]) + + strongSelf.present( + controller, + ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self] in + if let strongSelf = self { + return (strongSelf, strongSelf.codeInputView.frame.offsetBy(dx: 0.0, dy: -8.0), strongSelf, strongSelf.bounds) + } else { + return nil + } + }) + ) + } + } + self.nextOptionButtonNode.addTarget(self, action: #selector(self.nextOptionNodePressed), forControlEvents: .touchUpInside) self.proceedNode.pressed = { [weak self] in self?.proceedPressed() @@ -188,28 +218,34 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF self.view.addSubview(signInWithAppleButton) } } - + func updateCode(_ code: String) { self.codeInputView.text = code self.textChanged(text: code) + if let codeLength = self.requiredCodeLength, code.count == Int(codeLength) { + self.loginWithCode?(code) + } + } + + var requiredCodeLength: Int32? { if let codeType = self.codeType { - var codeLength: Int32? switch codeType { - case let .call(length): - codeLength = length - case let .otherSession(length): - codeLength = length - case let .missedCall(_, length): - codeLength = length - case let .sms(length): - codeLength = length - default: - break - } - if let codeLength = codeLength, code.count == Int(codeLength) { - self.loginWithCode?(code) + case let .call(length): + return length + case let .otherSession(length): + return length + case let .missedCall(_, length): + return length + case let .sms(length): + return length + case let .fragment(_, length): + return length + default: + return nil } + } else { + return nil } } diff --git a/submodules/CodeInputView/Sources/CodeInputView.swift b/submodules/CodeInputView/Sources/CodeInputView.swift index cc71e8f894..74d3b38ee9 100644 --- a/submodules/CodeInputView/Sources/CodeInputView.swift +++ b/submodules/CodeInputView/Sources/CodeInputView.swift @@ -118,6 +118,7 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate { private var itemViews: [ItemView] = [] public var updated: (() -> Void)? + public var longPressed: (() -> Void)? private var theme: Theme? private var count: Int? @@ -169,6 +170,18 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate { } } + public override func didLoad() { + super.didLoad() + + self.view.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress(_:)))) + } + + @objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) { + if case .ended = gestureRecognizer.state { + self.longPressed?() + } + } + private var isSucceed = false private var isFailed = false private var isResetting = false