// // LNJoinUsInputCaptchaView.swift // Gami // // Created by OneeChan on 2026/1/19. // import Foundation import UIKit import SnapKit protocol LNJoinUsInputCaptchaViewDelegate: AnyObject { func joinUsInputCaptchaViewDidFinish(view: LNJoinUsInputCaptchaView) } class LNJoinUsInputCaptchaView: UIView { private var code: String? private var phone: String? private let descLabel = UILabel() private let captchaInput = LNCaptchaInputView() private let tipsView = LNAutoSizeTextView() weak var delegate: LNJoinUsInputCaptchaViewDelegate? override var isHidden: Bool { didSet { if !isHidden { captchaInput.startInput() } } } override init(frame: CGRect) { super.init(frame: frame) setupViews() LNEventDeliver.addObserver(self) } func update(_ code: String, phone: String) { self.code = code self.phone = phone descLabel.text = .init(key: "B00026") + ": \(code) \(phone)" } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension LNJoinUsInputCaptchaView: LNProfileManagerNotify { func onBindPhoneCaptchaCoolDownChanged(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 LNJoinUsInputCaptchaView: UITextViewDelegate { func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { guard let code, let phone else { return false} showLoading() LNProfileManager.shared.getBindPhoneCaptcha(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 LNJoinUsInputCaptchaView: LNCaptchaInputViewDelegate { func onCaptchaInputChange(view: LNCaptchaInputView) { guard let code, let phone else { return } guard view.hasDone else { return } LNProfileManager.shared.bindPhone( code: code, phone: phone, captcha: view.curInput) { [weak self] success in guard let self else { return } guard success else { return } delegate?.joinUsInputCaptchaViewDidFinish(view: self) } } } extension LNJoinUsInputCaptchaView { private func setupViews() { onTap { [weak self] in guard let self else { return } endEditing(true) } let titleLabel = UILabel() titleLabel.font = .heading_h2 titleLabel.textColor = .text_5 titleLabel.text = .init(key: "B00035") titleLabel.textAlignment = .center addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(16) make.top.equalToSuperview().offset(26) } descLabel.font = .body_m descLabel.textColor = .text_4 descLabel.numberOfLines = 0 addSubview(descLabel) descLabel.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(22) make.top.equalTo(titleLabel.snp.bottom).offset(20) } captchaInput.delegate = self captchaInput.inputViews.forEach { $0.superview?.backgroundColor = .fill_2 } addSubview(captchaInput) captchaInput.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(22) make.top.equalTo(descLabel.snp.bottom).offset(20) make.height.equalTo(64) } let tipsView = buildCoolDown() addSubview(tipsView) tipsView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(22 - 4) make.top.equalTo(captchaInput.snp.bottom).offset(20 - 7) // 7 是 UITextView 自身的内容缩进 } } 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 } }