240 lines
7.6 KiB
Swift
240 lines
7.6 KiB
Swift
//
|
|
// FAPlayerDetailControlView.swift
|
|
// Fableon
|
|
//
|
|
// Created by 长沙鸿瑶 on 2025/9/16.
|
|
//
|
|
|
|
import UIKit
|
|
import JXPlayer
|
|
import SwiftUI
|
|
|
|
class FAPlayerDetailControlView: JXPlayerListControlView {
|
|
|
|
|
|
override var viewModel: JXPlayerListViewModel? {
|
|
didSet {
|
|
self.viewModel?.addObserver(self, forKeyPath: "isPlaying", context: nil)
|
|
}
|
|
}
|
|
|
|
var fa_viewModel: FAShortDetailViewModel? {
|
|
return self.viewModel as? FAShortDetailViewModel
|
|
}
|
|
|
|
override var model: Any? {
|
|
didSet {
|
|
let model = self.model as? FAVideoInfoModel
|
|
|
|
updateEp()
|
|
}
|
|
}
|
|
|
|
var shortModel: FAShortPlayModel? {
|
|
didSet {
|
|
updateEp()
|
|
shortNameLabel.text = shortModel?.name
|
|
textLabel.text = shortModel?.fa_description
|
|
|
|
collectButton.isSelected = shortModel?.is_collect == true
|
|
}
|
|
}
|
|
|
|
override var durationTime: TimeInterval {
|
|
didSet {
|
|
updateProgress()
|
|
}
|
|
}
|
|
|
|
override var currentTime: TimeInterval {
|
|
didSet {
|
|
updateProgress()
|
|
}
|
|
}
|
|
|
|
override var isCurrent: Bool {
|
|
didSet {
|
|
playButton.setNeedsUpdateConfiguration()
|
|
}
|
|
}
|
|
|
|
private lazy var epButton: UIHostingController<FAPlayerEpUIButton> = {
|
|
let view = FAPlayerEpUIButton()
|
|
let hc = UIHostingController(rootView: view)
|
|
hc.view.backgroundColor = .clear
|
|
return hc
|
|
}()
|
|
|
|
private lazy var progressView: FAPlayerProgressView = {
|
|
let view = FAPlayerProgressView()
|
|
view.insets = .init(top: 10, left: 16, bottom: 10, right: 16)
|
|
view.panFinish = { [weak self] progress in
|
|
guard let self = self else { return }
|
|
self.viewModel?.seekTo(Float(progress))
|
|
}
|
|
return view
|
|
}()
|
|
|
|
private lazy var textLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.font = .font(ofSize: 12, weight: .regular);
|
|
label.textColor = UIColor(named: .color_FFFFFF)!.withAlphaComponent(0.8)
|
|
label.numberOfLines = 2
|
|
return label
|
|
}()
|
|
|
|
private lazy var shortNameLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.font = .font(ofSize: 16, weight: .medium)
|
|
label.textColor = UIColor(named: .color_FFFFFF)
|
|
return label
|
|
}()
|
|
|
|
private lazy var playButton: UIButton = {
|
|
let config = UIButton.Configuration.plain()
|
|
|
|
let button = UIButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in
|
|
self?.fa_viewModel?.userSwitchPlayAndPause()
|
|
}))
|
|
button.configurationUpdateHandler = { [weak self] button in
|
|
guard let self = self else { return }
|
|
|
|
if self.viewModel?.isPlaying == true || !isCurrent {
|
|
button.configuration?.image = UIImage(named: "pause_icon")
|
|
} else {
|
|
button.configuration?.image = UIImage(named: "play_icon_01")
|
|
}
|
|
}
|
|
return button
|
|
}()
|
|
|
|
private lazy var collectButton: UIButton = {
|
|
var config = UIButton.Configuration.plain()
|
|
config.background.backgroundColor = .clear
|
|
let button = UIButton(configuration: config)
|
|
button.configurationUpdateHandler = { [weak self] button in
|
|
guard let self = self else { return }
|
|
if button.isSelected {
|
|
button.configuration?.image = UIImage(named: "collect_star_icon_selected")
|
|
} else {
|
|
button.configuration?.image = UIImage(named: "collect_star_icon")
|
|
}
|
|
}
|
|
button.addAction(UIAction(handler: { [weak self] _ in
|
|
guard let self = self else { return }
|
|
guard let shortPlayId = self.shortModel?.short_play_id else { return }
|
|
let videoId = (self.model as? FAVideoInfoModel)?.short_play_video_id
|
|
let isCollect = !(self.shortModel?.is_collect ?? false)
|
|
|
|
FAAPI.requestShortCollect(isCollect: isCollect, shortPlayId: shortPlayId, videoId: videoId, success: nil)
|
|
|
|
}), for: .touchUpInside)
|
|
|
|
return button
|
|
}()
|
|
|
|
|
|
|
|
deinit {
|
|
NotificationCenter.default.removeObserver(self)
|
|
}
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(updateShortCollectStateNotification), name: FAAPI.updateShortCollectStateNotification, object: nil)
|
|
|
|
fa_setupLayout()
|
|
}
|
|
|
|
@MainActor required init?(coder: NSCoder) {
|
|
super.init(coder: coder)
|
|
}
|
|
|
|
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
|
if keyPath == "isPlaying" {
|
|
playButton.setNeedsUpdateConfiguration()
|
|
}
|
|
}
|
|
|
|
private func updateEp() {
|
|
let model = self.model as? FAVideoInfoModel
|
|
|
|
let text = "Ep.##".localizedReplace(text: model?.episode ?? "") + "/" + "Ep.##".localizedReplace(text: "\(shortModel?.episode_total ?? 0)")
|
|
var view = FAPlayerEpUIButton(text: text)
|
|
view.clickHandle = { [weak self] in
|
|
self?.fa_viewModel?.onEpSelectorView()
|
|
}
|
|
epButton.rootView = view
|
|
}
|
|
|
|
private func updateProgress() {
|
|
guard durationTime > 0 else {
|
|
progressView.progress = 0
|
|
return
|
|
}
|
|
progressView.progress = currentTime / durationTime
|
|
}
|
|
|
|
@objc private func updateShortCollectStateNotification(sender: Notification) {
|
|
guard let userInfo = sender.userInfo else { return }
|
|
guard let shortPlayId = userInfo["id"] as? String else { return }
|
|
guard let state = userInfo["state"] as? Bool else { return }
|
|
guard shortPlayId == self.shortModel?.short_play_id else { return }
|
|
self.shortModel?.is_collect = state
|
|
|
|
collectButton.isSelected = state
|
|
}
|
|
}
|
|
|
|
extension FAPlayerDetailControlView {
|
|
|
|
private func fa_setupLayout() {
|
|
|
|
addSubview(epButton.view)
|
|
addSubview(progressView)
|
|
addSubview(textLabel)
|
|
addSubview(shortNameLabel)
|
|
addSubview(playButton)
|
|
addSubview(collectButton)
|
|
|
|
|
|
epButton.view.snp.makeConstraints { make in
|
|
make.left.equalToSuperview().offset(16)
|
|
make.centerX.equalToSuperview()
|
|
make.bottom.equalToSuperview().offset(-(UIScreen.safeBottom + 10))
|
|
}
|
|
|
|
progressView.snp.makeConstraints { make in
|
|
make.left.equalToSuperview()
|
|
make.centerX.equalToSuperview()
|
|
make.bottom.equalTo(epButton.view.snp.top).offset(-8)
|
|
}
|
|
|
|
textLabel.snp.makeConstraints { make in
|
|
make.left.equalToSuperview().offset(16)
|
|
make.right.lessThanOrEqualToSuperview().offset(-84)
|
|
make.bottom.equalTo(progressView.snp.top).offset(1)
|
|
}
|
|
|
|
shortNameLabel.snp.makeConstraints { make in
|
|
make.left.equalToSuperview().offset(16)
|
|
make.bottom.equalTo(textLabel.snp.top).offset(-5)
|
|
make.right.lessThanOrEqualToSuperview().offset(-84)
|
|
}
|
|
|
|
playButton.snp.makeConstraints { make in
|
|
make.center.equalToSuperview()
|
|
}
|
|
|
|
collectButton.snp.makeConstraints { make in
|
|
make.top.equalToSuperview().offset(UIScreen.safeTop)
|
|
make.right.equalToSuperview().offset(-16)
|
|
make.height.equalTo(44)
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|