播放更多视频

This commit is contained in:
zjx 2025-07-02 13:50:41 +08:00
parent 1cf2c2dde2
commit c8d3e9d349
11 changed files with 218 additions and 86 deletions

View File

@ -158,6 +158,8 @@
BFA21D9E2E01684E00B3573D /* VPStoreCoinsItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA21D9D2E01684E00B3573D /* VPStoreCoinsItemView.swift */; }; BFA21D9E2E01684E00B3573D /* VPStoreCoinsItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA21D9D2E01684E00B3573D /* VPStoreCoinsItemView.swift */; };
BFA21DA02E01688D00B3573D /* VPStoreCoinsBigItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA21D9F2E01688D00B3573D /* VPStoreCoinsBigItemView.swift */; }; BFA21DA02E01688D00B3573D /* VPStoreCoinsBigItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA21D9F2E01688D00B3573D /* VPStoreCoinsBigItemView.swift */; };
BFA21DA22E01696700B3573D /* VPStoreCoinsSmallItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA21DA12E01696700B3573D /* VPStoreCoinsSmallItemView.swift */; }; BFA21DA22E01696700B3573D /* VPStoreCoinsSmallItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA21DA12E01696700B3573D /* VPStoreCoinsSmallItemView.swift */; };
BFC676C02E13EBA1006659E5 /* VPAdPlayerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676BF2E13EBA1006659E5 /* VPAdPlayerCell.swift */; };
BFC676C22E13EBED006659E5 /* VPAdPlayerControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676C12E13EBED006659E5 /* VPAdPlayerControlView.swift */; };
BFCCE10D2DF951F600EDE165 /* SceneDelegate+APNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */; }; BFCCE10D2DF951F600EDE165 /* SceneDelegate+APNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */; };
BFCCE1122DF9638B00EDE165 /* VPVipAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */; }; BFCCE1122DF9638B00EDE165 /* VPVipAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */; };
BFCCE1142DFAAC0900EDE165 /* VPLanguageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCE1132DFAAC0900EDE165 /* VPLanguageViewController.swift */; }; BFCCE1142DFAAC0900EDE165 /* VPLanguageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCE1132DFAAC0900EDE165 /* VPLanguageViewController.swift */; };
@ -435,6 +437,8 @@
BFA21D9D2E01684E00B3573D /* VPStoreCoinsItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPStoreCoinsItemView.swift; sourceTree = "<group>"; }; BFA21D9D2E01684E00B3573D /* VPStoreCoinsItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPStoreCoinsItemView.swift; sourceTree = "<group>"; };
BFA21D9F2E01688D00B3573D /* VPStoreCoinsBigItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPStoreCoinsBigItemView.swift; sourceTree = "<group>"; }; BFA21D9F2E01688D00B3573D /* VPStoreCoinsBigItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPStoreCoinsBigItemView.swift; sourceTree = "<group>"; };
BFA21DA12E01696700B3573D /* VPStoreCoinsSmallItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPStoreCoinsSmallItemView.swift; sourceTree = "<group>"; }; BFA21DA12E01696700B3573D /* VPStoreCoinsSmallItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPStoreCoinsSmallItemView.swift; sourceTree = "<group>"; };
BFC676BF2E13EBA1006659E5 /* VPAdPlayerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAdPlayerCell.swift; sourceTree = "<group>"; };
BFC676C12E13EBED006659E5 /* VPAdPlayerControlView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAdPlayerControlView.swift; sourceTree = "<group>"; };
BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SceneDelegate+APNS.swift"; sourceTree = "<group>"; }; BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SceneDelegate+APNS.swift"; sourceTree = "<group>"; };
BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVipAlertView.swift; sourceTree = "<group>"; }; BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVipAlertView.swift; sourceTree = "<group>"; };
BFCCE1132DFAAC0900EDE165 /* VPLanguageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPLanguageViewController.swift; sourceTree = "<group>"; }; BFCCE1132DFAAC0900EDE165 /* VPLanguageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPLanguageViewController.swift; sourceTree = "<group>"; };
@ -998,6 +1002,8 @@
BF0FA7582DDF1C2800C9E5F2 /* VPPlayerProgressView.swift */, BF0FA7582DDF1C2800C9E5F2 /* VPPlayerProgressView.swift */,
BF0FA7622DE006E700C9E5F2 /* VPDetailPlayerCell.swift */, BF0FA7622DE006E700C9E5F2 /* VPDetailPlayerCell.swift */,
BF0FA7642DE00A0E00C9E5F2 /* VPDetailPlayerControlView.swift */, BF0FA7642DE00A0E00C9E5F2 /* VPDetailPlayerControlView.swift */,
BFC676BF2E13EBA1006659E5 /* VPAdPlayerCell.swift */,
BFC676C12E13EBED006659E5 /* VPAdPlayerControlView.swift */,
BF0FA7662DE0469300C9E5F2 /* VPEpisodeView.swift */, BF0FA7662DE0469300C9E5F2 /* VPEpisodeView.swift */,
BF0FA7682DE0502900C9E5F2 /* VPEpisodeCell.swift */, BF0FA7682DE0502900C9E5F2 /* VPEpisodeCell.swift */,
BF0FA76A2DE0533400C9E5F2 /* VPEpisodeMenuView.swift */, BF0FA76A2DE0533400C9E5F2 /* VPEpisodeMenuView.swift */,
@ -1547,6 +1553,7 @@
BFF5B2302DEFEF0C0044227A /* VPDeleteAccountNormalView.swift in Sources */, BFF5B2302DEFEF0C0044227A /* VPDeleteAccountNormalView.swift in Sources */,
1B056E702DDB019B007EE38D /* VPTabBarItemContainer.swift in Sources */, 1B056E702DDB019B007EE38D /* VPTabBarItemContainer.swift in Sources */,
BF0FA7752DE071B500C9E5F2 /* VPSearchViewController.swift in Sources */, BF0FA7752DE071B500C9E5F2 /* VPSearchViewController.swift in Sources */,
BFC676C02E13EBA1006659E5 /* VPAdPlayerCell.swift in Sources */,
BF0FA78D2DE16A8B00C9E5F2 /* VPSearchViewModel.swift in Sources */, BF0FA78D2DE16A8B00C9E5F2 /* VPSearchViewModel.swift in Sources */,
1B056E592DDACD44007EE38D /* VPTabBarItemContentView.swift in Sources */, 1B056E592DDACD44007EE38D /* VPTabBarItemContentView.swift in Sources */,
1B056E2B2DDAC0FD007EE38D /* AppDelegate.swift in Sources */, 1B056E2B2DDAC0FD007EE38D /* AppDelegate.swift in Sources */,
@ -1687,6 +1694,7 @@
BF0FA76F2DE062A700C9E5F2 /* VPRateSelectedView.swift in Sources */, BF0FA76F2DE062A700C9E5F2 /* VPRateSelectedView.swift in Sources */,
BF0FA7772DE0735800C9E5F2 /* VPSearchInputView.swift in Sources */, BF0FA7772DE0735800C9E5F2 /* VPSearchInputView.swift in Sources */,
BFF5AFB62DE803A30044227A /* VPVipPrivilegeItemView.swift in Sources */, BFF5AFB62DE803A30044227A /* VPVipPrivilegeItemView.swift in Sources */,
BFC676C22E13EBED006659E5 /* VPAdPlayerControlView.swift in Sources */,
BFF5B2542DF132540044227A /* VPConsumptionRecordsModel.swift in Sources */, BFF5B2542DF132540044227A /* VPConsumptionRecordsModel.swift in Sources */,
BFF5AFB82DE832580044227A /* VPVipBuyCell.swift in Sources */, BFF5AFB82DE832580044227A /* VPVipBuyCell.swift in Sources */,
BFF5B22E2DEFEEAF0044227A /* VPDeleteAccountContentView.swift in Sources */, BFF5B22E2DEFEEAF0044227A /* VPDeleteAccountContentView.swift in Sources */,

