123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- //
- // KMVerificationCodeView.swift
- // PDF Reader Pro
- //
- // Created by lizhe on 2023/2/23.
- //
- import Cocoa
- typealias KMVerificationCodeViewCancelAction = (_ view: KMVerificationCodeView) -> Void
- typealias KMVerificationCodeViewVerificationCodeAction = (_ view: KMVerificationCodeView, _ data: KMRegisterModel, _ codeString: String) -> Void
- typealias KMVerificationCodeViewDoneAction = (_ view: KMVerificationCodeView, _ data: KMRegisterModel, _ sender: NSButton) -> Void
- typealias KMVerificationCodeViewCloseAction = (_ view: KMVerificationCodeView) -> Void
- typealias KMVerificationCodeViewReSendAction = (_ view: KMVerificationCodeView, _ sender: NSTextView) -> Void
- class KMVerificationCodeView: KMBaseXibView {
- @IBOutlet weak var titleLabel: NSTextField!
- @IBOutlet weak var describeLabel: NSTextField!
- @IBOutlet var timerTextView: NSTextView!
-
- @IBOutlet weak var cancellationButton: NSButton!
- @IBOutlet weak var cancelButton: NSButton!
- @IBOutlet weak var closeButton: NSButton!
-
- @IBOutlet weak var textFieldContentView: NSView!
- @IBOutlet weak var code1ContentView: NSView!
- @IBOutlet weak var code1TextField: KMBaseTextField!
-
- @IBOutlet weak var code2ContentView: NSView!
- @IBOutlet weak var code2TextField: KMBaseTextField!
-
- @IBOutlet weak var code3ContentView: NSView!
- @IBOutlet weak var code3TextField: KMBaseTextField!
-
- @IBOutlet weak var code4ContentView: NSView!
- @IBOutlet weak var code4TextField: KMBaseTextField!
-
- @IBOutlet weak var code5ContentView: NSView!
- @IBOutlet weak var code5TextField: KMBaseTextField!
-
- @IBOutlet weak var code6ContentView: NSView!
- @IBOutlet weak var code6TextField: KMBaseTextField!
-
- @IBOutlet weak var doneButtonTopConstraint: NSLayoutConstraint!
- @IBOutlet weak var alertView: KMLightMemberAlertView!
-
- @IBOutlet weak var alertHeightConstraint: NSLayoutConstraint!
- @IBOutlet weak var closeBox: KMBox!
-
- var cancellationButtonVC: KMDesignButton!
- var cancelButtonVC: KMDesignButton!
-
- var cancelAction: KMVerificationCodeViewCancelAction?
- var doneAction: KMVerificationCodeViewDoneAction?
- var closeAction: KMVerificationCodeViewCloseAction?
- var reSendAction: KMVerificationCodeViewReSendAction?
- var verificationCodeAction: KMVerificationCodeViewVerificationCodeAction?
-
- var timer: Timer?
- var time: Int = -1
- let startTime = 60
- //验证码
- var verificationCode: String {
- get {
- return self.code1TextField.textField.stringValue + self.code2TextField.textField.stringValue + self.code3TextField.textField.stringValue + self.code4TextField.textField.stringValue + self.code5TextField.textField.stringValue + self.code6TextField.textField.stringValue
- }
- }
- var verificationCodeState: KMRequestServerErrorCodeType = .unknown
- var inputType: KMRegisterLogType = .login {
- didSet {
- switch self.inputType {
- case .register:
- self.verifyCodeType = .register
- case .loginInputPassword:
- self.verifyCodeType = .resetPassword
- case .accountInfo:
- self.verifyCodeType = .logOff
- default:
- KMPrint("")
- }
-
- self.cleanVerificationCode()
- self.reloadData()
- self.updateLanguage()
- }
- }
-
- var verifyCodeType: KMVerifyCodeType = .unknown {
- didSet {
- self.reloadData()
- self.updateLanguage()
- }
- }
-
- var isNetworking: Bool = false //是否正在进行网络请求
- var codeIsTrue: Bool = false //验证码是否正确
- var model: KMRegisterModel = KMRegisterModel()
-
- deinit {
- self.endTimer()
- KMPrint("KMVerificationCodeView dealloc")
- }
-
- override func draw(_ dirtyRect: NSRect) {
- super.draw(dirtyRect)
- // Drawing code here.
- }
-
- override func setup() {
- super.setup()
-
- self.backgroundColor(NSColor.km_init(hex: "#FFFFFF"))
-
- self.titleLabel.font = NSFont.SFProTextSemiboldFont(20.0)
- self.titleLabel.textColor = NSColor.km_init(hex: "#252629")
-
- self.describeLabel.font = NSFont.SFProTextRegularFont(14.0)
- self.describeLabel.textColor = NSColor.km_init(hex: "#252629")
-
- self.timerTextView.delegate = self
- self.timerTextView.frame = (self.timerTextView.enclosingScrollView?.contentView.bounds)!
- self.timerTextView.autoresizingMask = [.width, .height]
-
- let textFieldArray = [self.code1TextField,self.code2TextField,self.code3TextField,self.code4TextField,self.code5TextField,self.code6TextField]
-
- for i in 0...textFieldArray.count - 1 {
- let textField = textFieldArray[i]
- if textField != nil {
- textField!.textField.textColor = NSColor.km_init(hex: "#252629")
- textField!.textField.font = NSFont.SFProTextSemiboldFont(20.0)
- textField?.maxLen = 1
- textField?.model.isCanNull = true
- textField?.textField.tag = i + 10
- textField!.textField.alignment = .center
- textField?.superview?.border(NSColor.km_init(hex: "#DFE1E5"), 1, 2)
- textField?.textField.onFocus = { [unowned self] in
- self.cancelAllTextFieldFouce()
- textField?.superview?.border(NSColor.km_init(hex: "#1770F4"), 1, 2)
- }
-
- textField?.textDidEndEditing = { [unowned self] string in
- textField?.superview?.border(NSColor.km_init(hex: "#DFE1E5"), 1, 2)
- }
-
- textField?.textDidChange = { [unowned self] string in
- //自动验证验证码
- self.autoVerificationCode()
-
- var isNext = true
- if string == "" {
- isNext = false
- }
- for item in textFieldArray {
- let t = textField?.textField
- var tag = t!.tag + 1
- if !isNext {
- tag = t!.tag - 1
- }
- tag = max(10, tag)
- if item?.textField.tag == tag {
- item?.textField.becomeFirstResponder()
- item?.superview?.border(NSColor.km_init(hex: "#1770F4"), 1, 2)
- break
- }
- }
- }
-
- textField?.textDeleteAction = { [unowned self] string in
- if string == "" {
- for item in textFieldArray {
- let t = textField?.textField
- let tag = max(10, t!.tag - 1)
- if item?.textField.tag == tag {
- item?.textField.becomeFirstResponder()
- item?.superview?.border(NSColor.km_init(hex: "#1770F4"), 1, 2)
- break
- }
- }
- }
- }
- }
- }
-
- self.cancellationButtonVC = KMDesignButton(withType: .Text)
- self.cancellationButton.addSubview(self.cancellationButtonVC.view)
- self.cancellationButtonVC?.view.frame = self.cancellationButton.bounds
- self.cancellationButtonVC.target = self
- self.cancellationButtonVC.action = #selector(doneButtonAction)
- self.cancellationButtonVC.button(type: .Cta, size: .m)
- self.cancellationButtonVC.button.keyEquivalent = KMKeyEquivalent.enter
-
- self.cancelButtonVC = KMDesignButton(withType: .Text)
- self.cancelButton.addSubview(self.cancelButtonVC.view)
- self.cancelButtonVC?.view.frame = self.cancelButton.bounds
- self.cancelButtonVC.target = self
- self.cancelButtonVC.action = #selector(cancelButtonAction)
- self.cancelButtonVC.button(type: .Sec, size: .m)
- self.cancelButtonVC.button.keyEquivalent = KMKeyEquivalent.enter
-
- self.closeBox.moveCallback = { [weak self] (mouseEntered, mouseBox) in
- if mouseEntered {
- self?.closeButton.image = NSImage(named: "control_btn_icon_close_hov")
- } else {
- self?.closeButton.image = NSImage(named: "control_btn_icon_close")
- }
- }
- }
-
- override func reloadData() {
- super.reloadData()
-
- if inputType == .accountInfo {
- self.closeButton.isHidden = false
- self.cancelButtonVC.button(type: .Sec, size: .m)
- self.cancelButtonVC.updateUI()
- } else {
- self.closeButton.isHidden = true
- self.cancelButtonVC.button(type: .Text, size: .m)
- self.cancelButtonVC.updateUI()
- }
-
- let textFieldArray = [self.code1TextField,self.code2TextField,self.code3TextField,self.code4TextField,self.code5TextField,self.code6TextField]
- for item in textFieldArray {
- item?.isEnabled = !self.isNetworking
- }
-
- if self.verificationCode.count == 6 &&
- // self.time != -1 &&
- self.codeIsTrue {
- self.cancellationButtonVC.enabled = true
- } else {
- self.cancellationButtonVC.enabled = false
- self.showAlert(result: Result(code: 0))
- }
- }
-
- override func updateLanguage() {
- super.updateLanguage()
-
- if self.verifyCodeType == .unknown {
- self.titleLabel.stringValue = ""
- } else if self.verifyCodeType == .register {
- self.titleLabel.stringValue = NSLocalizedString("Sign Up", comment: "")
- } else if self.verifyCodeType == .logOff {
- self.titleLabel.stringValue = NSLocalizedString("Cancel Account", comment: "")
- } else if self.verifyCodeType == .resetPassword {
- self.titleLabel.stringValue = NSLocalizedString("Reset Password", comment: "")
- }
-
- self.describeLabel.stringValue = NSLocalizedString("Enter the verification code", comment: "")
-
- if inputType == .unknown {
- self.cancelButtonVC.stringValue = ""
- } else if inputType == .accountInfo {
- self.cancelButtonVC.stringValue = NSLocalizedString("Cancel", comment: "")
- } else {
- self.cancelButtonVC.stringValue = NSLocalizedString("Back to previous step", comment: "")
- }
-
- if self.verifyCodeType == .unknown {
- self.cancellationButtonVC.stringValue = ""
- } else if self.verifyCodeType == .register {
- self.cancellationButtonVC.stringValue = NSLocalizedString("Sign Up", comment: "")
- } else if self.verifyCodeType == .logOff {
- self.cancellationButtonVC.stringValue = NSLocalizedString("Cancellation", comment: "")
- } else if self.verifyCodeType == .resetPassword {
- self.cancellationButtonVC.stringValue = NSLocalizedString("Next Step", comment: "")
- }
-
-
- let tempTime: String = String(self.time)
- var timeString = "(" + tempTime + NSLocalizedString("s", comment: "") + ")"
- if tempTime == "60" {
- timeString = NSLocalizedString("Click to resend", comment: "")
- } else if tempTime == "-1" {
- timeString = " "
- }
- //singin
- let string = NSLocalizedString("Didn't receive the verification code?", comment: "") + " " + timeString
- let attributedString = NSMutableAttributedString.init(string: string)
- let paragraphStyle = NSMutableParagraphStyle()
- paragraphStyle.alignment = .left;
- attributedString.addAttributes([NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0),
- NSAttributedString.Key.foregroundColor : NSColor.km_init(hex: "#252629"),
- NSAttributedString.Key.paragraphStyle : paragraphStyle],
- range: NSRange(location: 0, length: string.count))
- let range = string.range(of: NSLocalizedString(timeString, comment: ""))
- attributedString.setAttributes([NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0),
- NSAttributedString.Key.foregroundColor : NSColor.km_init(hex: "#1770F4"),
- NSAttributedString.Key.underlineColor : NSColor.clear,
- NSAttributedString.Key.link : "timer://"],
- range: string.nsRange(from: range!)!)
- self.timerTextView.textStorage?.setAttributedString(attributedString)
-
- }
-
- func cleanVerificationCode() {
- let textFieldArray = [self.code1TextField,self.code2TextField,self.code3TextField,self.code4TextField,self.code5TextField,self.code6TextField]
- for item in textFieldArray {
- item?.stringValue = ""
- item?.textField.resignFirstResponder()
-
- if item != self.code1TextField {
- item?.superview?.border(NSColor.km_init(hex: "#DFE1E5"), 1, 2)
- }
- }
- self.model.verifyCode = ""
- }
-
- //验证码请求完成
- func updateNetworkingState(complete: Bool, codeIsTure: Bool) {
- self.isNetworking = !complete
- self.codeIsTrue = codeIsTure
- self.reloadData()
- if !codeIsTure {
- self.code6TextField.textField.becomeFirstResponder()
- }
- }
-
- //自动验证验证码
- func autoVerificationCode() {
- let textFieldArray = [self.code1TextField,self.code2TextField,self.code3TextField,self.code4TextField,self.code5TextField,self.code6TextField]
- for item in textFieldArray {
- item?.textField.resignFirstResponder()
- }
-
- if self.verificationCode.count == 6 {
- if self.verificationCodeAction != nil {
- self.isNetworking = true
- self.model.verifyCode = self.verificationCode
- self.verificationCodeAction!(self, self.model, self.verificationCode)
- }
- }
- }
- }
- protocol KMVerificationCodeViewTimer {}
- extension KMVerificationCodeView: KMVerificationCodeViewTimer {
- func cleanTimer() {
- self.time = startTime
- self.updateLanguage()
- }
-
- func resetTimer() {
- self.time = startTime
- self.beginTimer()
- self.updateTimerData(timer: self.timer!)
- }
-
- func beginTimer() {
- if self.timer != nil {
- self.endTimer()
- }
- if self.time == -1 {
- self.time = startTime
- }
- self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimerData), userInfo: nil, repeats: true)
- }
-
- func endTimer() {
- self.timer?.invalidate()
- self.timer = nil
- self.updateLanguage()
- }
-
- @objc func updateTimerData(timer: Timer) {
- self.time -= 1
- if self.time == 0 {
- self.endTimer()
- self.time = startTime
- }
- self.updateLanguage()
- }
- }
- protocol KMVerificationCodeViewAction {}
- extension KMVerificationCodeView: KMVerificationCodeViewAction {
- func sendVerificationCode() {
- guard let callBack = reSendAction else { return }
- self.timerTextView.isSelectable = false
- callBack(self, self.timerTextView)
- }
-
- @IBAction func cancelButtonAction(_ sender: NSButton) {
- self.endTimer()
- guard let callBack = cancelAction else { return }
-
- callBack(self)
- }
-
- @IBAction func doneButtonAction(_ sender: NSButton) {
- guard let callBack = doneAction else { return }
- self.model.verifyCode = self.verificationCode
-
- self.changeDoneButtonState(enable: false)
- callBack(self, self.model, sender)
- }
-
- @IBAction func closeButtonAction(_ sender: Any) {
- guard let callBack = closeAction else { return }
- self.endTimer()
- callBack(self)
- }
-
- func showAlert(result: Result?) {
- if result != nil {
- self.alertView.result = result!
- self.alertHeightConstraint.constant = self.alertView.fetchAlertHeight()
-
- if result?.code != 0 && result?.code != 200 {
- self.textFieldAlert()
- }
- }
- }
-
- func changeDoneButtonState(enable: Bool) {
- self.cancellationButtonVC.enabled = enable
- }
-
- func cancelAllTextFieldFouce() {
- let textFieldArray = [self.code1TextField,self.code2TextField,self.code3TextField,self.code4TextField,self.code5TextField,self.code6TextField]
- for item in textFieldArray {
- item?.superview?.border(NSColor.km_init(hex: "#DFE1E5"), 1, 2)
- }
- }
-
- func textFieldAlert() {
- let textFieldArray = [self.code1TextField,self.code2TextField,self.code3TextField,self.code4TextField,self.code5TextField,self.code6TextField]
- for item in textFieldArray {
- item?.superview?.border(NSColor.red, 1, 2)
- }
- }
- }
- extension KMVerificationCodeView: NSTextViewDelegate {
- func textView(_ textView: NSTextView, clickedOnLink link: Any, at charIndex: Int) -> Bool {
- if link as! String == "timer://" && self.time == 60 {
- guard let callBack = reSendAction else { return true }
- textView.isSelectable = false
- callBack(self, textView)
- }
- return true
- }
- }
- extension KMVerificationCodeView: NSTextFieldDelegate {
- func controlTextDidEndEditing(_ obj: Notification) {
- KMPrint("controlTextDidEndEditing")
- let textField = obj.object as? NSTextField
- for view in self.textFieldContentView.subviews {
- let t = view.subviews.first as? FocusAwareTextField
- if t == textField {
- view.border(NSColor.km_init(hex: "#DFE1E5"), 1, 4)
- }
- }
- }
- }
- extension KMVerificationCodeView {
- override var acceptsFirstResponder: Bool {
- return true
- }
-
- override func performKeyEquivalent(with event: NSEvent) -> Bool {
- if event.type == .keyDown, event.modifierFlags.contains(.command), event.characters == "v" {
- if let pasteboardString = NSPasteboard.general.string(forType: .string) {
- KMPrint(pasteboardString)
- if let num = Int(pasteboardString) {
- let textFieldArray = [self.code1TextField,self.code2TextField,self.code3TextField,self.code4TextField,self.code5TextField,self.code6TextField]
- for index in 0...textFieldArray.count - 1 {
- if index < pasteboardString.count {
- let textField = textFieldArray[index]
- let fifthChar = pasteboardString[pasteboardString.index(pasteboardString.startIndex, offsetBy: index)]
- textField?.textField.stringValue = String(fifthChar)
- textField?.stringValue = String(fifthChar)
- textField?.textField.becomeFirstResponder()
- }
- }
- if pasteboardString.count == 6 {
- self.autoVerificationCode()
- }
- }
- // 处理剪贴板中的字符串
- return true
- }
- }
- return super.performKeyEquivalent(with: event)
- }
- }
|