// // LNLoginCaptchaInputViewController.swift // Gami // // Created by OneeChan on 2026/1/16. // import Foundation import UIKit import SnapKit extension UIView { func pushToLoginCaptcha(code: String, phone: String) { let vc = LNLoginCaptchaInputViewController(code: code, phone: phone) navigationController?.pushViewController(vc, animated: true) } } class LNLoginCaptchaInputViewController: LNViewController { private let code: String private let phone: String private let captchaInput = LNCaptchaInputView() private let tipsView = LNAutoSizeTextView() init(code: String, phone: String) { self.code = code self.phone = phone super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() setupViews() LNEventDeliver.addObserver(self) } } extension LNLoginCaptchaInputViewController: LNAccountManagerNotify { func onLoginCaptchaCoolDownChanged(time: Int) { if time == 0 { let text = NSMutableAttributedString(string: .init(key: "B00028"), attributes: [ .foregroundColor: UIColor.text_5 ]) let resend = NSMutableAttributedString(string: .init(key: "B00029"), attributes: [ .font: UIFont.heading_h4, .link: "Gami:resend", ]) text.append(.init(string: " ")) text.append(resend) tipsView.attributedText = text } else { let text: String = .init(key: "B00027") + " (\(time)s)" tipsView.attributedText = .init(string: text, attributes: [ .foregroundColor: UIColor.text_3 ]) } } } extension LNLoginCaptchaInputViewController: UITextViewDelegate { func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { showLoading() LNAccountManager.shared.getLoginCaptcha(code: code, phone: phone) { [weak self] success in dismissLoading() guard self != nil else { return } guard success else { return } showToast(.init(key: "B00030")) } return false } func textViewDidChangeSelection(_ textView: UITextView) { textView.selectedTextRange = nil } } extension LNLoginCaptchaInputViewController: LNCaptchaInputViewDelegate { func onCaptchaInputChange(view: LNCaptchaInputView) { guard view.hasDone else { return } LNAccountManager.shared.loginByPhone(code: code, num: phone, captcha: view.curInput) } } extension LNLoginCaptchaInputViewController { private func setupViews() { navigationBarColor = .clear let cover = UIImageView(image: .icLoginProfileBg) view.addSubview(cover) cover.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalTo(fakeNaviBgView) } let textView = buildTextView() view.addSubview(textView) textView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(22) make.top.equalToSuperview().offset(20) } captchaInput.delegate = self captchaInput.startInput() view.addSubview(captchaInput) captchaInput.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(22) make.top.equalTo(textView.snp.bottom).offset(24) make.height.equalTo(64) } let tipsView = buildCoolDown() view.addSubview(tipsView) tipsView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(22 - 4) make.top.equalTo(captchaInput.snp.bottom).offset(24 - 7) // 7 是 UITextView 自身的内容缩进 } view.onTap { [weak self] in guard let self else { return } view.endEditing(true) } } private func buildTextView() -> UIView { let container = UIView() let titleLabel = UILabel() titleLabel.text = .init(key: "B00025") titleLabel.font = .heading_h1 titleLabel.textColor = .text_5 container.addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalToSuperview() } let descLabel = UILabel() descLabel.text = .init(key: "B00026") + "\n\(code) \(phone)" descLabel.font = .body_m descLabel.textColor = .text_4 descLabel.numberOfLines = 0 container.addSubview(descLabel) descLabel.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalTo(titleLabel.snp.bottom).offset(13) make.bottom.equalToSuperview() } return container } private func buildCoolDown() -> UIView { tipsView.font = .body_m tipsView.isEditable = false tipsView.delegate = self tipsView.showsVerticalScrollIndicator = false tipsView.showsHorizontalScrollIndicator = false tipsView.backgroundColor = .clear tipsView.linkTextAttributes = [.foregroundColor: UIColor.text_6] return tipsView } }