LNRoomInviteSeatPanel.swift 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. //
  2. // LNRoomInviteSeatPanel.swift
  3. // Gami
  4. //
  5. // Created by OneeChan on 2026/3/20.
  6. //
  7. import Foundation
  8. import UIKit
  9. import SnapKit
  10. import MJRefresh
  11. class LNRoomInviteSeatPanel: LNPopupView {
  12. private let countLabel = UILabel()
  13. private let filterButton = UIButton()
  14. private let tableView = UITableView(frame: .zero, style: .plain)
  15. private let emptyView = LNNoMoreDataView()
  16. private weak var roomSession: LNRoomViewModel?
  17. private var curSeat: LNRoomSeatItem?
  18. private var items: [LNRoomUserListItemVO] = []
  19. private var nextTag: String? = nil
  20. private var categories: [LNGameCategoryItemVO] = []
  21. private var curCategoryCode: String = ""
  22. private var curCategoryTitle: String = .init(key: "A00361")
  23. override init(frame: CGRect) {
  24. super.init(frame: frame)
  25. containerHeight = .percent(0.62)
  26. setupViews()
  27. }
  28. func update(_ seat: LNRoomSeatItem, room: LNRoomViewModel?) {
  29. curSeat = seat
  30. roomSession = room
  31. loadList()
  32. if seat.index == .guest {
  33. filterButton.isHidden = true
  34. } else {
  35. filterButton.isHidden = false
  36. loadCategory()
  37. }
  38. }
  39. required init?(coder: NSCoder) {
  40. fatalError("init(coder:) has not been implemented")
  41. }
  42. }
  43. extension LNRoomInviteSeatPanel {
  44. private func loadList() {
  45. guard let roomSession else { return }
  46. roomSession.getRoomUserList(next: nextTag, playmete: curSeat?.index != .guest, filter: curCategoryCode)
  47. { [weak self] res in
  48. guard let self else { return }
  49. if let list = res?.list {
  50. if nextTag == nil {
  51. items.removeAll()
  52. }
  53. items.append(contentsOf: list)
  54. nextTag = res?.next
  55. tableView.reloadData()
  56. if items.isEmpty {
  57. emptyView.showNoData()
  58. } else {
  59. emptyView.hide()
  60. }
  61. } else {
  62. if items.isEmpty {
  63. emptyView.showNetworkError()
  64. }
  65. }
  66. tableView.mj_header?.endRefreshing()
  67. if nextTag?.isEmpty != false {
  68. tableView.mj_footer?.endRefreshingWithNoMoreData()
  69. } else {
  70. tableView.mj_footer?.endRefreshing()
  71. }
  72. if let total = res?.total {
  73. countLabel.text = .init(key: "A00334", total)
  74. }
  75. }
  76. }
  77. private func loadCategory() {
  78. roomSession?.getPlaymateCategory { [weak self] res in
  79. guard let self else { return }
  80. guard let res else { return }
  81. categories = res.list
  82. }
  83. }
  84. }
  85. extension LNRoomInviteSeatPanel: UITableViewDataSource, UITableViewDelegate {
  86. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  87. items.count
  88. }
  89. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  90. let cell = tableView.dequeueReusableCell(
  91. withIdentifier: LNRoomInviteSeatCell.className,
  92. for: indexPath
  93. ) as! LNRoomInviteSeatCell
  94. cell.update(room: roomSession, seat: curSeat, item: items[indexPath.row], index: indexPath.row + 1)
  95. return cell
  96. }
  97. }
  98. private extension LNRoomInviteSeatPanel {
  99. func setupViews() {
  100. container.backgroundColor = .fill_7
  101. let countView = buildHeader()
  102. container.addSubview(countView)
  103. countView.snp.makeConstraints { make in
  104. make.top.equalToSuperview()
  105. make.horizontalEdges.equalToSuperview().inset(16)
  106. }
  107. let header = MJRefreshNormalHeader { [weak self] in
  108. guard let self else { return }
  109. nextTag = nil
  110. loadList()
  111. }
  112. header.lastUpdatedTimeLabel?.isHidden = true
  113. header.stateLabel?.isHidden = true
  114. tableView.mj_header = header
  115. let footer = MJRefreshAutoNormalFooter { [weak self] in
  116. guard let self else { return }
  117. loadList()
  118. }
  119. footer.setTitle("", for: .noMoreData)
  120. footer.setTitle(.init(key: "A00046"), for: .idle)
  121. tableView.mj_footer = footer
  122. tableView.backgroundColor = .clear
  123. tableView.separatorStyle = .none
  124. tableView.showsVerticalScrollIndicator = false
  125. tableView.showsHorizontalScrollIndicator = false
  126. tableView.allowsSelection = false
  127. tableView.dataSource = self
  128. tableView.delegate = self
  129. tableView.register(LNRoomInviteSeatCell.self, forCellReuseIdentifier: LNRoomInviteSeatCell.className)
  130. container.addSubview(tableView)
  131. tableView.snp.makeConstraints { make in
  132. make.top.equalTo(countView.snp.bottom)
  133. make.horizontalEdges.equalToSuperview()
  134. make.bottom.equalToSuperview().offset(commonBottomInset)
  135. }
  136. emptyView.isHidden = true
  137. emptyView.tipsLabel.textColor = .text_2
  138. tableView.addSubview(emptyView)
  139. emptyView.snp.makeConstraints { make in
  140. make.center.equalToSuperview()
  141. }
  142. updateFilterView()
  143. }
  144. func buildHeader() -> UIView {
  145. let container = UIView()
  146. container.snp.makeConstraints { make in
  147. make.height.equalTo(52)
  148. }
  149. let stackView = UIStackView()
  150. stackView.axis = .horizontal
  151. stackView.spacing = 5
  152. stackView.alignment = .center
  153. container.addSubview(stackView)
  154. stackView.snp.makeConstraints { make in
  155. make.leading.centerY.equalToSuperview()
  156. }
  157. countLabel.font = .body_m
  158. countLabel.textColor = .text_6
  159. container.addSubview(countLabel)
  160. stackView.addArrangedSubview(countLabel)
  161. let countDescLabel = UILabel()
  162. countDescLabel.font = .body_m
  163. countDescLabel.textColor = .text_1
  164. countDescLabel.text = .init(key: "A00369")
  165. stackView.addArrangedSubview(countDescLabel)
  166. let config = UIImage.SymbolConfiguration(pointSize: 12)
  167. filterButton.backgroundColor = .fill.withAlphaComponent(0.15)
  168. filterButton.layer.cornerRadius = 15
  169. filterButton.clipsToBounds = true
  170. filterButton.titleLabel?.font = .body_s
  171. filterButton.setTitleColor(.text_1, for: .normal)
  172. filterButton.setImage(.init(systemName: "chevron.backward", withConfiguration: config), for: .normal)
  173. filterButton.tintColor = .text_1
  174. filterButton.semanticContentAttribute = .forceRightToLeft
  175. filterButton.imageEdgeInsets = .init(top: 0, left: 4, bottom: 0, right: -4)
  176. filterButton.contentEdgeInsets = .init(top: 0, left: 12, bottom: 0, right: 12)
  177. filterButton.addAction(UIAction(handler: { [weak self] _ in
  178. guard let self else { return }
  179. let panel = LNRoomGameCategoryFilterPanel()
  180. let options = buildCategoryFilterOptions()
  181. panel.update(options: options, curSelectedCode: curCategoryCode)
  182. panel.handler = { [weak self] option in
  183. guard let self else { return }
  184. curCategoryCode = option.code
  185. curCategoryTitle = option.code.isEmpty ? .init(key: "A00361") : option.name
  186. updateFilterView()
  187. nextTag = nil
  188. tableView.mj_header?.beginRefreshing()
  189. }
  190. panel.popup(self)
  191. }), for: .touchUpInside)
  192. container.addSubview(filterButton)
  193. filterButton.snp.makeConstraints { make in
  194. make.centerY.trailing.equalToSuperview()
  195. make.height.equalTo(30)
  196. }
  197. return container
  198. }
  199. func buildCategoryFilterOptions() -> [LNGameCategoryItemVO] {
  200. var options: [LNGameCategoryItemVO] = []
  201. options.append(.init(code: "", name: .init(key: "A00360"), icon: "", categoryType: .normal))
  202. options.append(contentsOf: categories)
  203. return options
  204. }
  205. func updateFilterView() {
  206. filterButton.setTitle(curCategoryTitle, for: .normal)
  207. }
  208. }