244 lines
7.7 KiB
Swift
244 lines
7.7 KiB
Swift
//
|
|
// VPDetailPlayerControlView.swift
|
|
// Veloria
|
|
//
|
|
// Created by 湖南秦九 on 2025/5/23.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
class VPDetailPlayerControlView: VPVideoPlayerControlView {
|
|
|
|
override var viewModel: VPVideoPlayViewModel? {
|
|
didSet {
|
|
self.viewModel?.addObserver(self, forKeyPath: "rateModel", options: .new, context: nil)
|
|
|
|
rateButton.setTitle(self.viewModel?.rateModel.formatString(), for: .normal)
|
|
}
|
|
}
|
|
|
|
var hasLastEpisodeUnlocked = false {
|
|
didSet {
|
|
self.lockView.hasLastEpisodeUnlocked = hasLastEpisodeUnlocked
|
|
}
|
|
}
|
|
|
|
|
|
override var videoInfo: VPVideoInfoModel? {
|
|
didSet {
|
|
epView.setTitle(String(format: "EP.%@".localized, "\(videoInfo?.episode ?? "0")"), for: .normal)
|
|
lockView.isHidden = !(videoInfo?.is_lock ?? false)
|
|
lockView.videoInfo = videoInfo
|
|
}
|
|
}
|
|
|
|
override var shortModel: VPShortModel? {
|
|
didSet {
|
|
allEpView.setTitle(String(format: "All %@ Episodes".localized, "\(shortModel?.episode_total ?? 0)"), for: .normal)
|
|
}
|
|
}
|
|
|
|
override var durationTime: Int {
|
|
didSet {
|
|
updateTimeLabel()
|
|
}
|
|
}
|
|
|
|
override var currentTime: Int {
|
|
didSet {
|
|
updateTimeLabel()
|
|
}
|
|
}
|
|
|
|
//MARK: -------------- UI属性 --------------
|
|
private lazy var bottomView: VPGradientView = {
|
|
let view = VPGradientView()
|
|
view.isUserInteractionEnabled = false
|
|
view.colors = [UIColor.color000000(alpha: 0).cgColor, UIColor.color000000(alpha: 0.5).cgColor, UIColor.color000000(alpha: 1).cgColor]
|
|
view.locations = [0, 0.5, 1]
|
|
view.startPoint = .init(x: 0.5, y: 0)
|
|
view.endPoint = .init(x: 0.5, y: 1)
|
|
return view
|
|
}()
|
|
|
|
private lazy var epBgView: UIView = {
|
|
let view = UIButton(type: .custom)
|
|
view.setBackgroundImage(UIImage(color: .color949494(alpha: 0.4)), for: .normal)
|
|
view.layer.cornerRadius = 15
|
|
view.layer.masksToBounds = true
|
|
view.addTarget(self, action: #selector(handleEpisodesButton), for: .touchUpInside)
|
|
return view
|
|
}()
|
|
|
|
private lazy var epView: UIButton = {
|
|
let view = JXButton(type: .custom)
|
|
view.isUserInteractionEnabled = false
|
|
view.titleDirection = .right
|
|
view.jx_font = .fontRegular(ofSize: 13)
|
|
view.space = 5
|
|
view.setTitleColor(.colorFFFFFF(), for: .normal)
|
|
view.setImage(UIImage(named: "ep_icon_01"), for: .normal)
|
|
return view
|
|
}()
|
|
|
|
private lazy var allEpView: UIButton = {
|
|
let view = JXButton(type: .custom)
|
|
view.isUserInteractionEnabled = false
|
|
view.titleDirection = .left
|
|
view.jx_font = .fontRegular(ofSize: 13)
|
|
view.space = 4
|
|
view.setTitleColor(.colorBEBEBE(), for: .normal)
|
|
view.setImage(UIImage(named: "arrow_up_icon_01"), for: .normal)
|
|
return view
|
|
}()
|
|
|
|
private lazy var rateButton: UIButton = {
|
|
let button = UIButton(type: .custom)
|
|
button.setBackgroundImage(UIImage(color: .color949494(alpha: 0.4)), for: .normal)
|
|
button.layer.cornerRadius = 15
|
|
button.layer.masksToBounds = true
|
|
button.setTitleColor(.colorFFFFFF(), for: .normal)
|
|
button.titleLabel?.font = .fontRegular(ofSize: 13)
|
|
button.addTarget(self, action: #selector(handleRateButton), for: .touchUpInside)
|
|
return button
|
|
}()
|
|
|
|
private lazy var timeLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.font = .fontRegular(ofSize: 12)
|
|
label.textColor = .colorFFFFFB(alpha: 0.9)
|
|
label.isUserInteractionEnabled = false
|
|
return label
|
|
}()
|
|
|
|
///倍速选择
|
|
private lazy var rateSelectedView: VPRateSelectedView = {
|
|
let view = VPRateSelectedView()
|
|
view.didSelected = { [weak self] model in
|
|
guard let self = self else { return }
|
|
self.viewModel?.rateModel = model
|
|
}
|
|
return view
|
|
}()
|
|
|
|
private lazy var lockView: VPVideoLockView = {
|
|
let view = VPVideoLockView()
|
|
view.clickUnlockButton = { [weak self] in
|
|
guard let self = self else { return }
|
|
self.viewModel?.handleUnlock?()
|
|
}
|
|
return view
|
|
}()
|
|
|
|
deinit {
|
|
self.viewModel?.removeObserver(self, forKeyPath: "rateModel")
|
|
}
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
|
|
vp_setupUI()
|
|
}
|
|
|
|
@MainActor required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
|
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
|
|
|
|
if keyPath == "rateModel" {
|
|
rateButton.setTitle(self.viewModel?.rateModel.formatString(), for: .normal)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension VPDetailPlayerControlView {
|
|
|
|
private func updateTimeLabel() {
|
|
let currentTime = self.currentTime.formatTimeGroup()
|
|
let durationTime = self.durationTime.formatTimeGroup()
|
|
|
|
timeLabel.text = "\(currentTime.1):\(currentTime.2)/\(durationTime.1):\(durationTime.2)"
|
|
}
|
|
|
|
@objc private func handleEpisodesButton() {
|
|
self.viewModel?.handleEpisode?()
|
|
}
|
|
|
|
@objc private func handleRateButton() {
|
|
addSubview(rateSelectedView)
|
|
rateSelectedView.currentRateModel = self.viewModel?.rateModel
|
|
|
|
rateSelectedView.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension VPDetailPlayerControlView {
|
|
|
|
private func vp_setupUI() {
|
|
progressView.lineWidth = 3
|
|
progressView.insets = .init(top: 20, left: 15, bottom: 10, right: 15)
|
|
|
|
addSubview(bottomView)
|
|
addSubview(epBgView)
|
|
epBgView.addSubview(epView)
|
|
epBgView.addSubview(allEpView)
|
|
addSubview(rateButton)
|
|
addSubview(timeLabel)
|
|
addSubview(lockView)
|
|
|
|
self.sendSubviewToBack(self.bottomView)
|
|
|
|
progressView.snp.remakeConstraints { make in
|
|
make.left.right.equalToSuperview()
|
|
make.bottom.equalTo(epBgView.snp.top)
|
|
}
|
|
|
|
rightToolView.snp.updateConstraints { make in
|
|
make.bottom.equalToSuperview().offset(-(UIScreen.tabbarSafeBottomMargin + 150))
|
|
}
|
|
|
|
bottomView.snp.makeConstraints { make in
|
|
make.left.right.bottom.equalToSuperview()
|
|
make.height.equalTo(UIScreen.tabbarSafeBottomMargin + 100)
|
|
}
|
|
|
|
epBgView.snp.makeConstraints { make in
|
|
make.left.equalToSuperview().offset(15)
|
|
make.bottom.equalToSuperview().offset(-(UIScreen.tabbarSafeBottomMargin + 10))
|
|
make.height.equalTo(30)
|
|
}
|
|
|
|
epView.snp.makeConstraints { make in
|
|
make.left.equalToSuperview().offset(10)
|
|
make.centerY.equalToSuperview()
|
|
}
|
|
|
|
allEpView.snp.makeConstraints { make in
|
|
make.centerY.equalToSuperview()
|
|
make.right.equalToSuperview().offset(-10)
|
|
}
|
|
|
|
rateButton.snp.makeConstraints { make in
|
|
make.right.equalToSuperview().offset(-15)
|
|
make.left.equalTo(epBgView.snp.right).offset(10)
|
|
make.height.top.equalTo(epBgView)
|
|
make.width.equalTo(50)
|
|
}
|
|
|
|
timeLabel.snp.makeConstraints { make in
|
|
make.left.equalToSuperview().offset(15)
|
|
make.bottom.equalTo(epBgView.snp.top).offset(-16)
|
|
}
|
|
|
|
lockView.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview()
|
|
}
|
|
}
|
|
|
|
}
|