Music_Player3/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Base(基类,导航栏,标签栏)/MPPositive_MoreSongOperationsViewController.swift

482 lines
22 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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
self?.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
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)
}
}