BeeReel/BeeReel/Class/Player/Controller/BRVideoDetailViewController.swift
2025-07-29 17:43:43 +08:00

265 lines
8.9 KiB
Swift

//
// BRVideoDetailViewController.swift
// BeeReel
//
// Created by 鸿 on 2025/6/30.
//
import UIKit
class BRVideoDetailViewController: BRPlayerListViewController {
override var contentSize: CGSize {
return .init(width: UIScreen.width, height: UIScreen.height)
}
override var CellClass: BRPlayerListCell.Type {
return BRDetailPlayerCell.self
}
var shortPlayId: String?
var activityId: String?
private var detailArr: [BRVideoDetailModel] = []
///
private lazy var isAllowShowRecommand = false
private var recommandTimer: Timer?
///
private var lastUploadTime: TimeInterval = 0
//MARK: UI
private lazy var backButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "nav_back_icon_01"), for: .normal)
button.addTarget(self, action: #selector(handleBackButton), for: .touchUpInside)
return button
}()
///
private weak var popUpView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
self.dataSource = self
self.fd_interactivePopDisabled = true
self.requestDetailData()
self.viewModel.asyncGetRecommandDataArr()
br_setupUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
override var previousVideoUrl: String? {
let index = self.viewModel.currentIndexPath.row - 1
guard index > 0 else { return nil }
let model = self.detailArr[self.viewModel.currentIndexPath.section]
return model.episodeList?[index].video_url
}
override var nextVideoUrl: String? {
let index = self.viewModel.currentIndexPath.row + 1
let model = self.detailArr[self.viewModel.currentIndexPath.section]
guard index < (model.episodeList?.count ?? 0) else { return nil }
return model.episodeList?[index].video_url
}
override func play() {
let videoInfo = self.viewModel.currentPlayer?.videoInfo
guard videoInfo?.is_lock == true else {
super.play()
BRVideoAPI.requestAddPlayHistory(videoId: self.viewModel.currentPlayer?.videoInfo?.short_play_video_id, shortPlayId: self.viewModel.currentPlayer?.videoInfo?.short_play_id)
return
}
self.pause()
let myCoins = BRLoginManager.manager.userInfo?.totalCoin ?? 0
let coins = videoInfo?.coins ?? 0
if myCoins < coins, self.viewModel.currentPlayer?.hasLastEpisodeUnlocked != true {
self.viewModel.openRechargeView()
}
}
@objc private func handleBackButton() {
if !self.viewModel.recommandList.isEmpty, isAllowShowRecommand {
self.pause()
let view = BRVideoDetailRecommendView()
view.videoList = self.viewModel.recommandList
view.didDismissBlock = { [weak self] in
self?.handleNavBack()
}
view.didSelectedVideo = { [weak self] model in
guard let self = self else { return }
self.shortPlayId = model.short_play_id
self.requestDetailData()
}
view.present(in: nil)
} else {
self.handleNavBack()
}
}
}
extension BRVideoDetailViewController {
private func br_setupUI() {
view.addSubview(backButton)
backButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview().offset(UIScreen.statusBarHeight + 10)
}
}
}
extension BRVideoDetailViewController {
@objc private func handleRecommandTimer() {
self.isAllowShowRecommand = true
}
}
//MARK: -------------- BRPlayerViewModelDelegate --------------
//
extension BRVideoDetailViewController {
///
override func br_onEpisodeView(viewModel: BRPlayerViewModel) {
let indexPath = self.viewModel.currentIndexPath
let model = self.detailArr[indexPath.section]
let view = BREpisodeSelectorView()
view.shortModel = model.shortPlayInfo
view.epList = model.episodeList ?? []
view.index = viewModel.currentIndexPath.row
view.didSelectedIndex = { [weak self] index in
self?.scrollToItem(indexPath: IndexPath(row: index, section: indexPath.section), animated: false)
}
view.present(in: nil)
self.popUpView = view
}
///
override func br_clickRateButton(viewModel: BRPlayerViewModel) {
let view = BRRateSelectorView()
view.didSelectedRate = { [weak self] model in
guard let self = self else { return }
self.viewModel.rateModel = model
}
view.show()
self.popUpView = view
}
override func br_playProgressDidChange(viewModel: BRPlayerViewModel, time: TimeInterval) {
if (time >= lastUploadTime + 5 || time < lastUploadTime) && time >= 5 {
lastUploadTime = time
self.viewModel.uploadPlayTime()
}
}
override func br_needUpdateAllData(viewModel: BRPlayerViewModel, scrollTo indexPath: IndexPath?) {
self.requestDetailData(indexPath: indexPath)
}
}
//MARK: -------------- BRPlayerListViewControllerDataSource BRPlayerListViewControllerDelegate --------------
extension BRVideoDetailViewController: BRPlayerListViewControllerDataSource, BRPlayerListViewControllerDelegate {
func br_playerListViewController(_ viewController: BRPlayerListViewController, _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let model = self.detailArr[indexPath.section]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRDetailPlayerCell
cell.videoInfo = model.episodeList?[indexPath.row]
cell.shortModel = model.shortPlayInfo
let upRow = indexPath.row - 1
if upRow >= 0, let videoInfo = model.episodeList?[upRow], videoInfo.is_lock == true {
cell.hasLastEpisodeUnlocked = true
} else {
cell.hasLastEpisodeUnlocked = false
}
return cell
}
func br_playerListViewController(_ viewController: BRPlayerListViewController, _ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.detailArr[section].episodeList?.count ?? 0
}
func br_numberOfSections(in viewController: BRPlayerListViewController) -> Int {
return self.detailArr.count
}
func br_shouldAutoScrollNextEpisode(_ viewController: BRPlayerListViewController) -> Bool {
if self.popUpView == nil {
return true
} else {
return false
}
}
}
extension BRVideoDetailViewController {
private func requestDetailData(indexPath: IndexPath? = nil) {
guard let shortPlayId = shortPlayId else { return }
isAllowShowRecommand = false
recommandTimer?.invalidate()
recommandTimer = nil
recommandTimer = Timer.scheduledTimer(timeInterval: 6, target: YYTextWeakProxy(target: self), selector: #selector(handleRecommandTimer), userInfo: nil, repeats: false)
BRHUD.show(containerView: self.view)
BRVideoAPI.requestVideoDetail(shortPlayId: shortPlayId, activityId: activityId) { [weak self] model in
BRHUD.dismiss()
guard let self = self else { return }
guard let model = model else { return }
self.detailArr.removeAll()
self.detailArr.append(model)
self.reloadData { [weak self] in
guard let self = self else { return }
self.play()
var targetIndexPath = IndexPath(row: 0, section: 0)
if let indexPath = indexPath, indexPath.row < (model.episodeList?.count ?? 0) {
targetIndexPath = indexPath
} else if let videoInfo = model.video_info {
var row: Int?
model.episodeList?.enumerated().forEach({
if $1.id == videoInfo.id {
row = $0
}
})
if let row = row {
targetIndexPath = .init(row: row, section: 0)
}
}
self.scrollToItem(indexPath: targetIndexPath, animated: false)
}
}
}
}