View File

@ -46,7 +46,7 @@ extension SceneDelegate {
func vp_handleOpenAppMessage(webpageURL: URL?) { func vp_handleOpenAppMessage(webpageURL: URL?) {
guard VPNetworkReachabilityManager.manager.isReachable == true, // guard VPNetworkReachabilityManager.manager.isReachable == true, //
// AppDelegate.haveBeenShownAPNS, // AppDelegate.haveBeenShownAPNS, //
self.isOpenApp, //APP self.isOpenApp, //APP
VPAppTool.idfaAuthorizationFinish //idfa VPAppTool.idfaAuthorizationFinish //idfa
else { else {

View File

@ -33,17 +33,14 @@ extension AppDelegate {
} }
#endif #endif
} }
} else {
Self.haveBeenShownAPNS = true
VPAppTool.sceneDelegate?.vp_retryHandleOpenAppMessage()
} }
UserDefaults.standard.set(Date(), forKey: kVPApnsAlertDefaultsKey)
} else {
Self.haveBeenShownAPNS = true UserDefaults.standard.set(Date(), forKey: kVPApnsAlertDefaultsKey)
VPAppTool.sceneDelegate?.vp_retryHandleOpenAppMessage()
} }
Self.haveBeenShownAPNS = true
VPAppTool.sceneDelegate?.vp_retryHandleOpenAppMessage()
self.uploadNoticeStatus() self.uploadNoticeStatus()
} }
UIApplication.shared.registerForRemoteNotifications() UIApplication.shared.registerForRemoteNotifications()
@ -57,13 +54,13 @@ extension AppDelegate {
alert.clickHighlightButton = { [weak self] in alert.clickHighlightButton = { [weak self] in
guard let _ = self else { return } guard let _ = self else { return }
VPAppTool.openApnsSetting() VPAppTool.openApnsSetting()
Self.haveBeenShownAPNS = true // Self.haveBeenShownAPNS = true
} }
alert.clickCloseButton = { [weak self] in alert.clickCloseButton = { [weak self] in
guard let _ = self else { return } guard let _ = self else { return }
Self.haveBeenShownAPNS = true // Self.haveBeenShownAPNS = true
VPAppTool.sceneDelegate?.vp_retryHandleOpenAppMessage() // VPAppTool.sceneDelegate?.vp_retryHandleOpenAppMessage()
} }
} }

