// // MPPositive_SearchResultShowTableViewCell.swift // MusicPlayer // // Created by Mr.Zhou on 2024/5/13. // import UIKit import Kingfisher import DownloadButton class MPPositive_SearchResultShowTableViewCell: UITableViewCell, PKDownloadButtonDelegate { //特殊图片(展示预览图片) private lazy var iconImageView:UIImageView = { let imageView:UIImageView = .init() imageView.contentMode = .scaleAspectFill imageView.layer.masksToBounds = true imageView.layer.cornerRadius = 10*width return imageView }() private lazy var maskImageView:MP_WaveAnimationMaskView = .init(frame: .init(x: 0, y: 0, width: 24*width, height: 24*width), cornerRadius: 10*width) private lazy var titleLabel:UILabel = createLabel(font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left) private lazy var subtitleLabel:UILabel = createLabel(font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .init(hex: "#FFFFFF", alpha: 0.6), textAlignment: .left) ///更多按钮 private lazy var moreBtn:UIButton = { let btn:UIButton = .init() btn.setBackgroundImage(UIImage(named: "Song_More'logo"), for: .normal) btn.addTarget(self, action: #selector(moreActionClick(_ :)), for: .touchUpInside) return btn }() //设置下载按钮 private lazy var loadBtn:MP_DownloadButton = { let btn:MP_DownloadButton = .init() //开始下载状态 btn.startDownloadButton.cleanDefaultAppearance() btn.startDownloadButton.setBackgroundImage(UIImage(named: "Song_Unload'logo"), for: .normal) //下载结束状态 btn.downloadedButton.setBackgroundImage(UIImage(named: "Song_Loaded'logo"), for: .normal) btn.downloadedButton.setAttributedTitle(nil, for: .normal) //停止下载状态 btn.stopDownloadButton.stopButton.setImage(UIImage(named: "download"), for: .normal) btn.stopDownloadButton.tintColor = UIColor(hex: "#80F988") btn.stopDownloadButton.stopButtonWidth = 2 btn.stopDownloadButton.filledLineWidth = 3*width btn.stopDownloadButton.filledLineStyleOuter = true //加载状态设置 btn.pendingView.tintColor = UIColor(hex: "#80F988") btn.pendingView.radius = 12*width btn.pendingView.emptyLineRadians = 2*width btn.pendingView.spinTime = 3 btn.delegate = self return btn }() var itemView:MPPositive_SearchResultItemViewModel!{ didSet{ itemView.setImage(iconImageView) titleLabel.text = itemView.title subtitleLabel.text = itemView.subtitle //检索类型 if itemView.item.itemType == .single { moreBtn.isHidden = false loadBtn.isHidden = false }else { moreBtn.isHidden = true loadBtn.isHidden = true } setProgress(itemView.item.videoId ?? "") } } var songViewModel:MPPositive_CollectionSongViewModel!{ didSet{ songViewModel.setImage(iconImageView) titleLabel.text = songViewModel.title subtitleLabel.text = songViewModel.subtitle setProgress(songViewModel.collectionSong.videoId ?? "") if (songViewModel?.collectionSong.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) { titleLabel.textColor = greenTextColor maskImageView.isHidden = false maskImageView.startAnimation() }else { titleLabel.textColor = .white maskImageView.isHidden = true maskImageView.stopAnimation() } } } var loadViewModel:MPPositive_DownloadViewModel!{ didSet{ loadViewModel.setImage(iconImageView) titleLabel.text = loadViewModel.title subtitleLabel.text = loadViewModel.subtitle setProgress(loadViewModel.loadItem.videoId ?? "") if (loadViewModel?.loadItem.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) { titleLabel.textColor = greenTextColor maskImageView.isHidden = false maskImageView.startAnimation() }else { titleLabel.textColor = .white maskImageView.isHidden = true maskImageView.stopAnimation() } } } var videoModel:MPPositive_CustomVideoModel!{ didSet{ iconImageView.kf.setImage(with: videoModel.coverImageURL, placeholder: placeholderImage) titleLabel.text = videoModel.title subtitleLabel.text = videoModel.subtitle setProgress(videoModel.videoId ?? "") if (videoModel?.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) { titleLabel.textColor = greenTextColor maskImageView.isHidden = false maskImageView.startAnimation() }else { titleLabel.textColor = .white maskImageView.isHidden = true maskImageView.stopAnimation() } } } var moreBlock:(() -> Void)? //删除 var deleteBlock:(() -> Void)? //取消 var cancelBlock:(() -> Void)? override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) selectionStyle = .none backgroundColor = .clear //注册通知 NotificationCenter.notificationKey.add(observer: self, selector: #selector(downloadProgressAction(_ :)), notificationName: .download_progress_source) NotificationCenter.notificationKey.add(observer: self, selector: #selector(downloadEndAction(_ :)), notificationName: .dowload_end_source) configure() } deinit { NotificationCenter.default.removeObserver(self) } //根据输入videoId检索是否下载 func setProgress(_ videoId:String) { guard videoId.isEmpty == false, (videoId == itemView?.item?.videoId || videoId == songViewModel?.collectionSong.videoId || videoId == loadViewModel?.loadItem.videoId || videoId == videoModel?.videoId) else { DispatchQueue.main.async { [weak self] in guard let self = self else {return} //未加入下载队列 self.loadBtn.state = .startDownload } return } MP_DownloadManager.shared.loadQueue.async { [weak self] in guard let self = self else {return} //判断是否下载完成 MP_DownloadManager.shared.isDownloadedFileDocuments(videoId) {[weak self] statu in guard let self = self else {return} if statu == false { //未下载,判断是否加入了下载队列 if MP_DownloadManager.shared.isTasksQueue(for: videoId) { //加入下载队列,确定是否活跃下中 MP_DownloadManager.shared.isActiveTask(for: videoId){ [weak self] status in guard let self = self else {return} if status { DispatchQueue.main.async { [weak self] in guard let self = self else {return} self.loadBtn.state = .downloading } //活跃中,获取下载值 MP_DownloadManager.shared.getProgress(for: videoId) { [weak self] value in if let progress = value { //下载中 DispatchQueue.main.async { [weak self] in guard let self = self else {return} self.loadBtn.stopDownloadButton.progress = progress } } } }else { //处于队列中,还未开始下载 DispatchQueue.main.async { [weak self] in guard let self = self else {return} //未加入下载队列 self.loadBtn.state = .pending } } } }else { DispatchQueue.main.async { [weak self] in guard let self = self else {return} //未加入下载队列 self.loadBtn.state = .startDownload } } }else { DispatchQueue.main.async { [weak self] in guard let self = self else {return} //已经完成下载 self.loadBtn.state = .downloaded } } } } } //收到progress加载 @objc private func downloadProgressAction(_ sender:Notification) { if let dict = sender.object as? [String:String], let videoId = dict["videoId"], (videoId == itemView?.item?.videoId || videoId == songViewModel?.collectionSong.videoId || videoId == loadViewModel?.loadItem.videoId || videoId == videoModel?.videoId){ //比较当前videoId setProgress(videoId) } } //收到下载结束 @objc private func downloadEndAction(_ sender:Notification) { if let dict = sender.object as? [String:String], let videoId = dict["videoId"], (videoId == itemView?.item?.videoId || videoId == songViewModel?.collectionSong.videoId || videoId == loadViewModel?.loadItem.videoId || videoId == videoModel?.videoId){ setProgress(videoId) } } required init?(coder: NSCoder) { super.init(coder: coder) } override func awakeFromNib() { super.awakeFromNib() // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } private func configure() { contentView.addSubview(iconImageView) iconImageView.snp.makeConstraints { make in make.width.height.equalTo(60*width) make.top.equalToSuperview().offset(8*width).priority(999) make.bottom.equalToSuperview().offset(-8*width) make.left.equalToSuperview().offset(18*width) } contentView.addSubview(maskImageView) maskImageView.snp.makeConstraints { make in make.width.height.equalTo(iconImageView) make.center.equalTo(iconImageView) } maskImageView.configure() maskImageView.isHidden = true maskImageView.stopAnimation() contentView.addSubview(moreBtn) moreBtn.snp.makeConstraints { make in make.width.height.equalTo(24*width) make.centerY.equalTo(iconImageView.snp.centerY) make.right.equalToSuperview().offset(-18*width) } contentView.addSubview(loadBtn) loadBtn.snp.makeConstraints { make in make.width.height.equalTo(24*width) make.centerY.equalTo(iconImageView.snp.centerY) make.right.equalToSuperview().offset(-54*width) } contentView.addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.top.equalTo(iconImageView.snp.top).offset(10*width) make.left.equalTo(iconImageView.snp.right).offset(12*width) make.right.equalTo(loadBtn.snp.left).offset(-10*width) } contentView.addSubview(subtitleLabel) subtitleLabel.snp.makeConstraints { make in make.bottom.equalTo(iconImageView.snp.bottom).offset(-10*width) make.left.equalTo(titleLabel.snp.left) make.right.equalTo(titleLabel.snp.right) } } //点击更多 @objc private func moreActionClick(_ sender:UIButton) { // guard MP_NetWorkManager.shared.netWorkStatu == .reachable else { // MP_HUD.text("Bad connection~".localizableString(), delay: 2.0, completion: nil) // return // } if moreBlock != nil { moreBlock!() } } //下载按钮代理 func downloadButtonTapped(_ downloadButton: PKDownloadButton!, currentState state: PKDownloadButtonState) { var video:MPPositive_SongItemModel! //根据当前按钮状态确定进度 switch state { case .startDownload://开始状态,点击后进入下载状态 //检索当前网络状态 guard MP_NetWorkManager.shared.netWorkStatu == .reachable else { MP_HUD.text("Bad connection~".localizableString(), delay: 2.0, completion: nil) return } var videoId:String? var playListId:String? if let itemView = itemView { videoId = itemView.item.videoId playListId = itemView.item.playListId } if let songViewModel = songViewModel { videoId = songViewModel.collectionSong.videoId playListId = "" } if let loadViewModel = loadViewModel { videoId = loadViewModel.loadItem.videoId playListId = loadViewModel.loadItem.playListID } if let videoModel = videoModel { videoId = videoModel.videoId playListId = "" } //检索当前歌曲是否下载过 guard let videoId = videoId else { return } //未下载 MP_ADSimpleManager.shared.showLibraryInterstitialAdIfAvailable(completion: nil) //切换为准备状态 downloadButton.state = .pending //通过网络请求获取当前预览项资源(转为Song) MP_NetWorkManager.shared.requestNextList(playListId ?? "", videoId: videoId, clickTrackingParams: nil){ [weak self] listSongs in guard let self = self, let first = listSongs.first else { //获取资源失败 self?.setProgress(videoId) return } let group = DispatchGroup() group.enter() improveDataforLycirsAndRelated(first) {(result) in first.lyricsID = result.0 first.relatedID = result.1 group.leave() } group.enter() //补全资源路径组和封面路径组 improveDataforResouceAndCover(first) {(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 { self?.setProgress(videoId) return } video = first //事件打点 MP_AnalyticsManager.shared.player_b_download_clickAction(video.videoId ?? "", videoname: video.title ?? "", artistname: video.shortBylineText ?? "") //补全了数据,执行下载 MP_DownloadManager.shared.prepareVideoDownloadTask(from: video) }) } case .downloaded://已下载 if let block = deleteBlock { block() } default: if let block = cancelBlock { block() } } } }