// // KMEnterVerificationCodeView.swift // PDF Reader Pro // // Created by wanjun on 2024/10/29. // /** 重置密码(输入验证码) */ import Cocoa import Combine class KMEnterVerificationCodeView: KMBaseXibView { @IBOutlet weak var resetPasswordsLabel: NSTextField! @IBOutlet weak var tipLabel: NSTextField! @IBOutlet weak var verifficationView: NSView! @IBOutlet weak var verifficationBox: NSBox! @IBOutlet weak var verifficationTextField: NSTextField! @IBOutlet weak var sendBox: KMBox! @IBOutlet weak var sendLabel: NSTextField! @IBOutlet weak var verifficationErrorLabel: NSTextField! @IBOutlet weak var nextBox: NSBox! @IBOutlet weak var nextButton: NSButton! @IBOutlet weak var backButton: NSButton! private var viewModel = KMSignUpViewModel() private var cancellables = Set() convenience init(model: KMSignUpViewModel, superView: NSView) { self.init(frame: superView.bounds) viewModel = model viewModel.screenType = .enterVerificationCode loadUI() } public override init(frame frameRect: NSRect) { super.init(frame: frameRect) } public required init?(coder decoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func updateUI() { super.updateUI() loadUI() } // MARK: Private Method private func loadUI() -> Void { viewModel.sendContent = "60" bindViewModel() languageLocalized() initializeUI() sendBoxRefresh() viewModel.countDown(type: .reset) { result , params in if let data = params.first as? KMMemberCenterResult { if data.code == KMMemberCenterErrorCodeType.VERIFY_CODE_SEND_TOO_QUICKLY.rawValue { KMMainThreadExecute { let alert = NSAlert() let message = data.msg ?? KMMemberCenterManager.typeOfMessage(type: .VERIFY_CODE_SEND_TOO_QUICKLY) alert.messageText = NSLocalizedString(message, comment: "") alert.runModal() } } } } sendBox.moveCallback = { [weak self](mouseEntered: Bool, mouseBox: KMBox) -> Void in guard let self = self else { return } if self.viewModel.email.count <= 0 { return } if self.viewModel.sendBoxSelect { return } if mouseEntered { self.sendBox.fillColor = NSColor(named: "000000_0.1") ?? NSColor.blue self.sendBox.borderWidth = 1 } else { self.sendBox.fillColor = NSColor(named: "273C62") ?? NSColor.blue } } sendBox.downCallback = { [weak self](downEntered: Bool, mouseBox: KMBox, event) -> Void in guard let self = self else { return } if self.viewModel.email.count <= 0 { return } if self.viewModel.sendBoxSelect { return } if downEntered { self.sendBox.fillColor = NSColor(named: "273C62_0.4") ?? NSColor.blue self.viewModel.countDown(type: .reset, callback: nil) } } } private func languageLocalized() -> Void { resetPasswordsLabel.stringValue = NSLocalizedString("Reset Password", tableName: "MemberCenterLocalizable", comment: "") tipLabel.stringValue = String(format: "%@%@", NSLocalizedString("We have sent you a code via email to", tableName: "MemberCenterLocalizable", comment: ""), viewModel.email) verifficationTextField.placeholderString = NSLocalizedString("Please enter code", tableName: "MemberCenterLocalizable", comment: "") verifficationErrorLabel.stringValue = viewModel.passwordErrorMessage nextButton.title = NSLocalizedString("Next", tableName: "MemberCenterLocalizable", comment: "") backButton.title = NSLocalizedString("Previous Step", tableName: "MemberCenterLocalizable", comment: "") } private func initializeUI() -> Void { verifficationBox.fillColor = NSColor(named: "texefiedfillcolor") ?? NSColor.white verifficationBox.borderColor = NSColor(named: "DADBDE") ?? NSColor.gray verifficationTextField.delegate = self resetPasswordsLabel.textColor = NSColor(named: "000000") resetPasswordsLabel.font = NSFont.SFMediumFontWithSize(20) tipLabel.textColor = NSColor(named: "0E1114") tipLabel.font = NSFont.SFProTextRegularFont(12) sendLabel.textColor = NSColor(named: "FFFFFF") ?? NSColor.white sendLabel.font = NSFont.SFProTextRegularFont(13) verifficationErrorLabel.isHidden = viewModel.passwordError() verifficationErrorLabel.textColor = NSColor(named: "FA1E5D") verifficationErrorLabel.font = NSFont.SFProTextRegularFont(9) nextBox.fillColor = NSColor(named: "273C62") ?? NSColor.blue nextButton.setTitleColor(color: NSColor(named: "FFFFFF") ?? NSColor.white, font: NSFont.SFProTextRegularFont(13)) backButton.setTitleColor(color: NSColor(named: "4982E6") ?? NSColor.blue, font: NSFont.SFProTextRegularFont(12)) } private func sendBoxRefresh() -> Void { sendLabel.stringValue = viewModel.sendContent if viewModel.sendContent == NSLocalizedString("Send", tableName: "MemberCenterLocalizable", comment: "") || viewModel.sendContent == NSLocalizedString("Resend", tableName: "MemberCenterLocalizable", comment: "") { if viewModel.email.count > 0 { if viewModel.isValidEmail() { sendBox.fillColor = NSColor(named: "273C62") ?? NSColor.blue } else { sendBox.fillColor = NSColor(named: "273C62_0.4") ?? NSColor.blue } } else { sendBox.fillColor = NSColor(named: "273C62_0.4") ?? NSColor.blue } sendLabel.textColor = NSColor(named: "FFFFFF") ?? NSColor.white } else { sendBox.fillColor = NSColor(named: "DADBDE") ?? NSColor.gray sendLabel.stringValue = String(format: "%@s", viewModel.sendContent) sendLabel.textColor = NSColor(named: "0E1114") ?? NSColor.black } } private func skipEnterNewPasswordView() -> Void { guard let parentView = self.superview else { return } if parentView is NSBox { let codeView = KMEnterNewPasswordView(model: viewModel, superView: parentView) NSAnimationContext.runAnimationGroup { context in context.duration = 0.3 self.animator().alphaValue = 0 } completionHandler: { self.removeFromSuperview() codeView.alphaValue = 0 (parentView as! NSBox).contentView = codeView NSAnimationContext.runAnimationGroup({ context in context.duration = 0.3 codeView.animator().alphaValue = 1 }, completionHandler: nil) } } else { guard let parentView = self.superview else { return } let codeView = KMEnterNewPasswordView(model: viewModel, superView: parentView) NSAnimationContext.runAnimationGroup { context in context.duration = 0.3 self.animator().alphaValue = 0 } completionHandler: { self.removeFromSuperview() codeView.alphaValue = 0 parentView.addSubview(codeView) NSAnimationContext.runAnimationGroup({ context in context.duration = 0.3 codeView.animator().alphaValue = 1 }, completionHandler: nil) } } } // MARK: Bind Method func bindViewModel() -> Void { viewModel.$sendContent .receive(on: RunLoop.main) .sink { [weak self] newValue in self?.sendBoxRefresh() } .store(in: &cancellables) viewModel.$passwordErrorMessage .receive(on: RunLoop.main) .sink { [weak self] newValue in self?.verifficationErrorLabel.stringValue = self?.viewModel.passwordErrorMessage ?? "" if self?.verifficationErrorLabel.stringValue.isEmpty == false { self?.verifficationErrorLabel.isHidden = false self?.verifficationBox.borderColor = NSColor(named: "FA1E5D") ?? NSColor.red } else { self?.verifficationErrorLabel.isHidden = true self?.verifficationBox.borderColor = NSColor(named: "DADBDE") ?? NSColor.red } } .store(in: &cancellables) viewModel.$verificationCode .receive(on: RunLoop.main) .sink { [weak self] newValue in if newValue.count <= 6 && newValue.count >= 0 { self?.viewModel.passwordErrorMessage = "" } else { self?.viewModel.passwordErrorMessage = NSLocalizedString("Verification code error.", tableName: "MemberCenterLocalizable", comment: "") } } .store(in: &cancellables) } // MARK: Action Method @IBAction func nextButtonAction(_ sender: NSButton) { if viewModel.verificationCode.count <= 0 || viewModel.verificationCode.count > 6 || !viewModel.isValidVerificationCode() { viewModel.passwordErrorMessage = NSLocalizedString("Verification code error.", tableName: "MemberCenterLocalizable", comment: "") return } viewModel.passwordErrorMessage = "" viewModel.enterVerificationCodeNextAction() { [weak self] success, msg in guard let self = self else { return } if success { self.skipEnterNewPasswordView() } } } @IBAction func backButtonAction(_ sender: NSButton) { guard let parentView = self.superview else { return } if parentView is NSBox { let model = KMSignUpViewModel() model.email = viewModel.email let forgotView = KMForgotPasswordView(model: model, superView: parentView) NSAnimationContext.runAnimationGroup { context in context.duration = 0.3 self.animator().alphaValue = 0 } completionHandler: { self.removeFromSuperview() forgotView.alphaValue = 0 (parentView as! NSBox).contentView = forgotView NSAnimationContext.runAnimationGroup({ context in context.duration = 0.3 forgotView.animator().alphaValue = 1 }, completionHandler: nil) } } else { let model = KMSignUpViewModel() model.email = viewModel.email let forgotView = KMForgotPasswordView(model: model, superView: parentView) NSAnimationContext.runAnimationGroup { context in context.duration = 0.3 self.animator().alphaValue = 0 } completionHandler: { self.removeFromSuperview() forgotView.alphaValue = 0 parentView.addSubview(forgotView) NSAnimationContext.runAnimationGroup({ context in context.duration = 0.3 forgotView.animator().alphaValue = 1 }, completionHandler: nil) } } } } extension KMEnterVerificationCodeView: NSTextFieldDelegate { func controlTextDidEndEditing(_ obj: Notification) { let textField = obj.object as? NSTextField if textField == verifficationTextField { viewModel.verificationCode = textField!.stringValue } } func controlTextDidChange(_ obj: Notification) { let textField = obj.object as? NSTextField if textField == verifficationTextField { viewModel.verificationCode = textField!.stringValue viewModel.passwordErrorMessage = "" } } }