488 lines
23 KiB
Swift
488 lines
23 KiB
Swift
//
|
||
// MPPositive_MoreOperationsViewController.swift
|
||
// MusicPlayer
|
||
//
|
||
// Created by Mr.Zhou on 2024/5/29.
|
||
//
|
||
|
||
import UIKit
|
||
import Kingfisher
|
||
///更多操作
|
||
class MPPositive_MoreSongOperationsViewController: UIViewController, UIViewControllerTransitioningDelegate {
|
||
//小角标图片
|
||
private lazy var indictorImageView:UIImageView = .init(image: .init(named: "Player_Indictor'logo"))
|
||
//展示ICON
|
||
private lazy var iconImageView:UIImageView = {
|
||
let imageView:UIImageView = .init()
|
||
imageView.contentMode = .scaleAspectFill
|
||
imageView.layer.masksToBounds = true
|
||
imageView.layer.cornerRadius = 10*width
|
||
return imageView
|
||
}()
|
||
//标题Label
|
||
private lazy var titleLabel:UILabel = createLabel("Title", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
||
//副标题
|
||
private lazy var subtitleLabel:UILabel = createLabel("Title", font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .init(hex: "#666666"), textAlignment: .left)
|
||
//是否收藏
|
||
private lazy var collectionBtn:UIButton = {
|
||
let btn = UIButton()
|
||
btn.setImage(UIImage(named: "Artist_Collection'logo"), for: .normal)
|
||
btn.setImage(UIImage(named: "Artist_Collectioned'logo"), for: .selected)
|
||
btn.setBackgroundImage(UIImage(named: "Artist_Collection'bg"), for: .normal)
|
||
btn.setBackgroundImage(UIImage(named: "Artist_Collectioned'bg"), for: .selected)
|
||
btn.addTarget(self, action: #selector(collectionClick(_ :)), for: .touchUpInside)
|
||
return btn
|
||
}()
|
||
//分割线
|
||
private lazy var lineView:UIView = {
|
||
let lineView:UIView = UIView()
|
||
lineView.backgroundColor = .init(hex: "#444444")
|
||
return lineView
|
||
}()
|
||
//展示tableView
|
||
private lazy var tableView:UITableView = {
|
||
let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain)
|
||
tableView.backgroundColor = .clear
|
||
tableView.separatorStyle = .none
|
||
tableView.estimatedRowHeight = 200
|
||
tableView.rowHeight = UITableView.automaticDimension
|
||
tableView.dataSource = self
|
||
tableView.delegate = self
|
||
tableView.register(MPPositive_MoreOperationDownLoadTableViewCell.self, forCellReuseIdentifier: MPPositive_MoreOperationDownLoadTableViewCellID)
|
||
tableView.register(MPPositive_MoreOperationShowTableViewCell.self, forCellReuseIdentifier: MPPositive_MoreOperationShowTableViewCellID)
|
||
return tableView
|
||
}()
|
||
private let MPPositive_MoreOperationDownLoadTableViewCellID = "MPPositive_MoreOperationDownLoadTableViewCell"
|
||
private let MPPositive_MoreOperationShowTableViewCellID = "MPPositive_MoreOperationShowTableViewCell"
|
||
private var song:MPPositive_SongItemModel!{
|
||
didSet{
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
// MP_HUD.hideNow()
|
||
view.isUserInteractionEnabled = true
|
||
iconImageView.kf.setImage(with: URL(string: song.reviewUrls?.last ?? ""), placeholder: placeholderImage)
|
||
titleLabel.text = song.title
|
||
subtitleLabel.text = song.shortBylineText
|
||
//判断该单曲是否收藏
|
||
MPPositive_CollectionSongModel.fetch(predicate: .init(format: "videoId == %@", (song.videoId ?? ""))) { [weak self] results in
|
||
guard let self = self else {return}
|
||
collectionBtn.isSelected = results.count != 0
|
||
}
|
||
tableView.reloadData()
|
||
}
|
||
}
|
||
}
|
||
private var playList:MPPositive_CustomPlayListModel?
|
||
var removeBlock:(() -> Void)?
|
||
var disMissBlock:(() -> Void)?
|
||
var collectionBlock:(() -> Void)?
|
||
init(_ song:MPPositive_SongItemModel) {
|
||
super.init(nibName: nil, bundle: nil)
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
self?.song = song
|
||
}
|
||
}
|
||
//通过browseViewModel加载更多框
|
||
init(_ browseViewModel:MPPositive_BrowseItemViewModel) {
|
||
super.init(nibName: nil, bundle: nil)
|
||
view.isUserInteractionEnabled = false
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
// MP_HUD.loading()
|
||
//发起网络请求补全数据
|
||
MP_NetWorkManager.shared.requestNextList("", videoId: browseViewModel.browseItem.videoId ?? "", clickTrackingParams: browseViewModel.browseItem.clickTrackingParams) { [weak self] listSongs in
|
||
guard let first = listSongs.first else {return}
|
||
let group = DispatchGroup()
|
||
group.enter()
|
||
improveDataforLycirsAndRelated(first) {[weak self] (result) in
|
||
first.lyricsID = result.0
|
||
first.relatedID = result.1
|
||
group.leave()
|
||
}
|
||
group.enter()
|
||
//补全资源路径组和封面路径组
|
||
improveDataforResouceAndCover(first) {[weak self] resourceUrls, coverUrls in
|
||
if let resourceUrls = resourceUrls {
|
||
first.resourceUrls = resourceUrls.0
|
||
first.itags = resourceUrls.1
|
||
first.mimeTypes = resourceUrls.2
|
||
}
|
||
first.coverUrls = coverUrls
|
||
group.leave()
|
||
} failure: {_ in
|
||
group.leave()
|
||
}
|
||
group.notify(queue: .main, execute: {
|
||
[weak self] in
|
||
//补全了数据
|
||
guard let self = self else {return}
|
||
song = first
|
||
})
|
||
}
|
||
}
|
||
}
|
||
//通过SearchResultItemViewModel加载更多框
|
||
init(_ searchResultItemViewModel:MPPositive_SearchResultItemViewModel) {
|
||
super.init(nibName: nil, bundle: nil)
|
||
view.isUserInteractionEnabled = false
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
// MP_HUD.loading()
|
||
//发起网络请求补全数据
|
||
MP_NetWorkManager.shared.requestNextList("", videoId: searchResultItemViewModel.item.videoId ?? "", clickTrackingParams: searchResultItemViewModel.item.clickTrackingParams) { [weak self] listSongs in
|
||
guard let first = listSongs.first else {return}
|
||
let group = DispatchGroup()
|
||
group.enter()
|
||
improveDataforLycirsAndRelated(first) {[weak self] (result) in
|
||
first.lyricsID = result.0
|
||
first.relatedID = result.1
|
||
group.leave()
|
||
}
|
||
group.enter()
|
||
//补全资源路径组和封面路径组
|
||
improveDataforResouceAndCover(first) {[weak self] resourceUrls, coverUrls in
|
||
if let resourceUrls = resourceUrls {
|
||
first.resourceUrls = resourceUrls.0
|
||
first.itags = resourceUrls.1
|
||
first.mimeTypes = resourceUrls.2
|
||
}
|
||
first.coverUrls = coverUrls
|
||
group.leave()
|
||
} failure: {_ in
|
||
group.leave()
|
||
}
|
||
group.notify(queue: .main, execute: {
|
||
[weak self] in
|
||
//补全了数据
|
||
guard let self = self else {return}
|
||
song = first
|
||
})
|
||
}
|
||
}
|
||
}
|
||
//通过collectionSongViewModel加载更多框
|
||
init(_ collectionSongViewModel:MPPositive_CollectionSongViewModel) {
|
||
super.init(nibName: nil, bundle: nil)
|
||
view.isUserInteractionEnabled = false
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
// MP_HUD.loading()
|
||
//发起网络请求补全数据
|
||
MP_NetWorkManager.shared.requestNextList("", videoId: collectionSongViewModel.collectionSong.videoId ?? "", clickTrackingParams: nil){ [weak self] listSongs in
|
||
guard let first = listSongs.first else {return}
|
||
let group = DispatchGroup()
|
||
group.enter()
|
||
improveDataforLycirsAndRelated(first) {[weak self] (result) in
|
||
first.lyricsID = result.0
|
||
first.relatedID = result.1
|
||
group.leave()
|
||
}
|
||
group.enter()
|
||
//补全资源路径组和封面路径组
|
||
improveDataforResouceAndCover(first) {[weak self] resourceUrls, coverUrls in
|
||
if let resourceUrls = resourceUrls {
|
||
first.resourceUrls = resourceUrls.0
|
||
first.itags = resourceUrls.1
|
||
first.mimeTypes = resourceUrls.2
|
||
}
|
||
first.coverUrls = coverUrls
|
||
group.leave()
|
||
} failure: {_ in
|
||
group.leave()
|
||
}
|
||
group.notify(queue: .main, execute: {
|
||
[weak self] in
|
||
//补全了数据
|
||
guard let self = self else {return}
|
||
song = first
|
||
})
|
||
}
|
||
}
|
||
}
|
||
//从自定义歌单弹出
|
||
init(_ playList:MPPositive_CustomPlayListModel, video:MPPositive_CustomVideoModel?) {
|
||
super.init(nibName: nil, bundle: nil)
|
||
view.isUserInteractionEnabled = false
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
self.playList = playList
|
||
// MP_HUD.loading()
|
||
//发起网络请求补全数据
|
||
MP_NetWorkManager.shared.requestNextList("", videoId: video?.videoId ?? "", clickTrackingParams: nil){ [weak self] listSongs in
|
||
guard let first = listSongs.first else {return}
|
||
let group = DispatchGroup()
|
||
group.enter()
|
||
improveDataforLycirsAndRelated(first) {[weak self] (result) in
|
||
first.lyricsID = result.0
|
||
first.relatedID = result.1
|
||
group.leave()
|
||
}
|
||
group.enter()
|
||
//补全资源路径组和封面路径组
|
||
improveDataforResouceAndCover(first) {[weak self] resourceUrls, coverUrls in
|
||
if let resourceUrls = resourceUrls {
|
||
first.resourceUrls = resourceUrls.0
|
||
first.itags = resourceUrls.1
|
||
first.mimeTypes = resourceUrls.2
|
||
}
|
||
first.coverUrls = coverUrls
|
||
group.leave()
|
||
} failure: {_ in
|
||
group.leave()
|
||
}
|
||
group.notify(queue: .main, execute: {
|
||
[weak self] in
|
||
//补全了数据
|
||
guard let self = self else {return}
|
||
song = first
|
||
})
|
||
}
|
||
}
|
||
}
|
||
required init?(coder: NSCoder) {
|
||
super.init(coder: coder)
|
||
}
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
view.backgroundColor = .init(hex: "#282A2C")
|
||
view.layer.masksToBounds = true
|
||
view.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
|
||
view.layer.cornerRadius = 18*width
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||
if MP_NetWorkManager.shared.netWorkStatu != .reachable {
|
||
MP_HUD.onlytext("Bad connection~", delay: 1.0, completion: nil)
|
||
}
|
||
}
|
||
configure()
|
||
}
|
||
override func viewWillAppear(_ animated: Bool) {
|
||
super.viewWillAppear(animated)
|
||
}
|
||
override func viewWillDisappear(_ animated: Bool) {
|
||
super.viewWillDisappear(animated)
|
||
if disMissBlock != nil {
|
||
disMissBlock!()
|
||
}
|
||
}
|
||
private func configure() {
|
||
view.addSubview(indictorImageView)
|
||
indictorImageView.snp.makeConstraints { make in
|
||
make.centerX.equalToSuperview()
|
||
make.width.equalTo(29*width)
|
||
make.height.equalTo(4*width)
|
||
make.top.equalToSuperview().offset(8*width)
|
||
}
|
||
view.addSubview(iconImageView)
|
||
iconImageView.snp.makeConstraints { make in
|
||
make.width.height.equalTo(50*width)
|
||
make.left.equalToSuperview().offset(18*width)
|
||
make.top.equalToSuperview().offset(32*width)
|
||
}
|
||
view.addSubview(collectionBtn)
|
||
collectionBtn.snp.makeConstraints { make in
|
||
make.width.height.equalTo(32*width)
|
||
make.centerY.equalTo(iconImageView)
|
||
make.right.equalToSuperview().offset(-18*width)
|
||
}
|
||
view.addSubview(titleLabel)
|
||
titleLabel.snp.makeConstraints { make in
|
||
make.top.equalTo(iconImageView).offset(8*width)
|
||
make.left.equalTo(iconImageView.snp.right).offset(12*width)
|
||
make.right.equalTo(collectionBtn.snp.left).offset(-12*width)
|
||
}
|
||
view.addSubview(subtitleLabel)
|
||
subtitleLabel.snp.makeConstraints { make in
|
||
make.left.right.equalTo(titleLabel)
|
||
make.bottom.equalTo(iconImageView).offset(-8*width)
|
||
}
|
||
view.addSubview(lineView)
|
||
lineView.snp.makeConstraints { make in
|
||
make.width.equalTo(339*width)
|
||
make.height.equalTo(1*width)
|
||
make.centerX.equalToSuperview()
|
||
make.top.equalTo(iconImageView.snp.bottom).offset(15*width)
|
||
}
|
||
view.addSubview(tableView)
|
||
tableView.snp.makeConstraints { make in
|
||
make.top.equalTo(lineView.snp.bottom).offset(8*width)
|
||
make.left.right.bottom.equalToSuperview()
|
||
}
|
||
}
|
||
//是否收藏
|
||
@objc private func collectionClick(_ sender:UIButton) {
|
||
if self.collectionBtn.isSelected == true{
|
||
self.collectionBtn.isSelected = false
|
||
MPPositive_CollectionSongModel.fetch(predicate: .init(format: "videoId == %@", (song.videoId ?? ""))) { [weak self] result in
|
||
guard let self = self else {return}
|
||
result.forEach { item in
|
||
if item.videoId == self.song.videoId {
|
||
MPPositive_CollectionSongModel.delete(item)
|
||
}
|
||
}
|
||
MPPositive_LoadCoreModel.shared.reloadCollectionSongViewModel(nil)
|
||
}
|
||
MP_AnalyticsManager.shared.player_b_unlove_clickAction(song.videoId ?? "", videoname: song.title ?? "", artistname: song.shortBylineText ?? "")
|
||
}else{
|
||
self.collectionBtn.isSelected = true
|
||
let item = try? MPPositive_CollectionSongModel.create()
|
||
item?.coverImage = URL(string: song.reviewUrls?.last ?? "")
|
||
item?.title = song.title
|
||
item?.subtitle = song.shortBylineText
|
||
item?.videoId = song.videoId
|
||
item?.lyricsID = song.lyricsID
|
||
item?.relatedID = song.relatedID
|
||
item?.addTime = Date()
|
||
MPPositive_CollectionSongModel.save()
|
||
MPPositive_LoadCoreModel.shared.reloadCollectionSongViewModel(nil)
|
||
MP_AnalyticsManager.shared.player_b_love_clickAction(song.videoId ?? "", videoname: song.title ?? "", artistname: song.shortBylineText ?? "")
|
||
}
|
||
if MP_PlayerManager.shared.loadPlayer?.currentVideo != nil {
|
||
MP_PlayerManager.shared.loadPlayer?.currentVideo?.reloadCollectionAndDownLoad()
|
||
}
|
||
if collectionBlock != nil {
|
||
collectionBlock!()
|
||
}
|
||
}
|
||
}
|
||
//MARK: - tableView
|
||
extension MPPositive_MoreSongOperationsViewController:UITableViewDataSource, UITableViewDelegate {
|
||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||
return 4
|
||
}
|
||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||
switch indexPath.row {
|
||
case 0:
|
||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_MoreOperationDownLoadTableViewCellID, for: indexPath) as! MPPositive_MoreOperationDownLoadTableViewCell
|
||
if let song = song {
|
||
cell.song = song
|
||
}
|
||
return cell
|
||
default:
|
||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_MoreOperationShowTableViewCellID, for: indexPath) as! MPPositive_MoreOperationShowTableViewCell
|
||
switch indexPath.row {
|
||
case 1://添加歌单/移除歌单
|
||
cell.title = playList != nil ? "Remove from playlist":"Add to playlist"
|
||
case 2:
|
||
cell.title = "Play next"
|
||
default://举报
|
||
cell.title = "Report"
|
||
}
|
||
return cell
|
||
}
|
||
}
|
||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||
switch indexPath.row {
|
||
case 0:
|
||
let cell = tableView.cellForRow(at: indexPath) as? MPPositive_MoreOperationDownLoadTableViewCell
|
||
switch cell?.loadBtn.state {
|
||
case .startDownload://开始状态,点击后进入下载状态
|
||
//检索当前网络状态
|
||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||
MP_HUD.text("Bad connection~".localizableString(), delay: 2.0, completion: nil)
|
||
return
|
||
}
|
||
//检索当前歌曲是否下载过
|
||
guard let song = song else {
|
||
return
|
||
}
|
||
//切换为准备状态
|
||
cell?.loadBtn.state = .pending
|
||
//事件打点
|
||
MP_AnalyticsManager.shared.player_b_download_clickAction(song.videoId ?? "", videoname: song.title ?? "", artistname: song.shortBylineText ?? "")
|
||
//补全了数据,执行下载
|
||
MP_DownloadManager.shared.prepareVideoDownloadTask(from: song)
|
||
case .downloaded://已下载,点击删除下载
|
||
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) {[weak self](action) in
|
||
guard let videoId = self?.song?.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)
|
||
tableView.reloadData()
|
||
self?.dismiss(animated: true)
|
||
}
|
||
}
|
||
}
|
||
alertController.addAction(sure)
|
||
present(alertController, animated: true)
|
||
default://取消下载
|
||
//点击取消下载
|
||
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) {[weak self](action) in
|
||
guard let videoId = self?.song?.videoId else {return}
|
||
//确定取消
|
||
MP_DownloadManager.shared.cancelDownloadTask(videoId) { videoId in
|
||
MP_HUD.text("Cancel".localizableString(), delay: 1.0, completion: nil)
|
||
tableView.reloadData()
|
||
}
|
||
}
|
||
alertController.addAction(sure)
|
||
present(alertController, animated: true)
|
||
}
|
||
if MP_PlayerManager.shared.loadPlayer?.currentVideo != nil {
|
||
MP_PlayerManager.shared.loadPlayer?.currentVideo?.reloadCollectionAndDownLoad()
|
||
}
|
||
case 1://添加歌单/移除歌单
|
||
if playList != nil {
|
||
//当前有歌单
|
||
//从歌单中移除
|
||
let array = playList?.videosArray.filter({$0.videoId != song.videoId})
|
||
playList?.addToRelationshipToCustomVideos(array ?? [])
|
||
MPPositive_CustomPlayListModel.save()
|
||
//重新设置
|
||
MPPositive_LoadCoreModel.shared.reloadCustomPlayLists(nil)
|
||
dismiss(animated: true) {
|
||
[weak self] in
|
||
MP_HUD.onlytext("Success".localizableString(), delay: 1.0, completion: nil)
|
||
}
|
||
}else {
|
||
//选择歌单
|
||
MPPositive_ModalType = .MoreOperations
|
||
let chooseVC = MPPositive_ChoosePlayListViewController(song)
|
||
chooseVC.disMissBlock = {
|
||
[weak self] in
|
||
self?.dismiss(animated: true)
|
||
}
|
||
chooseVC.transitioningDelegate = self
|
||
chooseVC.modalPresentationStyle = .custom
|
||
present(chooseVC, animated: true)
|
||
}
|
||
case 2://下一首播放
|
||
//检索播放列表,如果不存在播放列表,则禁止下一首播放
|
||
guard let load = MP_PlayerManager.shared.loadPlayer else {
|
||
//不存在播放列表,禁止下一首播放
|
||
MP_HUD.onlytext("There is no playlist currently playing".localizableString(), delay: 1.0, completion: nil)
|
||
return
|
||
}
|
||
//存在播放列表,判断当前歌曲是否存在于播放列表
|
||
guard load.songVideos?.contains(where: {$0.videoId == song.videoId}) == false else {
|
||
//存在于播放列表中,不可再度添加
|
||
MP_HUD.onlytext("The current playlist already exists".localizableString(), delay: 1.0, completion: nil)
|
||
return
|
||
}
|
||
if let s = song {
|
||
MP_PlayerManager.shared.loadPlayer?.playNextAction(s)
|
||
}
|
||
default://举报
|
||
MP_HUD.onlytext("Your report has been submitted and we will process it as soon as possible.".localizableString(), delay: 1.0, completion: nil)
|
||
}
|
||
|
||
}
|
||
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
||
return MPPositive_PresentationController(presentedViewController: presented, presenting: presenting)
|
||
}
|
||
|
||
}
|