From 907142b0088c3a36baa8235058a82ea55779cef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=86=E6=B5=B716?= <> Date: Wed, 22 May 2024 17:51:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E4=B8=8B=E8=BD=BD=EF=BC=8C?= =?UTF-8?q?=E6=AD=8C=E5=8D=95=EF=BC=8C=E6=AD=8C=E6=89=8B=EF=BC=8C=E5=8D=95?= =?UTF-8?q?=E6=9B=B2=E6=94=B6=E8=97=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MusicPlayer/AppDelegate.swift | 11 + .../MusicPlayer.xcdatamodel/contents | 3 +- .../MP_CircularProgressView.swift | 83 ++++--- .../Tool(工具封装)/MP_DownloadManager.swift | 129 +++++++--- .../MPPositive_CollectionListModel.swift | 2 - .../MPPositive_ListAlbumListViewModel.swift | 2 + .../MPPositive_ArtistShowViewController.swift | 6 + .../MPPositive_ListShowViewController.swift | 34 ++- .../MPPositive_PlayerViewController.swift | 1 + .../MPPositive_ArtistShowHeaderView.swift | 39 ++++ .../Player/MPPositive_PlayerCoverView.swift | 221 +++++++++++++----- 11 files changed, 413 insertions(+), 118 deletions(-) diff --git a/MusicPlayer/AppDelegate.swift b/MusicPlayer/AppDelegate.swift index d757688..27707c9 100644 --- a/MusicPlayer/AppDelegate.swift +++ b/MusicPlayer/AppDelegate.swift @@ -29,6 +29,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate { switch_lunch() return true } + func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) { + DownloadManager.shared.session.getAllTasks { tasks in + for task in tasks { + task.resume() + } + } + completionHandler() + } + + + //设置播放器会话状态 private func setAudioSupport(){ //设置会话 diff --git a/MusicPlayer/MP/Common/DataBase/MusicPlayer.xcdatamodeld/MusicPlayer.xcdatamodel/contents b/MusicPlayer/MP/Common/DataBase/MusicPlayer.xcdatamodeld/MusicPlayer.xcdatamodel/contents index 5a00158..95fb2fa 100644 --- a/MusicPlayer/MP/Common/DataBase/MusicPlayer.xcdatamodeld/MusicPlayer.xcdatamodel/contents +++ b/MusicPlayer/MP/Common/DataBase/MusicPlayer.xcdatamodeld/MusicPlayer.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -10,7 +10,6 @@ - diff --git a/MusicPlayer/MP/Common/Tool(工具封装)/MP_CircularProgressView.swift b/MusicPlayer/MP/Common/Tool(工具封装)/MP_CircularProgressView.swift index 2a49c3f..0c58bde 100644 --- a/MusicPlayer/MP/Common/Tool(工具封装)/MP_CircularProgressView.swift +++ b/MusicPlayer/MP/Common/Tool(工具封装)/MP_CircularProgressView.swift @@ -12,7 +12,7 @@ class CircularProgressView: UIView { private var progressLayer = CAShapeLayer() private var trackLayer = CAShapeLayer() - private var progress: CGFloat = 0 { + public var progress: CGFloat = 0 { didSet { progressLayer.strokeEnd = progress } @@ -20,36 +20,65 @@ class CircularProgressView: UIView { override init(frame: CGRect) { super.init(frame: frame) - setupLayers() + setupView() } required init?(coder: NSCoder) { super.init(coder: coder) - setupLayers() + setupView() } - private func setupLayers() { - // Track layer (background circle) - let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2) - let circularPath = UIBezierPath(arcCenter: center, radius: bounds.width / 2, startAngle: -CGFloat.pi / 2, endAngle: 3 * CGFloat.pi / 2, clockwise: true) - - trackLayer.path = circularPath.cgPath - trackLayer.strokeColor = UIColor.lightGray.cgColor - trackLayer.lineWidth = 3 - trackLayer.fillColor = UIColor.clear.cgColor - layer.addSublayer(trackLayer) - - // Progress layer (foreground circle) - progressLayer.path = circularPath.cgPath - progressLayer.strokeColor = UIColor.green.cgColor - progressLayer.lineWidth = 3 - progressLayer.fillColor = UIColor.clear.cgColor - progressLayer.lineCap = .round - progressLayer.strokeEnd = 0 - layer.addSublayer(progressLayer) - } - - func setProgress(to progress: CGFloat) { - self.progress = progress - } +// private func setupLayers() { +// // Track layer (background circle) +// let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2) +// let circularPath = UIBezierPath(arcCenter: center, radius: bounds.width / 2, startAngle: -CGFloat.pi / 2, endAngle: 3 * CGFloat.pi / 2, clockwise: true) +// +// trackLayer.path = circularPath.cgPath +// trackLayer.strokeColor = UIColor.lightGray.cgColor +// trackLayer.lineWidth = 3 +// trackLayer.fillColor = UIColor.clear.cgColor +// layer.addSublayer(trackLayer) +// +// // Progress layer (foreground circle) +// progressLayer.path = circularPath.cgPath +// progressLayer.strokeColor = UIColor.green.cgColor +// progressLayer.lineWidth = 3 +// progressLayer.fillColor = UIColor.clear.cgColor +// progressLayer.lineCap = .round +// progressLayer.strokeEnd = 0 +// layer.addSublayer(progressLayer) +// } +// +// func setProgress(to progress: CGFloat) { +// self.progress = progress +// } + private func setupView() { + // 设置轨道图层 + trackLayer.path = createCircularPath().cgPath + trackLayer.fillColor = UIColor.clear.cgColor + trackLayer.strokeColor = UIColor.lightGray.cgColor + trackLayer.lineWidth = 3 + trackLayer.strokeEnd = 1.0 + layer.addSublayer(trackLayer) + + // 设置进度图层 + progressLayer.path = createCircularPath().cgPath + progressLayer.fillColor = UIColor.clear.cgColor + progressLayer.strokeColor = UIColor.green.cgColor + progressLayer.lineWidth = 3 + progressLayer.strokeEnd = 0.0 + layer.addSublayer(progressLayer) + } + + private func createCircularPath() -> UIBezierPath { + return UIBezierPath(arcCenter: center, radius: bounds.size.width / 2, startAngle: -.pi / 2, endAngle: .pi * 3 / 2, clockwise: true) + } + + func setProgress(to progress: CGFloat) { + self.progress = progress + print("Updating progress to: \(progress)") + DispatchQueue.main.async { + self.progressLayer.strokeEnd = progress + } + } } diff --git a/MusicPlayer/MP/Common/Tool(工具封装)/MP_DownloadManager.swift b/MusicPlayer/MP/Common/Tool(工具封装)/MP_DownloadManager.swift index ce50126..1de0afc 100644 --- a/MusicPlayer/MP/Common/Tool(工具封装)/MP_DownloadManager.swift +++ b/MusicPlayer/MP/Common/Tool(工具封装)/MP_DownloadManager.swift @@ -9,39 +9,110 @@ import Foundation import Foundation import Alamofire -class DownloadManager { - +class DownloadManager: NSObject, URLSessionDownloadDelegate { static let shared = DownloadManager() - - private init() {} - - func downloadVideo(from url: URL, videoId: String, progressView: CircularProgressView, completion: @escaping (Result) -> Void) { - let destination: DownloadRequest.Destination = { _, _ in - let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] - let downloadsURL = documentsURL.appendingPathComponent("Downloads") - - // 检查并创建 Downloads 文件夹 - if !FileManager.default.fileExists(atPath: downloadsURL.path) { - do { - try FileManager.default.createDirectory(at: downloadsURL, withIntermediateDirectories: true, attributes: nil) - } catch { - completion(.failure(error)) - return (downloadsURL, [.removePreviousFile, .createIntermediateDirectories]) - } + + var session: URLSession! + var progressHandlers: [URL: (CGFloat) -> Void] = [:] + var completionHandlers: [URL: (Result) -> Void] = [:] + var downloadTasks: [URL: URLSessionDownloadTask] = [:] + var progressStorage: [URL: CGFloat] = [:] // 新增进度存储 + + private override init() { + super.init() + let configuration = URLSessionConfiguration.background(withIdentifier: "com.yourApp.backgroundDownload") + session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil) + } + + func downloadVideo(from url: URL, videoId: String, progressHandler: @escaping (CGFloat) -> Void, completion: @escaping (Result) -> Void) { + let downloadTask = session.downloadTask(with: url) + progressHandlers[url] = progressHandler + completionHandlers[url] = completion + downloadTasks[url] = downloadTask + downloadTask.resume() + } + + func getProgress(for url: URL) -> CGFloat? { + return progressStorage[url] + } + + // URLSessionDownloadDelegate methods + func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { + guard let originalURL = downloadTask.originalRequest?.url else { return } + let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + let downloadsURL = documentsURL.appendingPathComponent("Downloads") + + if !FileManager.default.fileExists(atPath: downloadsURL.path) { + do { + try FileManager.default.createDirectory(at: downloadsURL, withIntermediateDirectories: true, attributes: nil) + } catch { + completionHandlers[originalURL]?(.failure(error)) + return } - - let fileURL = downloadsURL.appendingPathComponent("\(videoId).mp4") - return (fileURL, [.removePreviousFile, .createIntermediateDirectories]) } - AF.download(url, to: destination).downloadProgress { progress in - progressView.setProgress(to: CGFloat(progress.fractionCompleted)) - }.response { response in - if let error = response.error { - completion(.failure(error)) - } else if let filePath = response.fileURL { - completion(.success(filePath)) - } + let fileURL = downloadsURL.appendingPathComponent("\(MP_PlayerManager.shared.loadPlayer.currentVideo.song.videoId ?? "").mp4") + do { + try FileManager.default.moveItem(at: location, to: fileURL) + completionHandlers[originalURL]?(.success(fileURL)) + progressStorage[originalURL] = nil // 清除已完成任务的进度记录 + } catch { + completionHandlers[originalURL]?(.failure(error)) + } + } + + func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { + guard let originalURL = downloadTask.originalRequest?.url else { return } + let progress = CGFloat(totalBytesWritten) / CGFloat(totalBytesExpectedToWrite) + progressHandlers[originalURL]?(progress) + progressStorage[originalURL] = progress // 存储当前进度 + + } + + func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + guard let originalURL = task.originalRequest?.url else { return } + if let error = error { + completionHandlers[originalURL]?(.failure(error)) } } } + + + +//class DownloadManager { +// +// static let shared = DownloadManager() +// +// private init() {} +// +// func downloadVideo(from url: URL, videoId: String, progressView: CircularProgressView, completion: @escaping (Result) -> Void) { +// let destination: DownloadRequest.Destination = { _, _ in +// let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] +// let downloadsURL = documentsURL.appendingPathComponent("Downloads") +// +// // 检查并创建 Downloads 文件夹 +// if !FileManager.default.fileExists(atPath: downloadsURL.path) { +// do { +// try FileManager.default.createDirectory(at: downloadsURL, withIntermediateDirectories: true, attributes: nil) +// } catch { +// completion(.failure(error)) +// return (downloadsURL, [.removePreviousFile, .createIntermediateDirectories]) +// } +// } +// +// let fileURL = downloadsURL.appendingPathComponent("\(videoId).mp4") +// return (fileURL, [.removePreviousFile, .createIntermediateDirectories]) +// } +// +// AF.download(url, to: destination).downloadProgress { progress in +// progressView.setProgress(to: CGFloat(progress.fractionCompleted)) +// }.response { response in +// if let error = response.error { +// completion(.failure(error)) +// } else if let filePath = response.fileURL { +// completion(.success(filePath)) +// } +// } +// } +//} + diff --git a/MusicPlayer/MP/MPPositive/Models/Models/MPPositive_CollectionListModel.swift b/MusicPlayer/MP/MPPositive/Models/Models/MPPositive_CollectionListModel.swift index 0653817..affd95a 100644 --- a/MusicPlayer/MP/MPPositive/Models/Models/MPPositive_CollectionListModel.swift +++ b/MusicPlayer/MP/MPPositive/Models/Models/MPPositive_CollectionListModel.swift @@ -15,8 +15,6 @@ class MPPositive_CollectionListModel: NSManagedObject, MP_CoreDataManageableDele @NSManaged var coverImage:URL! ///标题(单曲标题) @NSManaged var title:String? - ///二级标题 - @NSManaged var subtitle:String? ///列表专辑预览ID @NSManaged var browseId:String? ///列表专辑预览参数 diff --git a/MusicPlayer/MP/MPPositive/Models/ViewModels/ListViewModels/MPPositive_ListAlbumListViewModel.swift b/MusicPlayer/MP/MPPositive/Models/ViewModels/ListViewModels/MPPositive_ListAlbumListViewModel.swift index 657a074..60febff 100644 --- a/MusicPlayer/MP/MPPositive/Models/ViewModels/ListViewModels/MPPositive_ListAlbumListViewModel.swift +++ b/MusicPlayer/MP/MPPositive/Models/ViewModels/ListViewModels/MPPositive_ListAlbumListViewModel.swift @@ -13,5 +13,7 @@ class MPPositive_ListAlbumListViewModel: NSObject { ///列表数据组(由预览模块组成) var items:[MPPositive_BrowseItemViewModel] = [] + var isCollection:Bool = false + } diff --git a/MusicPlayer/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ArtistShowViewController.swift b/MusicPlayer/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ArtistShowViewController.swift index 052655a..9399f7f 100644 --- a/MusicPlayer/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ArtistShowViewController.swift +++ b/MusicPlayer/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ArtistShowViewController.swift @@ -64,7 +64,9 @@ class MPPositive_ArtistShowViewController: MPPositive_BaseViewController { if artist != nil { pagingView.isHidden = false //更新头部视图数据 + headView.artistid = self.browseid headView.artist = artist + //更新分页数据源 dataSource.titles = artist.lists.compactMap({$0.title}) nameLabel.text = artist.header?.title @@ -73,11 +75,14 @@ class MPPositive_ArtistShowViewController: MPPositive_BaseViewController { } } } + var browseid:String = "" + var iscollection:Bool = false /// 艺术家页面 /// - Parameter browseId: 艺术家Id init(_ browseId:String) { super.init(nibName: nil, bundle: nil) + browseid = browseId //进行网络请求 MP_NetWorkManager.shared.requestArtist(browseId) { [weak self] result in DispatchQueue.main.async { @@ -97,6 +102,7 @@ class MPPositive_ArtistShowViewController: MPPositive_BaseViewController { setTitle("") configure() } + private func configure() { segmentView.dataSource = dataSource segmentView.indicators = [indicator] diff --git a/MusicPlayer/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ListShowViewController.swift b/MusicPlayer/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ListShowViewController.swift index b048f99..b734386 100644 --- a/MusicPlayer/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ListShowViewController.swift +++ b/MusicPlayer/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ListShowViewController.swift @@ -81,16 +81,21 @@ class MPPositive_ListShowViewController: MPPositive_BaseViewController { } } + var browseid:String = "" + var params:String = "" /// 生成列表控制器 /// - Parameters: /// - browseId: 列表的id /// - params: 列表的编码 init(_ browseId:String, params:String) { super.init(nibName: nil, bundle: nil) + self.browseid = browseId + self.params = params //发起网络请求 MP_NetWorkManager.shared.requestAlbumOrListDatas(browseId, params: params) { [weak self] result in guard let self = self else {return} listOrAlbum = result + } } @@ -105,6 +110,13 @@ class MPPositive_ListShowViewController: MPPositive_BaseViewController { } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + MPPositive_CollectionListModel.fetch(.init(format: "browseId == %@", self.browseid)).forEach { i in + if i.browseId == self.browseid{ + if i.params == self.params{ + self.collectionListBtn.isSelected = true + } + } + } } //页面刷新 private func reload() { @@ -222,7 +234,27 @@ class MPPositive_ListShowViewController: MPPositive_BaseViewController { } //切换当前列表收藏状态 @objc private func collectionSwitchClick(_ sender:UIButton) { - + if self.collectionListBtn.isSelected == true{ + self.collectionListBtn.isSelected = false + + MPPositive_CollectionListModel.fetch(.init(format: "browseId == %@", self.browseid)).forEach { i in + if i.browseId == self.browseid{ + if i.params == self.params{ + MPPositive_CollectionListModel.delete(i) + } + } + } + + }else{ + self.collectionListBtn.isSelected = true + let item = MPPositive_CollectionListModel.create() + item.title = listOrAlbum.header.title + item.browseId = self.browseid + item.params = self.params + item.coverImage = listOrAlbum.header.coverUrl + MPPositive_CollectionListModel.save() + + } } //更改当前列表播放状态 @objc private func collectionStatuClick(_ sender:UIButton) { diff --git a/MusicPlayer/MP/MPPositive/ViewControllers/Player(播放器)/MPPositive_PlayerViewController.swift b/MusicPlayer/MP/MPPositive/ViewControllers/Player(播放器)/MPPositive_PlayerViewController.swift index 8298d5e..e192b99 100644 --- a/MusicPlayer/MP/MPPositive/ViewControllers/Player(播放器)/MPPositive_PlayerViewController.swift +++ b/MusicPlayer/MP/MPPositive/ViewControllers/Player(播放器)/MPPositive_PlayerViewController.swift @@ -165,6 +165,7 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont if MP_PlayerManager.shared.loadPlayer.currentVideo != nil { uploadUI() } + coverView.restoreDownloadProgress() } //视图配置 private func configure() { diff --git a/MusicPlayer/MP/MPPositive/Views/Home/MPPositive_ArtistShowHeaderView.swift b/MusicPlayer/MP/MPPositive/Views/Home/MPPositive_ArtistShowHeaderView.swift index f5bc707..d5494a5 100644 --- a/MusicPlayer/MP/MPPositive/Views/Home/MPPositive_ArtistShowHeaderView.swift +++ b/MusicPlayer/MP/MPPositive/Views/Home/MPPositive_ArtistShowHeaderView.swift @@ -14,6 +14,8 @@ class MPPositive_ArtistShowHeaderView: UIView { imageView.contentMode = .scaleAspectFill return imageView }() + var artistid:String = "" + var iscollection:Bool = false //艺术家名字 private lazy var nameLabel:UILabel = createLabel(font: .systemFont(ofSize: 32*width, weight: .semibold), textColor: .white, textAlignment: .left) //艺术家当前订阅量label @@ -40,16 +42,26 @@ class MPPositive_ArtistShowHeaderView: UIView { reviewImageView.kf.setImage(with: URL(string: artist.header?.thumbnails?.last ?? ""), placeholder: placeholderImage) nameLabel.text = artist.header?.title followersLabel.text = (artist.header?.subscriptions ?? "")+" "+(artist.header?.subscriptionedText ?? "") + let items = MPPositive_CollectionArtistModel.fetch(.init(format: "artistId == %@", self.artistid)) + for item in items { + if item.artistId == self.artistid { + + self.collectionBtn.isSelected = true + + } + } } } override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear configure() + } required init?(coder: NSCoder) { super.init(coder: coder) + } private func configure() { addSubview(reviewImageView) @@ -78,9 +90,36 @@ class MPPositive_ArtistShowHeaderView: UIView { make.left.right.equalTo(nameLabel) make.bottom.equalTo(collectionBtn) } + } //收藏这位艺术家 @objc private func collectionClick(_ sender:UIButton) { + if self.collectionBtn.isSelected == true{ + self.collectionBtn.isSelected = false + +// MPPositive_CollectionArtistModel.fetch(.init(format: "artistId == %@", self.browseid)).forEach { i in +// if i.artistId == self.browseid{ +// MPPositive_CollectionArtistModel.delete(i) +// } +// } + let items = MPPositive_CollectionArtistModel.fetch(.init(format: "artistId == %@", self.artistid)) + for item in items { + if item.artistId == self.artistid { + MPPositive_CollectionArtistModel.delete(item) + } + } + + + }else{ + self.collectionBtn.isSelected = true + let item = MPPositive_CollectionArtistModel.create() + item.title = artist.header.title + item.coverImage = URL(string: artist.header.thumbnails?.last ?? "") + item.subtitle = artist.header.subscriptionedText + item.artistId = self.artistid + MPPositive_CollectionArtistModel.save() + + } } } diff --git a/MusicPlayer/MP/MPPositive/Views/Player/MPPositive_PlayerCoverView.swift b/MusicPlayer/MP/MPPositive/Views/Player/MPPositive_PlayerCoverView.swift index fa0d870..376f05e 100644 --- a/MusicPlayer/MP/MPPositive/Views/Player/MPPositive_PlayerCoverView.swift +++ b/MusicPlayer/MP/MPPositive/Views/Player/MPPositive_PlayerCoverView.swift @@ -1,12 +1,9 @@ -// // MPPositive_PlayerCoverView.swift // MusicPlayer -// // Created by Mr.Zhou on 2024/5/8. -// import UIKit -import SVProgressHUD + //B面播放器封面View(封面,标题,副标题,收藏,下载,进度条View) class MPPositive_PlayerCoverView: UIView { //下载进度条View @@ -61,15 +58,64 @@ class MPPositive_PlayerCoverView: UIView { ///最大播放时间值Label lazy var maxTimesLabel:UILabel = createLabel("00:00" ,font: .systemFont(ofSize: 12*width, weight: .medium), textColor: .init(hex: "#FFFFFF", alpha: 0.6), textAlignment: .right) + + override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear configure() + } + + required init?(coder: NSCoder) { super.init(coder: coder) +// NotificationCenter.default.addObserver(self, selector: #selector(updateProgress(_:)), name: Notification.Name("DownloadProgressUpdated"), object: nil) +// +// // 恢复进度 +// restoreDownloadProgress() } + + public func restoreDownloadProgress() { + + if let currentVideo = MP_PlayerManager.shared.loadPlayer.currentVideo, + let videoURLString = currentVideo.song.resourceUrls?.first, + let videoURL = URL(string: videoURLString) { + if let progress = DownloadManager.shared.getProgress(for: videoURL) { + addCircularProgressBar(over: loadBtn) + loadView.setProgress(to: progress) +// DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // 延迟0.1秒 + self.layoutIfNeeded() + self.loadBtn.setBackgroundImage(UIImage(named: ""), for: .normal) + self.loadBtn.setImage(UIImage(named: "download"), for: .normal) + self.addCircularProgressBar(over: self.loadBtn) + self.loadView.setProgress(to: progress) +// } + } + } + } + + @objc private func updateProgress(_ notification: Notification) { + if let userInfo = notification.userInfo, + let url = userInfo["url"] as? URL, + let progress = userInfo["progress"] as? CGFloat, + let currentVideo = MP_PlayerManager.shared.loadPlayer.currentVideo, + let videoURLString = currentVideo.song.resourceUrls?.first, + let videoURL = URL(string: videoURLString), + videoURL == url { + loadView.setProgress(to: progress) + if loadView.progress.isEqual(to: 1.0){ + self.loadView.removeFromSuperview() + self.loadBtn.setBackgroundImage(UIImage(named: "Song_Loaded'logo"), for: .normal) + self.loadBtn.setImage(UIImage(named: ""), for: .normal) + } + + } + } + + + //视图配置 private func configure() { //配置封面图 @@ -127,6 +173,10 @@ class MPPositive_PlayerCoverView: UIView { make.right.equalTo(sliderView.snp.right) make.top.equalTo(sliderView.snp.bottom).offset(5*width) } + NotificationCenter.default.addObserver(self, selector: #selector(updateProgress(_:)), name: Notification.Name("DownloadProgressUpdated"), object: nil) + + // 恢复进度 + restoreDownloadProgress() } //调整音乐进度 @objc private func seekProgressClick(_ sender: UISlider, forEvent event: UIEvent) { @@ -172,63 +222,118 @@ class MPPositive_PlayerCoverView: UIView { } } } - //点击下载 - @objc private func loadActionClick(_ sender:UIButton) { - - if MP_PlayerManager.shared.loadPlayer.currentVideo?.isDlownd == false{ - - // 添加圆形进度条到下载按钮位置 - addCircularProgressBar(over: sender) + @objc private func loadActionClick(_ sender: UIButton) { + if MP_PlayerManager.shared.loadPlayer.currentVideo?.isDlownd == false { + addCircularProgressBar(over: sender) - self.loadBtn.setBackgroundImage(UIImage(named: ""), for: .normal) - self.loadBtn.setImage(UIImage(named: "download"), for: .normal) - - //下载,检索当前播放音乐是否存在 - if MP_PlayerManager.shared.loadPlayer.currentVideo != nil { + self.loadBtn.setBackgroundImage(UIImage(named: ""), for: .normal) + self.loadBtn.setImage(UIImage(named: "download"), for: .normal) - // 下载视频 - if let currentVideo = MP_PlayerManager.shared.loadPlayer.currentVideo, let videoURLString = currentVideo.song.resourceUrls?.first, let videoURL = URL(string: videoURLString) { - let videoId = currentVideo.song.videoId ?? "default_video_id" - DownloadManager.shared.downloadVideo(from: videoURL, videoId: videoId, progressView: loadView, completion: { [weak self] result in - switch result { - case .success(let fileURL): - let item = MPPositive_DownloadItemModel.create() - item.resourcePath = "\(fileURL)" - item.coverImage = URL(string: MP_PlayerManager.shared.loadPlayer.currentVideo.song.coverUrls!.first!) - item.reviewImage = URL(string: MP_PlayerManager.shared.loadPlayer.currentVideo.song.reviewUrls!.first!) - item.title = MP_PlayerManager.shared.loadPlayer.currentVideo.song.title - item.longBylineText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.longBylineText - item.lengthText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.lengthText - item.shortBylineText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.shortBylineText - item.lyrics = MP_PlayerManager.shared.loadPlayer.currentVideo.lyrics - item.videoId = MP_PlayerManager.shared.loadPlayer.currentVideo.song.videoId - item.relatedID = MP_PlayerManager.shared.loadPlayer.currentVideo.song.relatedID - - MPPositive_DownloadItemModel.save() - DispatchQueue.main.async { - MP_PlayerManager.shared.loadPlayer.currentVideo.reloadCollectionAndDownLoad() - self?.loadBtn.setBackgroundImage(UIImage(named: "Song_Loaded'logo"), for: .normal) - self?.loadBtn.setImage(UIImage(named: ""), for: .normal) - } - - self?.loadView.removeFromSuperview() - case .failure(let error): - print("Download failed with error: \(error)") - self?.loadView.removeFromSuperview() - DispatchQueue.main.async { - self?.loadBtn.setBackgroundImage(UIImage(named: "Song_Unload'logo"), for: .normal) - self?.loadBtn.setImage(UIImage(named: ""), for: .normal) - } - MP_HUD.text("下载超时请重新下载", delay: 1.5, completion: nil) - } - }) - } + if let currentVideo = MP_PlayerManager.shared.loadPlayer.currentVideo, + let videoURLString = currentVideo.song.resourceUrls?.first, + let videoURL = URL(string: videoURLString) { + let videoId = currentVideo.song.videoId ?? "default_video_id" + DownloadManager.shared.downloadVideo(from: videoURL, videoId: videoId, progressHandler: { [weak self] progress in + DispatchQueue.main.async { + self?.loadView.setProgress(to: progress) + NotificationCenter.default.post(name: Notification.Name("DownloadProgressUpdated"), object: nil, userInfo: ["url": videoURL, "progress": progress]) + } + }, completion: { [weak self] result in + switch result { + case .success(let fileURL): + let item = MPPositive_DownloadItemModel.create() + item.resourcePath = "\(fileURL)" + item.coverImage = URL(string: MP_PlayerManager.shared.loadPlayer.currentVideo.song.coverUrls!.first!) + item.reviewImage = URL(string: MP_PlayerManager.shared.loadPlayer.currentVideo.song.reviewUrls!.first!) + item.title = MP_PlayerManager.shared.loadPlayer.currentVideo.song.title + item.longBylineText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.longBylineText + item.lengthText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.lengthText + item.shortBylineText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.shortBylineText + item.lyrics = MP_PlayerManager.shared.loadPlayer.currentVideo.lyrics + item.videoId = MP_PlayerManager.shared.loadPlayer.currentVideo.song.videoId + item.relatedID = MP_PlayerManager.shared.loadPlayer.currentVideo.song.relatedID + + MPPositive_DownloadItemModel.save() + DispatchQueue.main.async { + self?.loadView.removeFromSuperview() + MP_PlayerManager.shared.loadPlayer.currentVideo.reloadCollectionAndDownLoad() + self?.loadBtn.setBackgroundImage(UIImage(named: "Song_Loaded'logo"), for: .normal) + self?.loadBtn.setImage(UIImage(named: ""), for: .normal) + } + case .failure(let error): + print("Download failed with error: \(error)") + DispatchQueue.main.async { + self?.loadView.removeFromSuperview() + self?.loadBtn.setBackgroundImage(UIImage(named: "Song_Unload'logo"), for: .normal) + self?.loadBtn.setImage(UIImage(named: ""), for: .normal) + } + MP_HUD.text("Download timed out, please download again", delay: 1.5, completion: nil) + } + }) + } } } - - } - // 添加圆形进度条 - private func addCircularProgressBar(over button: UIButton) { + + +// //点击下载 +// @objc private func loadActionClick(_ sender:UIButton) { +// +// if MP_PlayerManager.shared.loadPlayer.currentVideo?.isDlownd == false{ +// +// // 添加圆形进度条到下载按钮位置 +// addCircularProgressBar(over: sender) +// +// self.loadBtn.setBackgroundImage(UIImage(named: ""), for: .normal) +// self.loadBtn.setImage(UIImage(named: "download"), for: .normal) +// +// //下载,检索当前播放音乐是否存在 +// if MP_PlayerManager.shared.loadPlayer.currentVideo != nil { +// +// // 下载视频 +// if let currentVideo = MP_PlayerManager.shared.loadPlayer.currentVideo, let videoURLString = currentVideo.song.resourceUrls?.first, let videoURL = URL(string: videoURLString) { +// let videoId = currentVideo.song.videoId ?? "default_video_id" +// DownloadManager.shared.downloadVideo(from: videoURL, videoId: videoId, progressView: loadView, completion: { [weak self] result in +// switch result { +// case .success(let fileURL): +// let item = MPPositive_DownloadItemModel.create() +// item.resourcePath = "\(fileURL)" +// item.coverImage = URL(string: MP_PlayerManager.shared.loadPlayer.currentVideo.song.coverUrls!.first!) +// item.reviewImage = URL(string: MP_PlayerManager.shared.loadPlayer.currentVideo.song.reviewUrls!.first!) +// item.title = MP_PlayerManager.shared.loadPlayer.currentVideo.song.title +// item.longBylineText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.longBylineText +// item.lengthText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.lengthText +// item.shortBylineText = MP_PlayerManager.shared.loadPlayer.currentVideo.song.shortBylineText +// item.lyrics = MP_PlayerManager.shared.loadPlayer.currentVideo.lyrics +// item.videoId = MP_PlayerManager.shared.loadPlayer.currentVideo.song.videoId +// item.relatedID = MP_PlayerManager.shared.loadPlayer.currentVideo.song.relatedID +// +// MPPositive_DownloadItemModel.save() +// DispatchQueue.main.async { +// MP_PlayerManager.shared.loadPlayer.currentVideo.reloadCollectionAndDownLoad() +// self?.loadBtn.setBackgroundImage(UIImage(named: "Song_Loaded'logo"), for: .normal) +// self?.loadBtn.setImage(UIImage(named: ""), for: .normal) +// } +// +// self?.loadView.removeFromSuperview() +// case .failure(let error): +// print("Download failed with error: \(error)") +// self?.loadView.removeFromSuperview() +// DispatchQueue.main.async { +// self?.loadBtn.setBackgroundImage(UIImage(named: "Song_Unload'logo"), for: .normal) +// self?.loadBtn.setImage(UIImage(named: ""), for: .normal) +// } +// MP_HUD.text("Download timed out, please download again", delay: 1.5, completion: nil) +// } +// }) +// } +// } +// } +// +// } +// // 添加圆形进度条 + + private func addCircularProgressBar(over button: UIButton) { + loadView.removeFromSuperview() // 移除先前的进度视图(如果有) loadView = CircularProgressView(frame: button.bounds) @@ -238,4 +343,6 @@ class MPPositive_PlayerCoverView: UIView { make.width.height.equalTo(button) } } + + }