LNUserSearchRoomListView.swift 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. //
  2. // LNUserSearchRoomListView.swift
  3. // Lanu
  4. //
  5. // Created by OpenAI Codex on 2026/3/19.
  6. //
  7. import Foundation
  8. import UIKit
  9. import SnapKit
  10. import MJRefresh
  11. final class LNUserSearchRoomListView: UIView {
  12. private let emptyView = LNNoMoreDataView()
  13. private var items: [LNRoomItemVO] = []
  14. private var curKeyword: String? = nil
  15. private var nextTag: String? = nil
  16. private let collectionView: UICollectionView
  17. override init(frame: CGRect) {
  18. let width = (UIScreen.main.bounds.width - 16 * 2 - 13) * 0.5
  19. let layout = UICollectionViewFlowLayout()
  20. layout.scrollDirection = .vertical
  21. layout.minimumLineSpacing = 16
  22. layout.minimumInteritemSpacing = 13
  23. layout.itemSize = .init(width: width, height: width * 204 / 165)
  24. self.collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
  25. super.init(frame: frame)
  26. setupViews()
  27. }
  28. func search(keyword: String) {
  29. curKeyword = keyword
  30. nextTag = nil
  31. items.removeAll()
  32. collectionView.reloadData()
  33. emptyView.hide()
  34. collectionView.mj_footer?.resetNoMoreData()
  35. collectionView.mj_header?.beginRefreshing()
  36. }
  37. required init?(coder: NSCoder) {
  38. fatalError("init(coder:) has not been implemented")
  39. }
  40. }
  41. extension LNUserSearchRoomListView {
  42. private func searchRoom() {
  43. guard let curKeyword, !curKeyword.isEmpty else {
  44. collectionView.mj_header?.endRefreshing()
  45. collectionView.mj_footer?.endRefreshingWithNoMoreData()
  46. return
  47. }
  48. collectionView.isHidden = false
  49. LNRoomManager.shared.searchRoom(keyword: curKeyword, next: nextTag) { [weak self] res in
  50. guard let self else { return }
  51. guard let list = res?.list else {
  52. collectionView.mj_header?.endRefreshing()
  53. collectionView.mj_footer?.endRefreshingWithNoMoreData()
  54. if items.isEmpty {
  55. emptyView.showNetworkError()
  56. }
  57. return
  58. }
  59. if nextTag?.isEmpty != false {
  60. items = list
  61. } else {
  62. items.append(contentsOf: list)
  63. }
  64. nextTag = res?.next
  65. collectionView.reloadData()
  66. if items.isEmpty {
  67. emptyView.showNoData(tips: .init(key: "A00244"))
  68. } else {
  69. emptyView.hide()
  70. }
  71. collectionView.mj_header?.endRefreshing()
  72. if res?.next.isEmpty != false {
  73. collectionView.mj_footer?.endRefreshingWithNoMoreData()
  74. } else {
  75. collectionView.mj_footer?.endRefreshing()
  76. }
  77. }
  78. }
  79. }
  80. extension LNUserSearchRoomListView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  81. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  82. items.count
  83. }
  84. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  85. let cell = collectionView.dequeueReusableCell(
  86. withReuseIdentifier: LNUserSearchRoomCardCell.className,
  87. for: indexPath
  88. ) as! LNUserSearchRoomCardCell
  89. cell.update(items[indexPath.item])
  90. return cell
  91. }
  92. }
  93. extension LNUserSearchRoomListView {
  94. private func setupViews() {
  95. backgroundColor = .primary_1
  96. let header = MJRefreshNormalHeader { [weak self] in
  97. guard let self else { return }
  98. nextTag = nil
  99. searchRoom()
  100. }
  101. header.lastUpdatedTimeLabel?.isHidden = true
  102. header.stateLabel?.isHidden = true
  103. collectionView.mj_header = header
  104. let footer = MJRefreshAutoNormalFooter { [weak self] in
  105. guard let self else { return }
  106. searchRoom()
  107. }
  108. footer.setTitle("", for: .noMoreData)
  109. footer.setTitle(.init(key: "A00046"), for: .idle)
  110. collectionView.mj_footer = footer
  111. collectionView.backgroundColor = .clear
  112. collectionView.showsVerticalScrollIndicator = false
  113. collectionView.showsHorizontalScrollIndicator = false
  114. collectionView.allowsSelection = false
  115. collectionView.dataSource = self
  116. collectionView.delegate = self
  117. collectionView.register(LNUserSearchRoomCardCell.self, forCellWithReuseIdentifier: LNUserSearchRoomCardCell.className)
  118. collectionView.contentInset = .init(top: 6, left: 0, bottom: -commonBottomInset, right: 0)
  119. addSubview(collectionView)
  120. collectionView.snp.makeConstraints { make in
  121. make.horizontalEdges.equalToSuperview().inset(16)
  122. make.verticalEdges.equalToSuperview()
  123. }
  124. collectionView.addSubview(emptyView)
  125. emptyView.snp.makeConstraints { make in
  126. make.centerX.equalToSuperview()
  127. make.centerY.equalToSuperview().multipliedBy(0.6)
  128. }
  129. }
  130. }
  131. private final class LNUserSearchRoomCardCell: UICollectionViewCell {
  132. private let cardView = LNUserSearchRoomCardView()
  133. override init(frame: CGRect) {
  134. super.init(frame: frame)
  135. contentView.addSubview(cardView)
  136. cardView.snp.makeConstraints { make in
  137. make.edges.equalToSuperview()
  138. }
  139. }
  140. required init?(coder: NSCoder) {
  141. fatalError("init(coder:) has not been implemented")
  142. }
  143. func update(_ item: LNRoomItemVO) {
  144. cardView.update(item)
  145. }
  146. }