| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- //
- // LNJoinUsInputPhoneView.swift
- // Gami
- //
- // Created by OneeChan on 2026/1/19.
- //
- import Foundation
- import UIKit
- import SnapKit
- protocol LNJoinUsInputPhoneViewDelegate: AnyObject {
- func joinUsInputPhoneView(view: LNJoinUsInputPhoneView, didFinished code: String, phone: String)
- }
- class LNJoinUsInputPhoneView: UIView {
- private let countryIcon = UIImageView()
- private let countryCodeLabel = UILabel()
- private let phoneInputView = LNTextField()
-
- private let confirmButton = UIButton()
-
- private var sections: [(code: String, list: [LNCountryCodeVO])] = []
-
- weak var delegate: LNJoinUsInputPhoneViewDelegate?
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- setupViews()
-
- LNEventDeliver.addObserver(self)
- loadCountryCodeList()
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension LNJoinUsInputPhoneView {
- private func loadCountryCodeList() {
- LNConfigManager.shared.getCountryCodeList { [weak self] list in
- guard let self else { return }
- guard let list else { return }
-
- sortList(list)
- }
- }
-
- private func sortList(_ list: [LNCountryCodeVO]) {
- sections.removeAll()
-
- var map: [String: [LNCountryCodeVO]] = [:]
- for item in list {
- let first = item.name.classificationFirstLetter
- var section = map[first] ?? []
- section.append(item)
- map[first] = section
- }
-
- let keys = map.keys.sorted()
- for key in keys {
- sections.append((key, map[key]) as! (code: String, list: [LNCountryCodeVO]))
- }
-
- var item: LNCountryCodeVO? = list.first {
- $0.code == LNAppConfig.shared.curLang.countryCode
- }
- if item == nil {
- item = list.first {
- $0.code == LNAppLanguage.indonesian.countryCode
- }
- }
- if let item {
- countryIcon.sd_setImage(with: URL(string: item.icon))
- countryCodeLabel.text = item.num
- }
- }
- }
- extension LNJoinUsInputPhoneView: LNProfileManagerNotify {
- func onBindPhoneCaptchaCoolDownChanged(time: Int) {
- let text: String = if time == 0 {
- .init(key: "B00023")
- } else {
- .init(key: "B00023") + " (\(time)s)"
- }
- confirmButton.setTitle(text, for: .normal)
- checkConfirmButton()
- }
- }
- extension LNJoinUsInputPhoneView {
- private func checkConfirmButton() {
- let text = phoneInputView.text ?? ""
- confirmButton.isEnabled = !text.isEmpty && LNProfileManager.shared.canSendCaptcha
- }
-
- 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)
- }
-
- let phoneInput = buildPhoneInput()
- addSubview(phoneInput)
- phoneInput.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(22)
- make.top.equalTo(titleLabel.snp.bottom).offset(30)
- }
-
- let confirm = buildConfirmButton()
- addSubview(confirm)
- confirm.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(22)
- make.top.equalTo(phoneInput.snp.bottom).offset(24)
- }
- }
-
- private func buildPhoneInput() -> UIView {
- let container = UIView()
- container.backgroundColor = .fill_2
- container.layer.cornerRadius = 26
- container.snp.makeConstraints { make in
- make.height.equalTo(52)
- }
-
- let countryView = UIView()
- countryView.onTap { [weak self] in
- guard let self else { return }
- guard !sections.isEmpty else { return }
-
- let panel = LNCountrySelectPanel()
- panel.containerHeight = .height(superview!.bounds.height)
- panel.update(sections)
- panel.handler = { [weak self] item in
- guard let self else { return }
- countryIcon.sd_setImage(with: URL(string: item.icon))
- countryCodeLabel.text = item.num
- }
- panel.popup()
- }
- container.addSubview(countryView)
- countryView.snp.makeConstraints { make in
- make.verticalEdges.equalToSuperview()
- make.leading.equalToSuperview()
- }
-
- countryIcon.layer.cornerRadius = 12
- countryIcon.clipsToBounds = true
- countryView.addSubview(countryIcon)
- countryIcon.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalToSuperview().offset(16)
- make.width.height.equalTo(24)
- }
-
- countryCodeLabel.font = .heading_h2
- countryCodeLabel.textColor = .text_5
- countryCodeLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
- countryCodeLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
- countryView.addSubview(countryCodeLabel)
- countryCodeLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalTo(countryIcon.snp.trailing).offset(4)
- }
-
- let config = UIImage.SymbolConfiguration(pointSize: 10)
- let arrow = UIImageView()
- arrow.image = .init(systemName: "chevron.down", withConfiguration: config)?.withRenderingMode(.alwaysTemplate)
- arrow.tintColor = .text_5
- countryView.addSubview(arrow)
- arrow.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalTo(countryCodeLabel.snp.trailing).offset(4)
- make.trailing.equalToSuperview()
- make.width.equalTo(12)
- }
-
- phoneInputView.font = .heading_h2
- phoneInputView.textColor = .text_5
- phoneInputView.attributedPlaceholder = .init(string: .init(key: "B00021"), attributes: [
- .font: UIFont.body_l,
- .foregroundColor: UIColor.text_2
- ])
- phoneInputView.clearButtonMode = .always
- phoneInputView.keyboardType = .numberPad
- phoneInputView.cursorWidth = 2
- phoneInputView.cursorHeight = 18
- phoneInputView.addAction(UIAction(handler: { [weak self] _ in
- guard let self else { return }
- checkConfirmButton()
- }), for: .editingChanged)
- container.addSubview(phoneInputView)
- phoneInputView.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalTo(countryView.snp.trailing).offset(12)
- make.trailing.equalToSuperview().offset(-12)
- }
-
- return container
- }
-
- private func buildConfirmButton() -> UIView {
- confirmButton.setBackgroundImage(.primary_8, for: .normal)
- confirmButton.layer.cornerRadius = 23.5
- confirmButton.clipsToBounds = true
- confirmButton.setTitle(.init(key: "B00023"), for: .normal)
- confirmButton.setTitleColor(.text_1, for: .normal)
- confirmButton.titleLabel?.font = .heading_h3
- confirmButton.isEnabled = false
- confirmButton.addAction(UIAction(handler: { [weak self] _ in
- guard let self else { return }
- let code = countryCodeLabel.text
- let phone = phoneInputView.text
- guard let code, let phone else { return }
- showLoading()
- LNProfileManager.shared.getBindPhoneCaptcha(code: code, phone: phone)
- { [weak self] success in
- dismissLoading()
- guard let self else { return }
- guard success else { return }
-
- delegate?.joinUsInputPhoneView(view: self, didFinished: code, phone: phone)
- }
- }), for: .touchUpInside)
- confirmButton.snp.makeConstraints { make in
- make.height.equalTo(47)
- }
-
- return confirmButton
- }
- }
|