Music_Player3/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Center(个人曲库页)/MPPositive_LoveSongsViewController.swift
2024-09-06 18:21:15 +08:00

568 lines
25 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_LoveSongsViewController.swift
// MusicPlayer
//
// Created by Mr.Zhou on 2024/5/28.
//
import UIKit
class MPPositive_LoveSongsViewController: MPPositive_BaseViewController, UIViewControllerTransitioningDelegate {
///View
private lazy var headView:UIView = {
let headView:UIView = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: (227*width)+navAndstatusBarHeight))
headView.backgroundColor = .init(hex: "#151718")
headView.layer.masksToBounds = true
return headView
}()
///
private lazy var backImageView:UIImageView = {
let image:UIImageView = .init(image: placeholderImage)
image.contentMode = .scaleAspectFill
image.layer.masksToBounds = true
return image
}()
///
private lazy var backBlurView:UIVisualEffectView = {
//
let blurEffect = UIBlurEffect(style: .dark)
//
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.alpha = 0.6
blurEffectView.isUserInteractionEnabled = false
return blurEffectView
}()
///
private lazy var maskImageView:UIImageView = {
let imageView:UIImageView = .init(image: .init(named: "List_Cover'mask"))
imageView.contentMode = .scaleAspectFill
return imageView
}()
///
private lazy var coverImageView:UIImageView = {
let image:UIImageView = .init(image: placeholderImage)
image.contentMode = .scaleAspectFill
image.layer.masksToBounds = true
image.layer.cornerRadius = 8*width
return image
}()
///
private lazy var titleLabel:UILabel = createLabel("Name", font: .systemFont(ofSize: 18*width, weight: .regular), textColor: .white, textAlignment: .center, lines: 2)
///sectionView
private lazy var sectionShowView:UIView = {
let sectionView:UIView = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: 165*width))
sectionView.backgroundColor = .init(hex: "#151718")
return sectionView
}()
///
private lazy var playAllBtn:UIButton = {
let btn = UIButton()
btn.setImage(UIImage(named: "Center_PlayAll'logo"), for: .normal)
btn.setTitle(" Play all", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 14*width, weight: .regular)
btn.addTarget(self, action: #selector(playAllClick(_ :)), for: .touchUpInside)
return btn
}()
///
private lazy var shuffleBtn:UIButton = {
let btn = UIButton()
btn.setImage(UIImage(named: "List_ShufflePlay'logo"), for: .normal)
btn.setTitle(" Shuffle", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 14*width, weight: .regular)
btn.addTarget(self, action: #selector(shuffleClick(_ :)), for: .touchUpInside)
return btn
}()
///
private lazy var searchBtn:UIButton = {
let btn = UIButton()
btn.setBackgroundImage(UIImage(named: "Center_Search'logo"), for: .normal)
btn.addTarget(self, action: #selector(searchActionShowClick(_ :)), for: .touchUpInside)
return btn
}()
//View
private lazy var searchShowView:MPPositive_CenterListSearchView = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: 30*width))
///广View
fileprivate lazy var adContainerView:UIView = {
let adContainerView:UIView = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: 150))
adContainerView.backgroundColor = .clear
return adContainerView
}()
//广
private var isShowAdNatived:Bool = false
//
private lazy var rightBtn:UIButton = {
let btn:UIButton = .init(frame: .init(x: 0, y: 0, width: 24*width, height: 24*width))
btn.setBackgroundImage(UIImage(named: "Change Sort'logo"), for: .normal)
btn.addTarget(self, action: #selector(sortTypeClick(_ :)), for: .touchUpInside)
return btn
}()
///tableView
private lazy var tableView:UITableView = {
let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain)
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0
}
tableView.tableHeaderView = headView
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.contentInsetAdjustmentBehavior = .never
tableView.estimatedRowHeight = 200
tableView.rowHeight = UITableView.automaticDimension
tableView.bounces = false
tableView.dataSource = self
tableView.delegate = self
tableView.register(MPPositive_SearchResultShowTableViewCell.self, forCellReuseIdentifier: MPPositive_SearchResultShowTableViewCellID)
tableView.contentInset = .init(top: 0, left: 0, bottom: 70*width, right: 0)
return tableView
}()
private let MPPositive_SearchResultShowTableViewCellID = "MPPositive_SearchResultShowTableViewCell"
//
private var isSearchStyle:Bool = false
//
private var songs:[MPPositive_CollectionSongViewModel] = []
//
private var searchSongs:[MPPositive_CollectionSongViewModel] = []
//
private var showSongs:[MPPositive_CollectionSongViewModel] = []
//
private var sortType:Int{
get{
if let type = UserDefaults.standard.object(forKey: "Love_Songs_SortType") as? Int {
return type
}else {
return 0
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
setTitle("")
setPopBtn()
configure()
MP_AdMobManager.shared.layoutLibraryNativeAd(in: adContainerView, index: 1){
[weak self] in
self?.reloadNatived()
}
MP_AdMobManager.shared.onLibraryNativeAdBlock = {
[weak adContainerView] in
guard let adContainerView = adContainerView else {return}
MP_AdMobManager.shared.layoutLibraryNativeAd(in: adContainerView, index: 1){
self.reloadNatived()
}
}
searchShowView.cancelBlock = {
[weak self] in
guard let self = self else {return}
cancelSearchAction()
}
searchShowView.textBlock = {
[weak self] (text) in
guard let self = self else {return}
isSearchStyle = true
//
reloadSearch(text)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
reload()
}
//
private func reload() {
MPPositive_LoadCoreModel.shared.reloadCollectionSongViewModel {
[weak self] in
guard let self = self else {return}
songs = MPPositive_LoadCoreModel.shared.songViewModels
let coverURL = songs.first?.collectionSong.coverImage
backImageView.kf.setImage(with: coverURL, placeholder: placeholderImage)
coverImageView.kf.setImage(with: coverURL, placeholder: placeholderImage)
titleLabel.text = "Love Songs".localizableString()
playAllBtn.setTitle(" Play (\(songs.count))", for: .normal)
isSearchStyle ? reloadSearch(self.searchShowView.textField.text ?? ""):reloadShow()
}
}
//
private func reloadShow() {
switch sortType {
case 0://
showSongs = songs.sorted(by: { item1, item2 in
if let date1 = item1.collectionSong.addTime, let date2 = item2.collectionSong.addTime {
return date1 > date2
}else {
return false
}
})
default://
showSongs = songs.sorted(by: { item1, item2 in
if let date1 = item1.collectionSong.addTime, let date2 = item2.collectionSong.addTime {
return date1 < date2
}else {
return true
}
})
}
tableView.reloadData()
}
//
private func reloadSearch(_ text:String) {
if text.isEmpty {
//
searchSongs = songs
}else {
//
searchSongs = songs.filter({($0.title ?? "").contains(text) || ($0.subtitle ?? "").contains(text)})
}
tableView.reloadSections(.init(integer: 0), with: .automatic)
}
//广
@objc private func reloadNatived() {
isShowAdNatived = true
tableView.reloadData()
}
private func configure() {
navView.addSubview(rightBtn)
rightBtn.snp.makeConstraints { make in
make.width.height.equalTo(24*width)
make.centerY.equalToSuperview()
make.right.equalToSuperview().offset(-16*width)
}
//
headView.addSubview(backImageView)
backImageView.snp.makeConstraints { make in
make.left.top.right.equalToSuperview()
make.height.equalTo((227*width)+navAndstatusBarHeight)
}
//
headView.addSubview(backBlurView)
backBlurView.snp.makeConstraints { make in
make.left.top.right.equalToSuperview()
make.height.equalTo(backImageView)
}
//
headView.addSubview(maskImageView)
maskImageView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.height.equalTo(120*width)
make.bottom.equalTo(backImageView)
}
//
headView.addSubview(coverImageView)
coverImageView.snp.makeConstraints { make in
make.width.height.equalTo(120*width)
make.center.equalTo(backImageView)
}
//
headView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.width.lessThanOrEqualToSuperview().multipliedBy(0.7)
make.centerX.equalToSuperview()
make.top.equalTo(coverImageView.snp.bottom).offset(30*width)
}
//
sectionShowView.addSubview(playAllBtn)
playAllBtn.snp.makeConstraints { make in
make.left.equalToSuperview().offset(18*width)
make.top.equalToSuperview().offset(24*width)
}
//
sectionShowView.addSubview(shuffleBtn)
shuffleBtn.snp.makeConstraints { make in
make.left.equalTo(playAllBtn.snp.right).offset(18*width)
make.centerY.equalTo(playAllBtn)
}
//
sectionShowView.addSubview(searchBtn)
searchBtn.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-18*width)
make.width.height.equalTo(24*width)
make.centerY.equalTo(playAllBtn)
}
sectionShowView.addSubview(searchShowView)
searchShowView.snp.makeConstraints { make in
make.height.equalTo(45*width)
make.left.right.equalToSuperview()
make.centerY.equalTo(searchBtn)
}
searchShowView.alpha = 0
searchShowView.isHidden = true
searchShowView.isUserInteractionEnabled = false
//广View
sectionShowView.addSubview(adContainerView)
adContainerView.snp.makeConstraints { make in
make.top.equalTo(playAllBtn.snp.bottom).offset(20*width)
make.left.right.equalToSuperview()
make.height.equalTo(130*width)
}
//tableView
view.addSubview(tableView)
tableView.snp.makeConstraints { make in
make.top.left.right.bottom.equalToSuperview()
}
}
//
@objc private func sortTypeClick(_ sender:UIButton) {
view.endEditing(true)
//
cancelSearchAction()
MPPositive_ModalType = .SortType
let sortVC = MPPositive_SortTypeViewController(sortType)
sortVC.chooseBlock = {
[weak self] (type) in
guard let self = self else {return}
UserDefaults.standard.set(type, forKey: "Love_Songs_SortType")
reloadShow()
}
sortVC.transitioningDelegate = self
sortVC.modalPresentationStyle = .custom
present(sortVC, animated: true)
}
//
@objc private func searchActionShowClick(_ sender:UIButton) {
//
UIView.animate(withDuration: 0.2) {
[weak self] in
guard let self = self else {return}
searchShowView.isHidden = false
//searchView
searchShowView.alpha = 1
searchBtn.isUserInteractionEnabled = false
} completion: { [weak self] statu in
guard let self = self else {return}
searchShowView.isUserInteractionEnabled = true
}
}
//
private func cancelSearchAction() {
UIView.animate(withDuration: 0.2) {
[weak self] in
guard let self = self else {return}
searchShowView.isUserInteractionEnabled = false
searchShowView.alpha = 0
isSearchStyle = false
} completion: { [weak self] statu in
guard let self = self else {return}
searchShowView.isHidden = true
searchBtn.isUserInteractionEnabled = true
reloadShow()
}
}
//
@objc private func playAllClick(_ sender:UIButton) {
guard songs.count != 0 else {return}
MPPositive_Debouncer.shared.call {
[weak self] in
guard let self = self else {return}
// guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
// MP_HUD.text("Bad connection~".localizableString(), delay: 2.0, completion: nil)
// return
// }
MP_AnalyticsManager.shared.song_clickAction("Love Song")
//
MP_PlayerManager.shared.loadPlayer = nil
//
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
MP_AnalyticsManager.shared.player_b_impAction()
//
var array:[MPPositive_SongItemModel] = []
for (index,song) in songs.enumerated() {
let item = MPPositive_SongItemModel()
//item
item.index = index
item.reviewUrls = [song.coverURL.absoluteString]
item.title = song.title
item.shortBylineText = song.subtitle
item.videoId = song.collectionSong.videoId
item.lyricsID = song.collectionSong.lyricsID
item.relatedID = song.collectionSong.relatedID
array.append(item)
}
guard let currentVideo = songs.first else {
return
}
let lodaViewModel = MPPositive_PlayerLoadViewModel(array, currentVideoId: currentVideo.collectionSong.videoId ?? "")
lodaViewModel.improveData(currentVideo.collectionSong.videoId ?? "")
//
MP_PlayerManager.shared.setPlayType(.normal)
MP_PlayerManager.shared.loadPlayer = lodaViewModel
MP_AnalyticsManager.shared.player_b_listAction()
}
}
//
@objc private func shuffleClick(_ sender:UIButton) {
guard songs.count != 0 else {return}
MPPositive_Debouncer.shared.call {
[weak self] in
guard let self = self else {return}
// guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
// MP_HUD.text("Bad connection~".localizableString(), delay: 2.0, completion: nil)
// return
// }
MP_AnalyticsManager.shared.song_clickAction("Love Song")
//
MP_PlayerManager.shared.loadPlayer = nil
//
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
MP_AnalyticsManager.shared.player_b_impAction()
//
var array:[MPPositive_SongItemModel] = []
for (index,song) in songs.enumerated() {
let item = MPPositive_SongItemModel()
//item
item.index = index
item.reviewUrls = [song.coverURL.absoluteString]
item.title = song.title
item.shortBylineText = song.subtitle
item.videoId = song.collectionSong.videoId
item.lyricsID = song.collectionSong.lyricsID
item.relatedID = song.collectionSong.relatedID
array.append(item)
}
//
guard let currentVideo = songs.randomElement() else {
return
}
let lodaViewModel = MPPositive_PlayerLoadViewModel(array, currentVideoId: currentVideo.collectionSong.videoId ?? "")
lodaViewModel.improveData(currentVideo.collectionSong.videoId ?? "")
//
MP_PlayerManager.shared.setPlayType(.random)
MP_PlayerManager.shared.loadPlayer = lodaViewModel
MP_AnalyticsManager.shared.player_b_listAction()
}
}
}
//MARK: - tableView
extension MPPositive_LoveSongsViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return isSearchStyle ? searchSongs.count:showSongs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_SearchResultShowTableViewCellID, for: indexPath) as! MPPositive_SearchResultShowTableViewCell
if isSearchStyle {
cell.songViewModel = searchSongs[indexPath.row]
}else {
cell.songViewModel = showSongs[indexPath.row]
}
cell.moreBlock = {
[weak self] in
guard let self = self else {return}
MPPositive_Debouncer.shared.call {
MPPositive_ModalType = .MoreOperations
let item = self.isSearchStyle ? self.searchSongs[indexPath.row]:self.showSongs[indexPath.row]
let moreVC = MPPositive_MoreSongOperationsViewController(item)
moreVC.disMissBlock = {
self.reload()
}
moreVC.transitioningDelegate = self
moreVC.modalPresentationStyle = .custom
self.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.isSearchStyle ? self.searchSongs[indexPath.row].collectionSong.videoId:self.showSongs[indexPath.row].collectionSong.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()
}
}
}
alertController.addAction(sure)
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.isSearchStyle ? self.searchSongs[indexPath.row].collectionSong.videoId:self.showSongs[indexPath.row].collectionSong.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)
}
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return sectionShowView
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return isShowAdNatived ? 185*width:75*width
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
MPPositive_Debouncer.shared.call {
[weak self] in
guard let self = self else {return}
// guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
// MP_HUD.text("Bad connection~".localizableString(), delay: 2.0, completion: nil)
// return
// }
MP_AnalyticsManager.shared.song_clickAction("Love Song")
//
MP_PlayerManager.shared.loadPlayer = nil
//
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
MP_AnalyticsManager.shared.player_b_impAction()
//
var array:[MPPositive_SongItemModel] = []
for (index,song) in MPPositive_LoadCoreModel.shared.songViewModels.enumerated() {
let item = MPPositive_SongItemModel()
//item
item.index = index
item.reviewUrls = [song.coverURL.absoluteString]
item.title = song.title
item.shortBylineText = song.subtitle
item.videoId = song.collectionSong.videoId
item.lyricsID = song.collectionSong.lyricsID
item.relatedID = song.collectionSong.relatedID
array.append(item)
}
let currentVideo = isSearchStyle ? searchSongs[indexPath.row]:showSongs[indexPath.row]
let lodaViewModel = MPPositive_PlayerLoadViewModel(array, currentVideoId: currentVideo.collectionSong.videoId ?? "")
lodaViewModel.improveData(currentVideo.collectionSong.videoId ?? "")
//
MP_PlayerManager.shared.setPlayType(.normal)
MP_PlayerManager.shared.loadPlayer = lodaViewModel
MP_AnalyticsManager.shared.player_b_listAction()
}
}
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return MPPositive_PresentationController(presentedViewController: presented, presenting: presenting)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let yOffset = scrollView.contentOffset.y
//toppading
if yOffset >= ((153*width)+navAndstatusBarHeight) {
if tableView.contentInset.top == 0 {
tableView.contentInset = .init(top: navAndstatusBarHeight, left: 0, bottom: 70*width, right: 0)
topSafeAndNavView.backgroundColor = .init(hex: "#151718")
}
}else {
if tableView.contentInset.top == navAndstatusBarHeight {
tableView.contentInset = .init(top: 0, left: 0, bottom: 70*width, right: 0)
topSafeAndNavView.backgroundColor = .clear
}
}
}
}