// // SPCollectListViewController.swift // Thimra // // Created by 曾觉新 on 2025/4/18. // import UIKit class SPCollectListViewController: SPMyListChildViewController { private lazy var dataArr: [SPShortModel] = [] private var page: Int? private lazy var deleteGorup = DispatchGroup() //MARK: UI属性 private lazy var collectionViewLayout: UICollectionViewFlowLayout = { let itemWidth = floor((kSPScreenWidth - 32 - 8 * 2) / 3) let itemHeight = 145 / 109 * itemWidth + 36 let layout = UICollectionViewFlowLayout() layout.itemSize = .init(width: itemWidth, height: itemHeight) layout.minimumLineSpacing = 18 layout.minimumInteritemSpacing = 8 layout.sectionInset = .init(top: 0, left: 16, bottom: 0, right: 16) return layout }() private lazy var collectionView: SPCollectionView = { let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) collectionView.delegate = self collectionView.dataSource = self collectionView.contentInset = .init(top: 10, left: 0, bottom: 0, right: 0) collectionView.sp_addRefreshHeader(insetTop: collectionView.contentInset.top) { [weak self] in self?.handleHeaderRefresh(nil) } collectionView.sp_addRefreshBackFooter { [weak self] in self?.handleFooterRefresh(nil) } SPCollectListCell.registerCell(collectionView: collectionView) return collectionView }() override func viewDidLoad() { super.viewDidLoad() requestDataList(page: 1, completer: nil) _setupUI() } override func setBgImageView() { } override func handleHeaderRefresh(_ completer: (() -> Void)?) { requestDataList(page: 1) { [weak self] in self?.collectionView.sp_endHeaderRefreshing() } } override func handleFooterRefresh(_ completer: (() -> Void)?) { guard let page = self.page else { return } requestDataList(page: page + 1) { [weak self] in self?.collectionView.sp_endFooterRefreshing() } } override var sp_isEditing: Bool { didSet { self.collectionView.reloadData() } } override var isAllSelected: Bool { var result = true for model in dataArr { if model.sp_isSelected != true { result = false break } } return result } override var selectedCount: Int { var result = 0 dataArr.forEach { if $0.sp_isSelected ?? false { result += 1 } } return result } override func setAllSelectedState(isSelected: Bool) { dataArr.forEach { $0.sp_isSelected = isSelected } self.collectionView.reloadData() allSelectedStateDidChange?(isSelected) self.updateDeleteButtonState() } override func handelDeleteButton() { requestDelete() } } extension SPCollectListViewController { private func _setupUI() { view.addSubview(collectionView) collectionView.snp.makeConstraints { make in make.left.right.bottom.equalToSuperview() make.top.equalToSuperview().offset(10) } } } //MARK: -------------- UICollectionViewDelegate & UICollectionViewDataSource -------------- extension SPCollectListViewController: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = SPCollectListCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) cell.sp_isEditing = self.sp_isEditing cell.model = dataArr[indexPath.row] cell.clickDeleteButton = { [weak self] cell in guard let self = self else { return } guard let indexPath = self.collectionView.indexPath(for: cell) else { return } self.deleteShort(indexPath: indexPath) } return cell } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { let count = self.dataArr.count if count == 0 { let parameters = SPEmptyParameters(image: UIImage(named: "empty_image_01")) let emptyState = SPEmptyState.normail(parameters: parameters) self.collectionView.emptyState.format = emptyState.format self.collectionView.emptyState.show(emptyState) } else { self.collectionView.emptyState.hide() } return count } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let model = dataArr[indexPath.row] if sp_isEditing { model.sp_isSelected = !(model.sp_isSelected ?? false) self.collectionView.reloadData() allSelectedStateDidChange?(isAllSelected) self.updateDeleteButtonState() } else { let vc = SPPlayerDetailViewController() vc.shortPlayId = model.short_play_id self.navigationController?.pushViewController(vc, animated: true) } } func deleteShort(indexPath: IndexPath) { let model = self.dataArr[indexPath.row] guard let id = model.short_play_id else { return } SPVideoAPI.requestCollectShort(isCollect: false, shortPlayId: id, videoId: nil) { [weak self] in guard let self = self else { return } self.requestDataList(page: 1, completer: nil) } } } extension SPCollectListViewController { private func requestDataList(page: Int, completer: (() -> Void)?) { SPVideoAPI.requestCollectList(page: page) { [weak self] listModel in guard let self = self else { return } if let listModel = listModel, let list = listModel.list { if page == 1 { self.dataArr.removeAll() } self.dataArr += list self.page = page self.collectionView.reloadData() if self.sp_isEditing { self.allSelectedStateDidChange?(self.isAllSelected) } } completer?() } } private func requestDelete() { dataArr.forEach { if $0.sp_isSelected == true, let shortPlayId = $0.short_play_id { self.deleteGorup.enter() SPVideoAPI.requestCollectShort(isCollect: false, shortPlayId: shortPlayId, videoId: nil) { [weak self] in self?.deleteGorup.leave() } failure: { [weak self] in self?.deleteGorup.leave() } } } self.deleteGorup.notify(queue: DispatchQueue.main) { [weak self] in self?.requestDataList(page: 1, completer: nil) } } }