// // LNFeedCommentListPanel.swift // Gami // // Created by OneeChan on 2026/3/3. // import Foundation import UIKit import SnapKit import MJRefresh class LNFeedCommentListPanel: LNPopupView { private let titleLabel = UILabel() private let tableView = UITableView() private let tipsLabel = UILabel() private var feedId: String? private var comments: [LNFeedCommentVO] = [] private var total = 0 private var nextTag: String? override init(frame: CGRect) { super.init(frame: frame) setupViews() } func load(_ id: String) { feedId = id loadList() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension LNFeedCommentListPanel { private func loadList() { guard let feedId else { return } LNFeedManager.shared.getFeedCommentList(id: feedId, next: nextTag) { [weak self] res in guard let self else { return } if let res { if nextTag?.isEmpty != false { comments.removeAll() tableView.mj_header?.endRefreshing() } comments.append(contentsOf: res.list) self.nextTag = nextTag tableView.reloadData() titleLabel.text = .init(key: "A00304", res.total) total = res.total } if nextTag?.isEmpty != false { tableView.mj_footer?.endRefreshingWithNoMoreData() } else { tableView.mj_footer?.endRefreshing() } } } } extension LNFeedCommentListPanel: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { comments.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: LNFeedCommentCell.className, for: indexPath) as! LNFeedCommentCell cell.update(comments[indexPath.row]) return cell } } extension LNFeedCommentListPanel { private func setupViews() { containerHeight = .percent(0.7) let header = buildHeader() container.addSubview(header) header.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalToSuperview() } let menu = buildInputView() container.addSubview(menu) menu.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.bottom.equalToSuperview().offset(commonBottomInset) } let listView = buildListView() container.addSubview(listView) listView.snp.makeConstraints { make in make.top.equalTo(header.snp.bottom) make.horizontalEdges.equalToSuperview() make.bottom.equalTo(menu.snp.top) } } private func buildHeader() -> UIView { let header = UIView() header.snp.makeConstraints { make in make.height.equalTo(52) } titleLabel.font = .body_m titleLabel.textColor = .text_5 header.addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.leading.equalToSuperview().offset(16) make.centerY.equalToSuperview() } let close = UIButton() close.setImage(.init(systemName: "xmark"), for: .normal) close.tintColor = .text_4 close.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } dismiss() }), for: .touchUpInside) header.addSubview(close) close.snp.makeConstraints { make in make.centerY.equalToSuperview() make.trailing.equalToSuperview().offset(-16) make.width.height.equalTo(24) } return header } private func buildInputView() -> UIView { let container = UIView() container.onTap { [weak self] in guard let self else { return } guard let feedId else { return } let panel = LNCommonInputPanel() panel.maxInput = LNFeedManager.feedCommentMaxInput panel.handler = { [weak self] comment in guard let self else { return } LNFeedManager.shared.sendFeedComment(id: feedId, content: comment) { [weak self] success in guard let self else { return } guard success else { return } let item = LNFeedCommentVO() item.avatar = myUserInfo.avatar item.nickname = myUserInfo.nickname item.textContent = comment item.createdAt = Int(curTime * 1_000) comments.insert(item, at: 0) tableView.reloadData() total += 1 titleLabel.text = .init(key: "A00304", total) LNFeedManager.shared.notifyFeedCommentChanged(id: feedId, count: total) } } panel.popup() } container.snp.makeConstraints { make in make.height.equalTo(58) } let inputView = UIView() inputView.backgroundColor = .fill_2 inputView.layer.cornerRadius = 19 inputView.isUserInteractionEnabled = false container.addSubview(inputView) inputView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(12) make.height.equalTo(38) make.centerY.equalToSuperview() } let editIc = UIImageView() editIc.image = .icImChatMenuRemark.withTintColor(.text_2) inputView.addSubview(editIc) editIc.snp.makeConstraints { make in make.leading.equalToSuperview().offset(10) make.centerY.equalToSuperview() make.width.height.equalTo(24) } tipsLabel.font = .body_m tipsLabel.textColor = .text_2 tipsLabel.text = .init(key: "A00084") inputView.addSubview(tipsLabel) tipsLabel.snp.makeConstraints { make in make.leading.equalTo(editIc.snp.trailing).offset(4) make.trailing.equalToSuperview().offset(-10) make.centerY.equalToSuperview() } return container } private func buildListView() -> UIView { tableView.register(LNFeedCommentCell.self, forCellReuseIdentifier: LNFeedCommentCell.className) tableView.showsVerticalScrollIndicator = false tableView.showsHorizontalScrollIndicator = false tableView.separatorStyle = .none tableView.dataSource = self tableView.allowsSelection = false let header = MJRefreshNormalHeader { [weak self] in guard let self else { return } self.nextTag = nil self.loadList() } header.lastUpdatedTimeLabel?.isHidden = true header.stateLabel?.isHidden = true tableView.mj_header = header let footer = MJRefreshAutoNormalFooter { [weak self] in guard let self else { return } self.loadList() } footer.setTitle("", for: .noMoreData) footer.setTitle(.init(key: "A00046"), for: .idle) footer.endRefreshingCompletionBlock = { [weak self] in guard let self else { return } loadList() } tableView.mj_footer = footer return tableView } }