225 lines
5.4 KiB
Swift
225 lines
5.4 KiB
Swift
//
|
|
// VPVideoPlayerCell.swift
|
|
// Veloria
|
|
//
|
|
// Created by 湖南秦九 on 2025/5/22.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
class VPVideoPlayerCell: VPCollectionViewCell, VPPlayerProtocol {
|
|
|
|
var ControlViewClass: VPVideoPlayerControlView.Type {
|
|
return VPVideoPlayerControlView.self
|
|
}
|
|
|
|
|
|
weak var viewModel: VPVideoPlayViewModel? {
|
|
didSet {
|
|
self.controlView.viewModel = self.viewModel
|
|
}
|
|
}
|
|
|
|
var shortModel: VPShortModel? {
|
|
didSet {
|
|
self.controlView.shortModel = shortModel
|
|
coverImageView.vp_setImage(url: shortModel?.image_url)
|
|
}
|
|
}
|
|
|
|
var videoInfo: VPVideoInfoModel? {
|
|
didSet {
|
|
self.controlView.progress = 0
|
|
self.controlView.currentTime = 0
|
|
self.controlView.durationTime = 0
|
|
|
|
self.controlView.videoInfo = videoInfo
|
|
|
|
player.setPlayUrl(url: videoInfo?.video_url ?? "")
|
|
|
|
}
|
|
}
|
|
|
|
var isLoop = true {
|
|
didSet {
|
|
player.isLoop = isLoop
|
|
}
|
|
}
|
|
|
|
|
|
private lazy var player: VPPlayer = {
|
|
let player = VPPlayer()
|
|
player.playerView = playerView
|
|
player.delegate = self
|
|
return player
|
|
}()
|
|
|
|
//MARK: UI属性
|
|
private lazy var playerView: UIView = {
|
|
let view = UIView()
|
|
return view
|
|
}()
|
|
|
|
private lazy var coverImageView: VPImageView = {
|
|
let imageView = VPImageView()
|
|
return imageView
|
|
}()
|
|
|
|
private(set) lazy var controlView: VPVideoPlayerControlView = {
|
|
let view = ControlViewClass.init()
|
|
view.panProgressFinishBlock = { [weak self] progress in
|
|
guard let self = self else { return }
|
|
let duration = CGFloat(self.player.duration)
|
|
let toTime = progress * duration
|
|
self.player.seekToTime(toTime: Int(toTime))
|
|
}
|
|
return view
|
|
}()
|
|
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
|
|
vp_setupUI()
|
|
}
|
|
|
|
@MainActor required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
|
|
//MARK: VPPlayerProtocol
|
|
var playerFinishHadle: (() -> Void)?
|
|
|
|
var isCurrent: Bool = false {
|
|
didSet {
|
|
controlView.isCurrent = isCurrent
|
|
if !isCurrent {
|
|
self.coverImageView.isHidden = false
|
|
}
|
|
}
|
|
}
|
|
|
|
var hasLastEpisodeUnlocked: Bool = false
|
|
|
|
var duration: Int {
|
|
get {
|
|
return player.duration
|
|
}
|
|
}
|
|
|
|
var currentPosition: Int {
|
|
get {
|
|
player.currentPosition
|
|
}
|
|
}
|
|
|
|
var rate: Float {
|
|
set {
|
|
player.rate = newValue
|
|
}
|
|
get {
|
|
player.rate
|
|
}
|
|
}
|
|
|
|
func prepare() {
|
|
player.setPlayUrl(url: videoInfo?.video_url ?? "")
|
|
// self.player.stop()
|
|
// self.player.prepare()
|
|
}
|
|
|
|
func start() {
|
|
player.start()
|
|
}
|
|
|
|
func pause() {
|
|
player.pause()
|
|
}
|
|
|
|
func replay() {
|
|
player.replay()
|
|
}
|
|
|
|
func seekToTime(toTime: Int) {
|
|
player.seekToTime(toTime: toTime)
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
extension VPVideoPlayerCell {
|
|
|
|
private func vp_setupUI() {
|
|
contentView.addSubview(playerView)
|
|
contentView.addSubview(coverImageView)
|
|
contentView.addSubview(controlView)
|
|
|
|
coverImageView.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview()
|
|
}
|
|
|
|
playerView.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview()
|
|
}
|
|
|
|
controlView.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//MARK: -------------- SPPlayerDelegate --------------
|
|
extension VPVideoPlayerCell: VPPlayerDelegate {
|
|
|
|
func vp_playCompletion(_ player: VPPlayer) {
|
|
// self.playerFinishHadle?()
|
|
self.viewModel?.handlePlayFinish?()
|
|
}
|
|
|
|
func vp_playLoadingEnd(_ player: VPPlayer) {
|
|
|
|
}
|
|
|
|
func vp_playTimeChanged(_ player: VPPlayer, currentTime: Int, duration: Int) {
|
|
controlView.progress = CGFloat(currentTime) / CGFloat(duration)
|
|
controlView.currentTime = currentTime
|
|
controlView.durationTime = duration
|
|
self.viewModel?.handlePlayTimeDidChange?(currentTime)
|
|
}
|
|
|
|
func vp_firstRenderedStart(_ player: VPPlayer) {
|
|
|
|
}
|
|
|
|
func vp_player(_ player: VPPlayer, playStateDidChanged state: VPPlayer.PlayState) {
|
|
updateCoverShowState()
|
|
}
|
|
|
|
func vp_player(_ player: VPPlayer, loadStateDidChange state: VPPlayer.LoadState) {
|
|
if state == .prepare || state == .stalled {
|
|
self.controlView.isLoading = true
|
|
} else {
|
|
self.controlView.isLoading = false
|
|
}
|
|
updateCoverShowState()
|
|
}
|
|
|
|
func vp_playerReadyToPlay(_ player: VPPlayer) {
|
|
self.seekToTime(toTime: (videoInfo?.play_seconds ?? 0) / 1000)
|
|
player.rate = self.viewModel?.rateModel.rate.getRate() ?? 1
|
|
}
|
|
|
|
private func updateCoverShowState() {
|
|
let loadState = self.player.loadState
|
|
let playState = self.player.playState
|
|
if isCurrent && (loadState == .playable || loadState == .playthroughOK) && (playState == .playing) {
|
|
self.coverImageView.isHidden = true
|
|
}
|
|
}
|
|
|
|
}
|