| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- //
- // MOLineSearchUserView.swift
- // MiMoLive
- //
- // Created by OneeChan on 2025/9/25.
- //
- import Foundation
- import UIKit
- class MOLineSearchUserView: UIView, MOPopupViewProtocol {
- private let curType: LineType
- private var userList: [MOLivePkLinkInviteVO] = []
- private var nextTag = ""
- private var curKey = ""
-
- let container = UIView()
- let containerHeight: PopupViewHeight = .percent(0.7)
- private let noMoreDataView = MONoMoreDataView()
- private let tableView = UITableView()
- private let input = UITextField()
- private let clearButton = UIButton()
-
- init(type: LineType) {
- self.curType = type
-
- super.init(frame: .zero)
-
- setupViews()
-
- // reload()
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension MOLineSearchUserView {
- private func reload() {
- MOLineViewModel.loadLineMatchUsers(nil, curKey) { [weak self] list, hasMore in
- guard let self else { return }
- self.tableView.mj_header?.endRefreshing()
-
- guard let list else { return }
-
- self.noMoreDataView.isHaveData = !list.list.isEmpty
- self.userList = list.list
- self.nextTag = list.next
-
- if !hasMore {
- self.tableView.mj_footer?.endRefreshingWithNoMoreData()
- }
- self.tableView.reloadData()
- }
- }
-
- @objc
- private func loadNext() {
- guard !self.nextTag.isEmpty else {
- self.tableView.mj_footer?.endRefreshing()
- return
- }
- MOLineViewModel.loadLineMatchUsers(nextTag, curKey) { [weak self] list, hasMore in
- guard let self else { return }
- self.tableView.mj_footer?.endRefreshing()
-
- guard let list else { return }
- self.userList.append(contentsOf: list.list)
- self.nextTag = list.next
-
- if !hasMore {
- self.tableView.mj_footer?.endRefreshingWithNoMoreData()
- }
- self.tableView.reloadData()
- }
- }
- }
- extension MOLineSearchUserView {
- @objc
- private func handleBgClick() {
- input.resignFirstResponder()
- dismissH()
- }
-
- @objc
- private func handleClearClick() {
- input.text = ""
- clearButton.isHidden = true
- }
- }
- extension MOLineSearchUserView: UITableViewDataSource, UITableViewDelegate {
- func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
- 64
- }
-
- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- userList.count
- }
-
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let cell = tableView.dequeueReusableCell(withIdentifier: MOLineUserListCell.className())
- if indexPath.row < userList.count, let cell = cell as? MOLineUserListCell {
- cell.updateContent(MOLineUserListItemData(curType: curType, item: userList[indexPath.row]))
- }
- return cell!
- }
- }
- extension MOLineSearchUserView: UITextFieldDelegate {
- func textFieldShouldReturn(_ textField: UITextField) -> Bool {
- textField.resignFirstResponder()
-
- curKey = textField.text ?? ""
- reload()
-
- return true
- }
-
- @objc
- private func textFieldDidChanged(_ textField: UITextField) {
- clearButton.isHidden = textField.text?.isEmpty != false
- }
- }
- extension MOLineSearchUserView {
- private func setupViews() {
- let button = UIButton()
- button.addTarget(self, action: #selector(handleBgClick), for: .touchUpInside)
- addSubview(button)
- button.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- }
-
- container.backgroundColor = .white
- container.layer.cornerRadius = 16
- container.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
- addSubview(container)
-
- let match = buildSearch()
- container.addSubview(match)
- match.snp.makeConstraints { make in
- make.leading.equalToSuperview()
- make.trailing.equalToSuperview()
- make.top.equalToSuperview()
- }
-
- let list = buildList()
- container.addSubview(list)
- list.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(12)
- make.trailing.equalToSuperview().offset(-12)
- make.bottom.equalToSuperview()
- make.top.equalTo(match.snp.bottom)
- }
- }
-
- private func buildSearch() -> UIView {
- let container = UIView()
-
- let cancel = UIButton()
- cancel.setTitle("Cancel", for: .normal)
- cancel.setTitleColor(.init(hex: "#17171A"), for: .normal)
- cancel.titleLabel?.font = .poppinsRegularFont(14)
- cancel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
- cancel.addTarget(self, action: #selector(handleBgClick), for: .touchUpInside)
- container.addSubview(cancel)
- cancel.snp.makeConstraints { make in
- make.trailing.equalToSuperview().offset(-12)
- make.centerY.equalToSuperview()
- }
-
- let search = UIView()
- search.layer.cornerRadius = 8
- search.backgroundColor = .init(hex: "#F3F4FA")
- container.addSubview(search)
- search.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(12)
- make.top.equalToSuperview().offset(12)
- make.bottom.equalToSuperview().offset(-8)
- make.trailing.equalTo(cancel.snp.leading).offset(-19)
- }
-
- let icon = UIImageView()
- icon.image = UIImage(named: "icon_search")
- icon.setContentHuggingPriority(.defaultHigh, for: .horizontal)
- search.addSubview(icon)
- icon.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(8)
- make.centerY.equalToSuperview()
- }
-
- clearButton.addTarget(self, action: #selector(handleClearClick), for: .touchUpInside)
- clearButton.setImage(UIImage(named: "icon_textfield_clear"), for: .normal)
- clearButton.isHidden = true
- clearButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
- search.addSubview(clearButton)
- clearButton.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-10)
- }
-
- input.returnKeyType = .search
- let text: String = .init(key: "mimo_contact_search_hint")
- let placeholder = NSAttributedString(string: text,
- attributes: [.foregroundColor: UIColor.init(hex: "#878A99", alpha: 0.5)])
- input.attributedPlaceholder = placeholder
- input.font = .poppinsRegularFont(14)
- input.tintColor = .init(hex: "#17171A")
- input.textColor = .init(hex: "#17171A")
- input.delegate = self
- input.addTarget(self, action: #selector(textFieldDidChanged(_:)), for: .editingChanged)
- search.addSubview(input)
- input.snp.makeConstraints { make in
- make.leading.equalTo(icon.snp.trailing).offset(6)
- make.top.bottom.equalToSuperview()
- make.trailing.equalTo(clearButton.snp.leading).offset(-6)
- make.height.equalTo(36)
- }
-
- return container
- }
-
- private func buildList() -> UIView {
- noMoreDataView.isHaveData = true
-
- let header = MJRefreshNormalHeader { [weak self] in
- guard let self else { return }
- self.reload()
- }
- header.lastUpdatedTimeLabel?.isHidden = true
- header.stateLabel?.isHidden = true
- tableView.mj_header = header
-
- let footer = MJRefreshAutoNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadNext))
- footer.setTitle("", for: .noMoreData)
- tableView.mj_footer = footer
-
- tableView.backgroundView = noMoreDataView
-
- tableView.register(MOLineUserListCell.self, forCellReuseIdentifier: MOLineUserListCell.className())
- tableView.separatorColor = .clear
- tableView.delegate = self
- tableView.dataSource = self
- tableView.allowsSelection = false
-
- return tableView
- }
- }
- //import SwiftUI
- //
- //struct MOLineSearchUserViewPreview: UIViewRepresentable {
- // func makeUIView(context: Context) -> some UIView {
- // let viewModel = MOLineViewModel()
- // let view = UIView()
- // view.backgroundColor = .black
- // let list = MOLineSearchUserView(viewModel)
- // list.showIn(view)
- //
- // return view
- // }
- //
- // func updateUIView(_ uiView: UIViewType, context: Context) { }
- //}
- //
- //#Preview {
- // MOLineSearchUserViewPreview()
- //}
|