367 lines
19 KiB
Swift
367 lines
19 KiB
Swift
//
|
||
// MPPositive_PersonalisedRecommendationsTableViewCell.swift
|
||
// relax.offline.mp3.music
|
||
//
|
||
// Created by Mr.Zhou on 2024/8/28.
|
||
//
|
||
|
||
import UIKit
|
||
import Lottie
|
||
class MPPositive_PersonalisedRecommendationsTableViewCell: UITableViewCell, UIViewControllerTransitioningDelegate {
|
||
///主标题(因为你听过/因为你喜欢)
|
||
private lazy var titleLabel:UILabel = createLabel(font: .systemFont(ofSize: 14*width), textColor: .init(hex: "#FFFFFF", alpha: 0.6), textAlignment: .left)
|
||
///副标题(随机项的内容值)
|
||
private lazy var subTitleLabel:UILabel = {
|
||
let label = createLabel(font: .systemFont(ofSize: 16*width, weight: .bold), textColor: .white, textAlignment: .left)
|
||
label.isUserInteractionEnabled = true
|
||
label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(findRecommonedEvent(_ :))))
|
||
return label
|
||
}()
|
||
///刷新Icon
|
||
private lazy var reloadlotView:LottieAnimationView = {
|
||
//获取动画View
|
||
let json = Bundle.main.path(forResource: "Reload_Animation", ofType: "json")
|
||
let animationView:LottieAnimationView = .init(filePath: json ?? "")
|
||
//无限循环
|
||
animationView.loopMode = .loop
|
||
//填充
|
||
animationView.contentMode = .scaleAspectFill
|
||
animationView.backgroundColor = .clear
|
||
return animationView
|
||
}()
|
||
///个性化布局类型
|
||
enum PersonlShowType:Int {
|
||
case Singles = 0
|
||
case Lists = 1
|
||
case Artists = 2
|
||
///对应布局layout
|
||
var layout:UICollectionViewFlowLayout {
|
||
let layout = UICollectionViewFlowLayout()
|
||
switch self {
|
||
case .Singles:
|
||
layout.itemSize = .init(width: screen_Width*0.85, height: 70*width)
|
||
layout.sectionInset = .init(top: 10*width, left: 16*width, bottom: 0, right: 16*width)
|
||
layout.minimumLineSpacing = 0
|
||
layout.minimumInteritemSpacing = 0
|
||
layout.scrollDirection = .horizontal
|
||
case .Lists:
|
||
layout.sectionInset = .init(top: 15*width, left: 16*width, bottom: 0, right: 16*width)
|
||
layout.minimumLineSpacing = 8*width
|
||
layout.itemSize = .init(width: 109*width, height: 152*width)
|
||
layout.minimumInteritemSpacing = 0
|
||
layout.scrollDirection = .horizontal
|
||
case .Artists:
|
||
layout.sectionInset = .init(top: 15*width, left: 16*width, bottom: 0, right: 16*width)
|
||
layout.minimumLineSpacing = 8*width
|
||
layout.itemSize = .init(width: 94*width, height: 116*width)
|
||
layout.minimumInteritemSpacing = 0
|
||
layout.scrollDirection = .horizontal
|
||
}
|
||
return layout
|
||
}
|
||
}
|
||
//展示collectionView
|
||
private lazy var collectionView:UICollectionView = {
|
||
let collectionView:UICollectionView = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), collectionViewLayout: showType.layout)
|
||
collectionView.showsVerticalScrollIndicator = false
|
||
collectionView.showsHorizontalScrollIndicator = false
|
||
collectionView.backgroundColor = .clear
|
||
collectionView.dataSource = self
|
||
collectionView.delegate = self
|
||
collectionView.register(MPPositive_HomeSingleCollectionViewCell.self, forCellWithReuseIdentifier: MPPositive_HomeSingleCollectionViewCellID)
|
||
collectionView.register(MPPositive_HomeListThirdCollectionViewCell.self, forCellWithReuseIdentifier: MPPositive_HomeListThirdCollectionViewCellID)
|
||
collectionView.register(MPPositive_HomeListFourthCollectionViewCell.self, forCellWithReuseIdentifier: MPPositive_HomeListFourthCollectionViewCellID)
|
||
return collectionView
|
||
}()
|
||
private let MPPositive_HomeSingleCollectionViewCellID = "MPPositive_HomeSingleCollectionViewCell"
|
||
private let MPPositive_HomeListThirdCollectionViewCellID = "MPPositive_HomeListThirdCollectionViewCell"
|
||
private let MPPositive_HomeListFourthCollectionViewCellID = "MPPositive_HomeListFourthCollectionViewCell"
|
||
var personlViewModel:MPPositive_PersonalListViewModel?{
|
||
didSet{
|
||
titleLabel.text = personlViewModel?.title
|
||
subTitleLabel.text = titleLabel.text == "Because you listen".localizableString() ? personlViewModel?.random?.title:personlViewModel?.random?.subtitle
|
||
reloadlotView.stop()
|
||
if let first = personlViewModel?.items.first, first.browseItem.itemType == .single {
|
||
showType = .Singles
|
||
}else {
|
||
//判断是列表还是艺术家
|
||
if personlViewModel?.items.first?.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||
showType = .Artists
|
||
}else {
|
||
showType = .Lists
|
||
}
|
||
}
|
||
}
|
||
}
|
||
var reloadRecommondBlock:((Int) -> Void)?
|
||
///列表展示类型
|
||
var showType:PersonlShowType = .Singles{
|
||
didSet{
|
||
collectionView.collectionViewLayout = showType.layout
|
||
collectionView.reloadData()
|
||
collectionView.scrollToItem(at: .init(row: 0, section: 0), at: .top, animated: false)
|
||
}
|
||
}
|
||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||
confirgue()
|
||
}
|
||
|
||
required init?(coder: NSCoder) {
|
||
super.init(coder: coder)
|
||
}
|
||
override func awakeFromNib() {
|
||
super.awakeFromNib()
|
||
// Initialization code
|
||
}
|
||
//配置
|
||
private func confirgue() {
|
||
selectionStyle = .none
|
||
backgroundColor = .clear
|
||
contentView.backgroundColor = .clear
|
||
//配置UI
|
||
contentView.addSubview(titleLabel)
|
||
titleLabel.snp.makeConstraints { make in
|
||
make.left.equalToSuperview().offset(16*width)
|
||
make.top.equalTo(8*width)
|
||
}
|
||
contentView.addSubview(subTitleLabel)
|
||
subTitleLabel.snp.makeConstraints { make in
|
||
make.left.equalTo(titleLabel)
|
||
make.top.equalTo(titleLabel.snp.bottom).offset(6*width)
|
||
make.width.equalToSuperview().multipliedBy(0.6)
|
||
}
|
||
let reloadView = createReloadView()
|
||
contentView.addSubview(reloadView)
|
||
reloadView.snp.makeConstraints { make in
|
||
make.top.equalToSuperview().offset(10*width)
|
||
make.right.equalToSuperview().offset(-16*width)
|
||
make.width.equalTo(85*width)
|
||
make.height.equalTo(35*width)
|
||
}
|
||
contentView.addSubview(collectionView)
|
||
collectionView.snp.makeConstraints { make in
|
||
make.top.equalTo(subTitleLabel.snp.bottom).offset(5*width)
|
||
make.left.right.equalToSuperview()
|
||
make.bottom.equalToSuperview().offset(-30*width)
|
||
}
|
||
}
|
||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||
super.setSelected(selected, animated: animated)
|
||
|
||
// Configure the view for the selected state
|
||
}
|
||
//生成一个刷新按钮View
|
||
private func createReloadView() -> UIView {
|
||
let view:UIView = .init(frame: .init(x: 0, y: 0, width: 60*width, height: 32*width))
|
||
view.backgroundColor = .init(hex: "#FFFFFF", alpha: 0.1)
|
||
view.layer.masksToBounds = true
|
||
view.layer.cornerRadius = 8*width
|
||
view.addSubview(reloadlotView)
|
||
reloadlotView.snp.makeConstraints { make in
|
||
make.width.height.equalTo(20*width)
|
||
make.centerY.equalToSuperview()
|
||
make.left.equalToSuperview().offset(10*width)
|
||
}
|
||
reloadlotView.stop()
|
||
//生成一个Label
|
||
let label = createLabel("Refresh", font: .systemFont(ofSize: 12*width), textColor: .white, textAlignment: .center)
|
||
view.addSubview(label)
|
||
label.snp.makeConstraints { make in
|
||
make.centerY.equalToSuperview()
|
||
make.left.equalTo(reloadlotView.snp.right).offset(4*width)
|
||
}
|
||
view.isUserInteractionEnabled = true
|
||
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(reloadRecommonedEvent(_ :))))
|
||
return view
|
||
}
|
||
//刷新个性化模块
|
||
@objc private func reloadRecommonedEvent(_ sender:UITapGestureRecognizer) {
|
||
reloadlotView.play()
|
||
//刷新推荐信息
|
||
if titleLabel.text == "Because you listen".localizableString() {
|
||
reloadRecommondBlock?(1)
|
||
}else {
|
||
reloadRecommondBlock?(2)
|
||
}
|
||
}
|
||
//查看个性化内容
|
||
@objc private func findRecommonedEvent(_ sender:UITapGestureRecognizer) {
|
||
guard let item = (self.personlViewModel?.random?.recently) else {
|
||
return
|
||
}
|
||
switch showType {
|
||
case.Singles:
|
||
//单曲/视频跳转
|
||
MPPositive_Debouncer.shared.call {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||
playOfflineSongs(item.videoId ?? "")
|
||
return
|
||
}
|
||
MP_AnalyticsManager.shared.home_b_module_clickAction(titleLabel.text ?? "")
|
||
MP_AnalyticsManager.shared.song_clickAction("Home")
|
||
//优先清除数据
|
||
MP_PlayerManager.shared.loadPlayer = nil
|
||
//弹出播放器
|
||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||
MP_AnalyticsManager.shared.player_b_impAction()
|
||
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||
MP_NetWorkManager.shared.requestNextList(item.playListID ?? "", videoId: item.videoId ?? "", clickTrackingParams: ""){ [weak self] listSongs in
|
||
guard let self = self else {return}
|
||
//回掉的数据并不完善,生成一个playerloadViewModel
|
||
let lodaViewModel = MPPositive_PlayerLoadViewModel(listSongs, currentVideoId: item.videoId ?? "")
|
||
lodaViewModel.improveData(item.videoId ?? "")
|
||
//更改播放器播放类型
|
||
MP_PlayerManager.shared.setPlayType(.normal)
|
||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||
MP_AnalyticsManager.shared.player_b_listAction()
|
||
}
|
||
}
|
||
default:
|
||
//展示搜索内容
|
||
MP_AnalyticsManager.shared.search_from_actionAction("Home")
|
||
let resultVC = MPPositive_SearchResultShowViewController(item.subtitle ?? "", isShowAd: true)
|
||
self.parentController()?.navigationController?.pushViewController(resultVC, animated: false)
|
||
}
|
||
|
||
}
|
||
|
||
//经过计算设置tableViewCell真实高度
|
||
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
|
||
let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
|
||
collectionView.layoutIfNeeded()
|
||
switch showType {
|
||
case .Singles:
|
||
let height = showType.layout.itemSize.height*3 + showType.layout.sectionInset.top + 10
|
||
return CGSize(width: size.width, height: size.height + height)
|
||
default:
|
||
let height = showType.layout.itemSize.height + showType.layout.sectionInset.top + showType.layout.sectionInset.bottom
|
||
return CGSize(width: size.width, height: size.height + height)
|
||
}
|
||
}
|
||
}
|
||
//MARK: - collectionView
|
||
extension MPPositive_PersonalisedRecommendationsTableViewCell:UICollectionViewDataSource, UICollectionViewDelegate {
|
||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||
return personlViewModel?.items.count ?? 0
|
||
}
|
||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||
switch showType {
|
||
case .Singles:
|
||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_HomeSingleCollectionViewCellID, for: indexPath) as! MPPositive_HomeSingleCollectionViewCell
|
||
cell.itemViewModel = personlViewModel?.items[indexPath.row]
|
||
cell.moreBlock = {
|
||
[weak self] in
|
||
guard let self = self, let itemView = (self.personlViewModel?.items[indexPath.row]) else {return}
|
||
MPPositive_Debouncer.shared.call {
|
||
MPPositive_ModalType = .MoreOperations
|
||
let moreVC = MPPositive_MoreSongOperationsViewController(itemView)
|
||
moreVC.disMissBlock = {
|
||
DispatchQueue.main.async {
|
||
collectionView.reloadData()
|
||
}
|
||
}
|
||
moreVC.transitioningDelegate = self
|
||
moreVC.modalPresentationStyle = .custom
|
||
self.parentController()?.present(moreVC, animated: true)
|
||
}
|
||
}
|
||
cell.deleteBlock = {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
//点击删除下载
|
||
let alertController = UIAlertController(title: "Delete This Song".localizableString(), message: "Are you sure you want to delete the offline resources of this song?".localizableString(), preferredStyle: .alert)
|
||
let cancel = UIAlertAction(title: "Cancel".localizableString(), style: .cancel)
|
||
alertController.addAction(cancel)
|
||
let sure = UIAlertAction(title: "Confirm".localizableString(), style: .destructive) {(action) in
|
||
guard let videoId = (self.personlViewModel?.items[indexPath.row].browseItem.videoId) else {return}
|
||
//确定删除
|
||
MP_DownloadManager.shared.deleteFileDocuments(videoId) { videoId in
|
||
MP_HUD.progress("Loading...".localizableString(), delay: 0.5) {
|
||
MP_HUD.text("Removed".localizableString(), delay: 1.0, completion: nil)
|
||
collectionView.reloadData()
|
||
}
|
||
}
|
||
}
|
||
alertController.addAction(sure)
|
||
self.parentController()?.present(alertController, animated: true)
|
||
}
|
||
cell.cancelBlock = {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
//点击取消下载
|
||
let alertController = UIAlertController(title: "Cancel Song Download Task".localizableString(), message: "Are you sure you want to cancel the download task of this song?".localizableString(), preferredStyle: .alert)
|
||
let cancel = UIAlertAction(title: "Cancel".localizableString(), style: .cancel)
|
||
alertController.addAction(cancel)
|
||
let sure = UIAlertAction(title: "Confirm".localizableString(), style: .destructive) {(action) in
|
||
guard let videoId = (self.personlViewModel?.items[indexPath.row].browseItem.videoId) else {return}
|
||
//确定取消
|
||
MP_DownloadManager.shared.cancelDownloadTask(videoId) { videoId in
|
||
MP_HUD.text("Cancel".localizableString(), delay: 1.0, completion: nil)
|
||
collectionView.reloadData()
|
||
}
|
||
}
|
||
alertController.addAction(sure)
|
||
self.parentController()?.present(alertController, animated: true)
|
||
}
|
||
return cell
|
||
case .Lists:
|
||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_HomeListThirdCollectionViewCellID, for: indexPath) as! MPPositive_HomeListThirdCollectionViewCell
|
||
cell.itemViewModel = personlViewModel?.items[indexPath.row]
|
||
return cell
|
||
default:
|
||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_HomeListFourthCollectionViewCellID, for: indexPath) as! MPPositive_HomeListFourthCollectionViewCell
|
||
cell.itemViewModel = personlViewModel?.items[indexPath.row]
|
||
return cell
|
||
}
|
||
}
|
||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||
guard let item = (self.personlViewModel?.items[indexPath.row]) else {
|
||
return
|
||
}
|
||
switch showType {
|
||
case.Singles:
|
||
//单曲/视频跳转
|
||
MPPositive_Debouncer.shared.call {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||
playOfflineSongs(item.browseItem.videoId ?? "")
|
||
return
|
||
}
|
||
MP_AnalyticsManager.shared.home_b_module_clickAction(item.browseItem.pageType ?? "")
|
||
MP_AnalyticsManager.shared.song_clickAction("Home")
|
||
//优先清除数据
|
||
MP_PlayerManager.shared.loadPlayer = nil
|
||
//弹出播放器
|
||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||
MP_AnalyticsManager.shared.player_b_impAction()
|
||
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||
MP_NetWorkManager.shared.requestNextList(item.browseItem.playListId ?? "", videoId: item.browseItem.videoId ?? "", clickTrackingParams: item.browseItem.clickTrackingParams){ [weak self] listSongs in
|
||
guard let self = self else {return}
|
||
//回掉的数据并不完善,生成一个playerloadViewModel
|
||
let lodaViewModel = MPPositive_PlayerLoadViewModel(listSongs, currentVideoId: item.browseItem.videoId ?? "")
|
||
lodaViewModel.improveData(item.browseItem.videoId ?? "")
|
||
//更改播放器播放类型
|
||
MP_PlayerManager.shared.setPlayType(.normal)
|
||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||
MP_AnalyticsManager.shared.player_b_listAction()
|
||
}
|
||
}
|
||
case .Lists:
|
||
|
||
//列表专辑
|
||
let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: "", title: item.title ?? "", subtitle: item.subtitle ?? "", clickTrackingParams: item.browseItem.clickTrackingParams ?? "")
|
||
self.parentController()?.navigationController?.pushViewController(listVC, animated: true)
|
||
case .Artists:
|
||
let artistVC = MPPositive_ArtistShowViewController(item.browseItem.artistId ?? "", clickTrackingParams: item.browseItem.clickTrackingParams ?? "")
|
||
self.parentController()?.navigationController?.pushViewController(artistVC, animated: true)
|
||
}
|
||
}
|
||
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
||
return MPPositive_PresentationController(presentedViewController: presented, presenting: presenting)
|
||
}
|
||
}
|