View File

@ -33,6 +33,30 @@ class VPVideoAPI: NSObject {
} }
} }
///
static func requestMoreVideoDetail(shortPlayId: String, activityId: String? = nil, revolution: VPShortModel.VideoRevolution? = nil, completer: ((_ model: VPVideoDetailModel?) -> Void)?) {
var parameters: [String : Any] = [
"short_play_id" : shortPlayId,
"video_id" : "0"
]
if let activityId = activityId {
parameters["activity_id"] = activityId
}
if let revolution = revolution?.rawValue {
parameters["revolution"] = revolution
}
var param = VPNetworkParameters(path: "/getVideoDetails")
param.method = .get
param.parameters = parameters
VPNetwork.request(parameters: param) { (response: VPNetworkResponse<VPVideoDetailModel>) in
completer?(response.data)
}
}
/// ///
static func requestCategoryVideoList(id: String, page: Int, completer: ((_ listModel: VPListModel<VPShortModel>?) -> Void)?) { static func requestCategoryVideoList(id: String, page: Int, completer: ((_ listModel: VPListModel<VPShortModel>?) -> Void)?) {

View File

@ -20,6 +20,13 @@ class VPVersionUpdateModel: VPModel, SmartCodable {
let currentCode = NSNumber(string: kVPAPPBundleVersion)?.intValue ?? 0 let currentCode = NSNumber(string: kVPAPPBundleVersion)?.intValue ?? 0
let serverCode = NSNumber(string: version_code ?? "0")?.intValue ?? 0 let serverCode = NSNumber(string: version_code ?? "0")?.intValue ?? 0
return serverCode > currentCode return serverCode > currentCode
// let result = kVPAPPVersion.compare(version_name ?? "", options: .numeric)
// if result == .orderedAscending {
// return true
// } else {
// return false
// }
} }

View File

@ -20,7 +20,9 @@ class VPDetailPlayerViewController: VPVideoPlayerViewController {
var shortPlayId: String? var shortPlayId: String?
var activityId: String? var activityId: String?
private var detailModel: VPVideoDetailModel? // private var detailModel: VPVideoDetailModel?
private lazy var detailDataArr: [VPVideoDetailModel] = []
/// ///
private var lastUploadProgress: Int = 0 private var lastUploadProgress: Int = 0
@ -137,6 +139,7 @@ class VPDetailPlayerViewController: VPVideoPlayerViewController {
extension VPDetailPlayerViewController { extension VPDetailPlayerViewController {
private func vp_setupUI() { private func vp_setupUI() {
collectionView.register(VPAdPlayerCell.self, forCellWithReuseIdentifier: "VPAdPlayerCell")
view.addSubview(backButton) view.addSubview(backButton)
view.addSubview(videoNameLabel) view.addSubview(videoNameLabel)
@ -174,12 +177,15 @@ extension VPDetailPlayerViewController {
extension VPDetailPlayerViewController { extension VPDetailPlayerViewController {
private func onEpisode() { private func onEpisode() {
let indexPath = self.viewModel.currentIndexPath
let detailModel = self.detailDataArr[indexPath.section]
let view = VPEpisodeView() let view = VPEpisodeView()
view.dataArr = detailModel?.episodeList ?? [] view.dataArr = detailModel.episodeList ?? []
view.shortModel = detailModel?.shortPlayInfo view.shortModel = detailModel.shortPlayInfo
view.currentIndex = self.viewModel.currentIndexPath.row view.currentIndex = indexPath.row
view.didSelectedIndex = { [weak self] (index) in view.didSelectedIndex = { [weak self] (index) in
self?.scrollToItem(indexPath: IndexPath(row: index, section: 0), animated: false) self?.scrollToItem(indexPath: IndexPath(row: index, section: indexPath.section), animated: false)
} }
view.present(in: nil) view.present(in: nil)
self.episodeView = view self.episodeView = view
@ -223,27 +229,18 @@ extension VPDetailPlayerViewController {
/// ///
private func onRecharge() { private func onRecharge() {
// guard let videoInfo = self.viewModel.currentPlayer?.videoInfo else { return }
self.viewModel.showRechargeView() self.viewModel.showRechargeView()
// let view = VPPlayerRechargeView()
// view.shortPlayId = videoInfo.short_play_id
// view.videoId = videoInfo.short_play_video_id
// view.buyFinishBlock = { [weak self] in
// guard let self = self else { return }
// self.requestDetailData(indexPath: self.viewModel.currentIndexPath)
// }
// view.present(in: nil)
} }
/// ///
@objc private func buyVipFinishNotification() { @objc private func buyVipFinishNotification() {
guard VPLoginManager.manager.userInfo?.is_vip == true else { return } guard VPLoginManager.manager.userInfo?.is_vip == true else { return }
self.detailModel?.episodeList?.forEach({ self.detailDataArr.forEach {
$0.is_lock = false $0.episodeList?.forEach {
}) $0.is_lock = false
}
}
self.reloadData { [weak self] in self.reloadData { [weak self] in
self?.play() self?.play()
@ -289,20 +286,46 @@ extension VPDetailPlayerViewController {
/// ///
@objc private func didChangeRevolutionNotification() { @objc private func didChangeRevolutionNotification() {
if self.viewModel.currentPlayer?.videoInfo?.short_play_id != nil {
self.shortPlayId = self.viewModel.currentPlayer?.videoInfo?.short_play_id
}
self.requestDetailData(indexPath: self.viewModel.currentIndexPath) self.requestDetailData(indexPath: self.viewModel.currentIndexPath)
} }
///IndexPathindexPath
private func verify(indexPath: IndexPath) -> IndexPath? {
guard self.detailDataArr.count > 0 else { return nil }
var newIndexPath = indexPath
if indexPath.section >= self.detailDataArr.count {
newIndexPath.section = 0
}
guard let episodeList = self.detailDataArr[newIndexPath.section].episodeList else { return nil }
guard episodeList.count > 0 else { return nil }
if indexPath.row >= episodeList.count {
newIndexPath.row = 0
}
return newIndexPath
}
} }
//MARK: -------------- VPPlayerListViewControllerDataSource -------------- //MARK: -------------- VPPlayerListViewControllerDataSource --------------
extension VPDetailPlayerViewController: VPPlayerListViewControllerDataSource { extension VPDetailPlayerViewController: VPPlayerListViewControllerDataSource {
func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath, oldCell: UICollectionViewCell) -> UICollectionViewCell { func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath, oldCell: UICollectionViewCell) -> UICollectionViewCell {
// let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VPAdPlayerCell", for: indexPath)
let detailModel = self.detailDataArr[indexPath.section]
guard let cell = oldCell as? VPDetailPlayerCell else { return oldCell } guard let cell = oldCell as? VPDetailPlayerCell else { return oldCell }
cell.shortModel = detailModel?.shortPlayInfo cell.shortModel = detailModel.shortPlayInfo
cell.videoInfo = detailModel?.episodeList?[indexPath.row] cell.videoInfo = detailModel.episodeList?[indexPath.row]
cell.isLoop = false cell.isLoop = false
let upRow = indexPath.row - 1 let upRow = indexPath.row - 1
if upRow >= 0, let videoInfo = detailModel?.episodeList?[upRow], videoInfo.is_lock == true { if upRow >= 0, let videoInfo = detailModel.episodeList?[upRow], videoInfo.is_lock == true {
cell.hasLastEpisodeUnlocked = true cell.hasLastEpisodeUnlocked = true
} else { } else {
cell.hasLastEpisodeUnlocked = false cell.hasLastEpisodeUnlocked = false
@ -311,8 +334,13 @@ extension VPDetailPlayerViewController: VPPlayerListViewControllerDataSource {
return cell return cell
} }
func vp_numberOfSections(in viewController: VPVideoPlayerViewController) -> Int {
return self.detailDataArr.count
}
func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, _ collectionView: UICollectionView, numberOfItemsInSection section: Int, oldNumber: Int) -> Int { func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, _ collectionView: UICollectionView, numberOfItemsInSection section: Int, oldNumber: Int) -> Int {
return self.detailModel?.episodeList?.count ?? 0 let detailModel = self.detailDataArr[section]
return detailModel.episodeList?.count ?? 0
} }
@ -323,17 +351,22 @@ extension VPDetailPlayerViewController: VPPlayerListViewControllerDelegate {
func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, didChangeIndexPathForVisible indexPath: IndexPath) { func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, didChangeIndexPathForVisible indexPath: IndexPath) {
self.episodeView?.currentIndex = indexPath.row self.episodeView?.currentIndex = indexPath.row
} }
func vp_shouldAutoScrollNextEpisode(_ viewController: VPVideoPlayerViewController) -> Bool {
if episodeView != nil {
return false
}
return true
}
func vp_playerViewControllerLoadMoreData(playerViewController: VPVideoPlayerViewController) {
if self.detailDataArr.count > 0 {
self.requestMoreVideoDetail()
}
}
} }
////MARK: -------------- JXViewControllerPopDelegate --------------
//extension VPDetailPlayerViewController: JXViewControllerPopDelegate {
// func viewControllerPopShouldScrollBegan() -> Bool {
// self.handleBackButton()
// return false
// }
//}
//MARK: -------------- APP -------------- //MARK: -------------- APP --------------
extension VPDetailPlayerViewController { extension VPDetailPlayerViewController {
@ -359,18 +392,21 @@ extension VPDetailPlayerViewController {
VPHUD.dismiss() VPHUD.dismiss()
guard let self = self else { return } guard let self = self else { return }
guard let model = model else { return } guard let model = model else { return }
self.detailModel = model self.detailDataArr.removeAll()
self.detailDataArr.append(model)
self.videoNameLabel.text = model.shortPlayInfo?.name self.videoNameLabel.text = model.shortPlayInfo?.name
self.reloadData { [weak self] in self.reloadData { [weak self] in
guard let self = self else { return } guard let self = self else { return }
if let indexPath = indexPath { if let indexPath = indexPath {
self.scrollToItem(indexPath: indexPath, animated: false) guard let newIndexPath = self.verify(indexPath: indexPath) else { return }
self.scrollToItem(indexPath: newIndexPath, animated: false)
} else if let videoInfo = self.detailModel?.video_info { } else if let videoInfo = model.video_info {
var row: Int? var row: Int?
self.detailModel?.episodeList?.enumerated().forEach({ model.episodeList?.enumerated().forEach({
if $1.id == videoInfo.id { if $1.id == videoInfo.id {
row = $0 row = $0
} }
@ -387,6 +423,24 @@ extension VPDetailPlayerViewController {
} }
} }
///
private func requestMoreVideoDetail() {
guard let shortPlayId = shortPlayId else { return }
VPVideoAPI.requestMoreVideoDetail(shortPlayId: shortPlayId, revolution: VPVideoRevolutionManager.manager.revolution) { [weak self] model in
guard let self = self else { return }
guard let model = model else { return }
self.detailDataArr.append(model)
let section = self.detailDataArr.count - 1
let indexSet: IndexSet = IndexSet(integer: section)
self.collectionView.performBatchUpdates { [weak self] in
self?.collectionView.insertSections(indexSet)
}
}
}
private func requestRecommandDataArr() { private func requestRecommandDataArr() {
VPVideoAPI.requestDetailsRecommand { [weak self] list in VPVideoAPI.requestDetailsRecommand { [weak self] list in

View File

@ -9,19 +9,17 @@ import UIKit
@objc protocol VPPlayerListViewControllerDelegate { @objc protocol VPPlayerListViewControllerDelegate {
///
@objc optional func vp_playerViewControllerLoadNewDataV2(playerViewController: VPVideoPlayerViewController)
/// ///
@objc optional func vp_playerViewControllerShouldLoadMoreData(playerViewController: VPVideoPlayerViewController) -> Bool @objc optional func vp_playerViewControllerShouldLoadMoreData(playerViewController: VPVideoPlayerViewController) -> Bool
/// ///
@objc optional func vp_playerViewControllerLoadMoreData(playerViewController: VPVideoPlayerViewController) @objc optional func vp_playerViewControllerLoadMoreData(playerViewController: VPVideoPlayerViewController)
///
@objc optional func vp_playerViewControllerLoadUpMoreData(playerViewController: VPVideoPlayerViewController)
/// ///
@objc optional func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, didChangeIndexPathForVisible indexPath: IndexPath) @objc optional func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, didChangeIndexPathForVisible indexPath: IndexPath)
///
@objc optional func vp_shouldAutoScrollNextEpisode(_ viewController: VPVideoPlayerViewController) -> Bool
} }
@objc protocol VPPlayerListViewControllerDataSource { @objc protocol VPPlayerListViewControllerDataSource {
@ -31,7 +29,7 @@ import UIKit
func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, _ collectionView: UICollectionView, numberOfItemsInSection section: Int, oldNumber: Int) -> Int func vp_playerListViewController(_ viewController: VPVideoPlayerViewController, _ collectionView: UICollectionView, numberOfItemsInSection section: Int, oldNumber: Int) -> Int
@objc optional func vp_numberOfSections(in viewController: VPVideoPlayerViewController) -> Int
} }
@ -118,20 +116,9 @@ class VPVideoPlayerViewController: VPViewController {
self.viewModel.isPlaying = true self.viewModel.isPlaying = true
if getDataCount() - viewModel.currentIndexPath.row <= 2 { if (self.collectionView.contentSize.height - self.collectionView.contentOffset.y) / self.contentSize.height <= 3 {
self.loadMoreData() self.loadMoreData()
} }
// if isFirstPlay {
// isFirstPlay = false
// let offset = self.collectionView.contentOffset.y + 0.2
// self.collectionView.setContentOffset(CGPoint(x: 0, y: offset), animated: false)
//
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// let offset = self.collectionView.contentOffset.y
// self.collectionView.setContentOffset(CGPoint(x: 0, y: floor(offset)), animated: false)
// }
// }
} }
func pause() { func pause() {
@ -188,7 +175,7 @@ class VPVideoPlayerViewController: VPViewController {
CATransaction.setCompletionBlock { [weak self] in CATransaction.setCompletionBlock { [weak self] in
guard let self = self else { return } guard let self = self else { return }
if !animated { if !animated {
if viewModel.currentIndexPath != indexPath, indexPath.row < self.getDataCount() { if viewModel.currentIndexPath != indexPath {
self.skip(indexPath: indexPath) self.skip(indexPath: indexPath)
} else { } else {
self.play() self.play()
@ -205,8 +192,14 @@ class VPVideoPlayerViewController: VPViewController {
func currentPlayFinish() { func currentPlayFinish() {
self.viewModel.currentPlayer?.videoInfo?.play_seconds = 0 self.viewModel.currentPlayer?.videoInfo?.play_seconds = 0
if self.autoNextEpisode { var autoNextEpisode = self.autoNextEpisode
if let result = self.delegate?.vp_shouldAutoScrollNextEpisode?(self) {
autoNextEpisode = result
}
if autoNextEpisode {
scrollToNextEpisode() scrollToNextEpisode()
} else {
viewModel.currentPlayer?.replay()
} }
} }
@ -228,7 +221,8 @@ class VPVideoPlayerViewController: VPViewController {
extension VPVideoPlayerViewController { extension VPVideoPlayerViewController {
func getDataCount() -> Int { func getDataCount() -> Int {
return self.collectionView(self.collectionView, numberOfItemsInSection: 0) return Int(self.collectionView.contentSize.height / self.contentSize.height)
// return self.collectionView(self.collectionView, numberOfItemsInSection: 0)
} }
/// ///
@ -319,10 +313,16 @@ extension VPVideoPlayerViewController: UICollectionViewDelegate, UICollectionVie
didChangeIndexPathForVisible() didChangeIndexPathForVisible()
} }
return cell return cell
} }
func numberOfSections(in collectionView: UICollectionView) -> Int {
if let num = self.dataSource?.vp_numberOfSections?(in: self) {
return num
}
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let count = dataArr.count let count = dataArr.count
if let newCount = self.dataSource?.vp_playerListViewController(self, collectionView, numberOfItemsInSection: section, oldNumber: count) { if let newCount = self.dataSource?.vp_playerListViewController(self, collectionView, numberOfItemsInSection: section, oldNumber: count) {
@ -355,8 +355,8 @@ extension VPVideoPlayerViewController: UICollectionViewDelegate, UICollectionVie
} }
private func skip(indexPath: IndexPath) { private func skip(indexPath: IndexPath) {
viewModel.currentIndexPath = indexPath
guard let currentPlayer = self.collectionView.cellForItem(at: indexPath) as? VPPlayerProtocol else { return } guard let currentPlayer = self.collectionView.cellForItem(at: indexPath) as? VPPlayerProtocol else { return }
viewModel.currentIndexPath = indexPath
self.viewModel.currentPlayer = currentPlayer self.viewModel.currentPlayer = currentPlayer
// currentCell = self.collectionView.cellForItem(at: indexPath) as? BCListPlayerCell // currentCell = self.collectionView.cellForItem(at: indexPath) as? BCListPlayerCell
didChangeIndexPathForVisible() didChangeIndexPathForVisible()
@ -374,10 +374,6 @@ extension VPVideoPlayerViewController {
} }
} }
private func loadUpMoreData() {
self.delegate?.vp_playerViewControllerLoadUpMoreData?(playerViewController: self)
}
private func didChangeIndexPathForVisible() { private func didChangeIndexPathForVisible() {
self.delegate?.vp_playerListViewController?(self, didChangeIndexPathForVisible: viewModel.currentIndexPath) self.delegate?.vp_playerListViewController?(self, didChangeIndexPathForVisible: viewModel.currentIndexPath)
} }

View File

@ -0,0 +1,17 @@
//
// VPAdPlayerCell.swift
// Veloria
//
// Created by on 2025/7/1.
//
import UIKit
class VPAdPlayerCell: VPVideoPlayerCell {
override var ControlViewClass: VPVideoPlayerControlView.Type {
return VPAdPlayerControlView.self
}
}

View File

@ -0,0 +1,20 @@
//
// VPAdPlayerControlView.swift
// Veloria
//
// Created by on 2025/7/1.
//
import UIKit
class VPAdPlayerControlView: VPVideoPlayerControlView {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}

View File

@ -23,7 +23,8 @@ class VPVideoPlayerCell: VPCollectionViewCell, VPPlayerProtocol {
var shortModel: VPShortModel? { var shortModel: VPShortModel? {
didSet { didSet {
self.controlView.shortModel = shortModel self.controlView.shortModel = shortModel
coverImageView.vp_setImage(url: shortModel?.image_url) // coverImageView.vp_setImage(url: shortModel?.image_url)
player.coverImageView?.vp_setImage(url: shortModel?.image_url)
} }
} }
@ -60,10 +61,10 @@ class VPVideoPlayerCell: VPCollectionViewCell, VPPlayerProtocol {
return view return view
}() }()
private lazy var coverImageView: VPImageView = { // private lazy var coverImageView: VPImageView = {
let imageView = VPImageView() // let imageView = VPImageView()
return imageView // return imageView
}() // }()
private(set) lazy var controlView: VPVideoPlayerControlView = { private(set) lazy var controlView: VPVideoPlayerControlView = {
let view = ControlViewClass.init() let view = ControlViewClass.init()
@ -95,7 +96,7 @@ class VPVideoPlayerCell: VPCollectionViewCell, VPPlayerProtocol {
didSet { didSet {
controlView.isCurrent = isCurrent controlView.isCurrent = isCurrent
if !isCurrent { if !isCurrent {
self.coverImageView.isHidden = false // self.coverImageView.isHidden = false
} }
} }
} }
@ -154,12 +155,12 @@ extension VPVideoPlayerCell {
private func vp_setupUI() { private func vp_setupUI() {
contentView.addSubview(playerView) contentView.addSubview(playerView)
contentView.addSubview(coverImageView) // contentView.addSubview(coverImageView)
contentView.addSubview(controlView) contentView.addSubview(controlView)
coverImageView.snp.makeConstraints { make in // coverImageView.snp.makeConstraints { make in
make.edges.equalToSuperview() // make.edges.equalToSuperview()
} // }
playerView.snp.makeConstraints { make in playerView.snp.makeConstraints { make in
make.edges.equalToSuperview() make.edges.equalToSuperview()
@ -217,7 +218,7 @@ extension VPVideoPlayerCell: VPPlayerDelegate {
let loadState = self.player.loadState let loadState = self.player.loadState
let playState = self.player.playState let playState = self.player.playState
if isCurrent && (loadState == .playable || loadState == .playthroughOK) && (playState == .playing) { if isCurrent && (loadState == .playable || loadState == .playthroughOK) && (playState == .playing) {
self.coverImageView.isHidden = true // self.coverImageView.isHidden = true
} }
} }

View File

@ -99,6 +99,16 @@ class VPPlayer: NSObject {
} }
} }
var coverImageView: UIImageView? {
return self.player.view.coverImageView
}
private lazy var playerController: ZFPlayerController = {
let playerController = ZFPlayerController()
playerController.currentPlayerManager = player
return playerController
}()
private lazy var player: ZFAVPlayerManager = { private lazy var player: ZFAVPlayerManager = {
let player = ZFAVPlayerManager() let player = ZFAVPlayerManager()
player.shouldAutoPlay = false player.shouldAutoPlay = false
@ -172,8 +182,6 @@ class VPPlayer: NSObject {
func start() { func start() {
self.systemPause = false self.systemPause = false
self.isPlaying = true self.isPlaying = true
// if self.interruptionType != .began {
// }
player.play() player.play()
UIApplication.shared.isIdleTimerDisabled = true UIApplication.shared.isIdleTimerDisabled = true