// MPPositive_PlayerCoverView.swift // MusicPlayer // Created by Mr.Zhou on 2024/5/8. import UIKit import DownloadButton import MarqueeLabel //B面播放器封面View(封面,标题,副标题,收藏,下载,进度条View) class MPPositive_PlayerCoverView: UIView, PKDownloadButtonDelegate { ///封面视图 lazy var coverImageView:UIImageView = { let imageView = UIImageView() imageView.image = placeholderImage imageView.contentMode = .scaleAspectFill imageView.layer.masksToBounds = true imageView.layer.cornerRadius = 16*width return imageView }() //视频视图 lazy var videoView:UIView = { let videoView:UIView = .init() videoView.backgroundColor = .clear return videoView }() ///标题 lazy var titleLabel:MarqueeLabel = createMarQueeLabel("Loading", font: .systemFont(ofSize: 22*width, weight: .regular), textColor: .init(hex: "#FFFFFF", alpha: 0.85)) ///副标题 lazy var subtitleLabel:MarqueeLabel = { let label = createMarQueeLabel("Loading", font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .init(hex: "#EEEEEE", alpha: 0.6)) label.isUserInteractionEnabled = true label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(searchSubtitleClick(_ :)))) return label }() lazy var inctorLabel:UILabel = createLabel(">>", font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .init(hex: "#EEEEEE", alpha: 0.6), textAlignment: .left) ///收藏按钮 lazy var collectionSongBtn:UIButton = { let btn = UIButton() btn.setBackgroundImage(UIImage(named: "List_UnCollection'logo"), for: .normal) btn.setBackgroundImage(UIImage(named: "List_Collectioned'logo"), for: .selected) btn.addTarget(self, action: #selector(collectionSwitchClick(_ :)), for: .touchUpInside) return btn }() ///下载按钮 lazy var downloadButton: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.isUserInteractionEnabled = false btn.downloadedButton.setAttributedTitle(nil, for: .normal) //停止下载状态 btn.stopDownloadButton.stopButton.setImage(UIImage(named: "download"), for: .normal) // btn.stopDownloadButton.isUserInteractionEnabled = false 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 }() ///进度条View lazy var sliderView:MPPositive_PlayerSilder = { let sliderView:MPPositive_PlayerSilder = .init(frame: .init(x: 0, y: 0, width: 335*width, height: 6*width)) sliderView.addTarget(self, action: #selector(seekProgressClick(_:forEvent:)), for: .valueChanged) sliderView.addTarget(self, action: #selector(seekProgressClick(_:forEvent:)), for: .touchDown) sliderView.addTarget(self, action: #selector(seekProgressClick(_:forEvent:)), for: .touchUpInside) return sliderView }() ///缓存条View lazy var progressView:UIProgressView = { let progressView:UIProgressView = .init() progressView.isUserInteractionEnabled = true progressView.progressTintColor = .init(hex: "#FFFFFF", alpha: 0.3) progressView.trackTintColor = .clear progressView.progress = 0 return progressView }() ///当前播放时间值Label lazy var durationLabel:UILabel = createLabel("00:00" ,font: .systemFont(ofSize: 12*width, weight: .medium), textColor: .init(hex: "#FFFFFF", alpha: 0.85), textAlignment: .left) ///最大播放时间值Label lazy var maxTimesLabel:UILabel = createLabel("00:00" ,font: .systemFont(ofSize: 12*width, weight: .medium), textColor: .init(hex: "#FFFFFF", alpha: 0.6), textAlignment: .right) //删除 var deleteBlock:(() -> Void)? //取消 var cancelBlock:(() -> Void)? //副标题查询 var searchBlock:((String) -> Void)? override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear configure() NotificationCenter.notificationKey.add(observer: self, selector: #selector(downloadProgressAction(_ :)), notificationName: .download_progress_source) NotificationCenter.notificationKey.add(observer: self, selector: #selector(downloadEndAction(_ :)), notificationName: .dowload_end_source) } required init?(coder: NSCoder) { super.init(coder: coder) } deinit { NotificationCenter.default.removeObserver(self) } //视图配置 private func configure() { //配置封面图 addSubview(coverImageView) coverImageView.snp.makeConstraints { make in make.width.equalTo(335*width) make.height.equalTo(330*width) make.centerX.equalToSuperview() make.top.equalToSuperview().offset(12*width) } //添加标题 addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.left.equalTo(coverImageView.snp.left) make.top.equalTo(coverImageView.snp.bottom).offset(36*width) make.right.equalTo(coverImageView.snp.right).offset(-100*width) } addSubview(videoView) videoView.snp.makeConstraints { make in make.left.top.right.equalToSuperview() make.bottom.equalTo(titleLabel.snp.top).offset(0) } videoView.isHidden = true addSubview(subtitleLabel) subtitleLabel.snp.makeConstraints { make in make.left.equalTo(titleLabel) make.right.lessThanOrEqualTo(titleLabel) make.top.equalTo(titleLabel.snp.bottom).offset(6*width) } addSubview(inctorLabel) inctorLabel.snp.makeConstraints { make in make.left.equalTo(subtitleLabel.snp.right).offset(3*width) make.centerY.equalTo(subtitleLabel) } //配置下载和收藏按钮 addSubview(downloadButton) downloadButton.snp.makeConstraints { make in make.right.equalTo(coverImageView.snp.right).offset(-12*width) make.top.equalTo(coverImageView.snp.bottom).offset(47*width) make.width.height.equalTo(24*width) } addSubview(collectionSongBtn) collectionSongBtn.snp.makeConstraints { make in make.right.equalTo(downloadButton.snp.left).offset(-20*width) make.centerY.equalTo(downloadButton.snp.centerY) make.width.height.equalTo(24*width) } addSubview(progressView) progressView.snp.makeConstraints { make in make.top.equalTo(subtitleLabel.snp.bottom).offset(25*width) make.centerX.equalToSuperview() make.width.equalTo(335*width) make.height.equalTo(6*width) } //配置进度条和时间label addSubview(sliderView) sliderView.snp.makeConstraints { make in make.left.right.top.bottom.equalTo(progressView) } addSubview(durationLabel) durationLabel.snp.makeConstraints { make in make.left.equalTo(sliderView.snp.left) make.top.equalTo(sliderView.snp.bottom).offset(5*width) } addSubview(maxTimesLabel) maxTimesLabel.snp.makeConstraints { make in make.right.equalTo(sliderView.snp.right) make.top.equalTo(sliderView.snp.bottom).offset(5*width) } } //根据输入videoId检索是否下载 func setProgress(_ videoId:String) { guard videoId.isEmpty == false, videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId else { 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.downloadButton.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.downloadButton.stopDownloadButton.progress = progress } } } }else { //处于队列中,还未开始下载 DispatchQueue.main.async { [weak self] in guard let self = self else {return} //未加入下载队列 self.downloadButton.state = .pending } } } }else { //未加入下载队列 DispatchQueue.main.async { [weak self] in guard let self = self else {return} //未加入下载队列 self.downloadButton.state = .startDownload } } }else { //已经完成下载 DispatchQueue.main.async { [weak self] in guard let self = self else {return} //已经完成下载 self.downloadButton.state = .downloaded } } } } } //收到progress加载 @objc private func downloadProgressAction(_ sender:Notification) { if let dict = sender.object as? [String:String], let videoId = dict["videoId"], let currentVideoId = MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.videoId, videoId == currentVideoId { //比较当前videoId setProgress(videoId) } } //收到下载结束 @objc private func downloadEndAction(_ sender:Notification) { if let dict = sender.object as? [String:String], let videoId = dict["videoId"], let currentVideoId = MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.videoId, videoId == currentVideoId { setProgress(videoId) } } //查询副标题 @objc private func searchSubtitleClick(_ sender:UITapGestureRecognizer) { guard MP_NetWorkManager.shared.netWorkStatu == .reachable else { MP_HUD.onlytext("Bad connection~".localizableString(), delay: 1.0, completion: nil) return } guard let text = subtitleLabel.text, text.isEmpty != true else {return} if let block = searchBlock { block(text) } } //调整音乐进度 @objc private func seekProgressClick(_ sender: UISlider, forEvent event: UIEvent) { //获取touchEvent let touchEvent = event.allTouches?.first //判断点击事件状态 switch touchEvent?.phase { case .began://开始拖动 //让播放器进入调整状态 MP_PlayerManager.shared.setEditPorgressStatu() case .moved://移动中 break case .ended://结束 let value = sender.value //让播放器恢复状态 MP_PlayerManager.shared.setEditProgressEnd(value) default: break } } //切换当前列表收藏状态 @objc private func collectionSwitchClick(_ sender:UIButton) { //根据当前按钮的状况确定是否收藏 if self.collectionSongBtn.isSelected == true{ //取消收藏 self.collectionSongBtn.isSelected = false if let currentVideo = MP_PlayerManager.shared.loadPlayer?.currentVideo{ //移除收藏实例 MPPositive_CollectionSongModel.fetch(predicate: .init(format: "videoId == %@", (currentVideo.song.videoId ?? ""))) { [weak self] results in results.forEach { i in if i.videoId == currentVideo.song.videoId{ MPPositive_CollectionSongModel.delete(i) } } //更新当前播放音乐状态 MP_PlayerManager.shared.loadPlayer?.currentVideo?.reloadCollectionAndDownLoad() MPPositive_LoadCoreModel.shared.reloadCollectionSongViewModel(nil) } MP_AnalyticsManager.shared.player_b_unlove_clickAction(MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.videoId ?? "", videoname: MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.title ?? "", artistname: MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.shortBylineText ?? "") } }else{ //添加收藏 self.collectionSongBtn.isSelected = true if let currentVideo = MP_PlayerManager.shared.loadPlayer?.currentVideo{ //创建收藏实例 let item = try? MPPositive_CollectionSongModel.create() item?.title = currentVideo.title item?.videoId = currentVideo.song.videoId item?.subtitle = currentVideo.subtitle item?.coverImage = currentVideo.coverUrl item?.lyricsID = currentVideo.song.lyricsID item?.relatedID = currentVideo.song.relatedID item?.addTime = Date() MPPositive_CollectionSongModel.save() //更新当前播放音乐状态 MP_PlayerManager.shared.loadPlayer?.currentVideo.reloadCollectionAndDownLoad() MPPositive_LoadCoreModel.shared.reloadCollectionSongViewModel(nil) MP_AnalyticsManager.shared.player_b_love_clickAction(MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.videoId ?? "", videoname: MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.title ?? "", artistname: MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.shortBylineText ?? "") } } } //下载按钮代理 func downloadButtonTapped(_ downloadButton: PKDownloadButton!, currentState state: PKDownloadButtonState) { //当前音乐没有下载 switch state { case .startDownload: //开始状态,点击时准备加载 guard MP_PlayerManager.shared.loadPlayer?.currentVideo != nil, MP_PlayerManager.shared.loadPlayer?.currentVideo?.isDlownd == false else { return } guard MP_NetWorkManager.shared.netWorkStatu == .reachable else { MP_HUD.text("Bad connection~".localizableString(), delay: 2.0, completion: nil) return } MP_ADSimpleManager.shared.showLibraryInterstitialAdIfAvailable(completion: nil) //切换为准备状态 downloadButton.state = .pending //当开始下载时 guard let currentVideo = MP_PlayerManager.shared.loadPlayer?.currentVideo else { MP_HUD.text("An error occurred while downloading. Please download again.".localizableString(), delay: 1.0) { downloadButton.state = .startDownload } return } MP_AnalyticsManager.shared.player_b_download_clickAction(currentVideo.song.videoId ?? "", videoname: currentVideo.song.title ?? "", artistname: currentVideo.song.shortBylineText ?? "") //补全了数据,执行下载 MP_DownloadManager.shared.prepareVideoDownloadTask(from: currentVideo.song) case .downloaded://已下载,点击删除下载 if let block = deleteBlock { block() } default: if let block = cancelBlock { block() } } } }