|
@@ -1,566 +0,0 @@
|
|
|
-//
|
|
|
-// PQPhotoMaterialController.swift
|
|
|
-// PQSpeed
|
|
|
-//
|
|
|
-// Created by SanW on 2021/4/26.
|
|
|
-// Copyright © 2021 BytesFlow. All rights reserved.
|
|
|
-//
|
|
|
-
|
|
|
-import Photos
|
|
|
-import UIKit
|
|
|
-import BFCommonKit
|
|
|
-
|
|
|
-class PQPhotoMaterialController: PQBaseViewController {
|
|
|
- // 是否显示素材标识
|
|
|
- var isShowMediaTag: Bool = true
|
|
|
- // 是否是已经添加过的素材
|
|
|
- var isAdded: Bool = false
|
|
|
- // 默认图片时长
|
|
|
- var imageDuration: Float64 = 2.0
|
|
|
- // 已选图片时长
|
|
|
- var selectedImageDataCount: Int = 0
|
|
|
- var itemSpacing: CGFloat = cDefaultMargin / 2 // 间隔
|
|
|
- var itemSize = CGSize(width: (cScreenWidth - cDefaultMargin) / 3, height: (cScreenWidth - cDefaultMargin) / 3) // cell 大小
|
|
|
- var previousPreheatRect = CGRect.zero
|
|
|
-
|
|
|
- var allPhotos: PHFetchResult<PHAsset> = PHFetchResult<PHAsset>.init() // 所有的图片
|
|
|
- var photoData: [PQEditVisionTrackMaterialsModel] = Array<PQEditVisionTrackMaterialsModel>.init() // 相册数据
|
|
|
- // 选中的相册数据
|
|
|
- var selectedPhotoData: [PQEditVisionTrackMaterialsModel] = Array<PQEditVisionTrackMaterialsModel>.init()
|
|
|
- // 选中的总时长
|
|
|
- var selectedTotalDuration: Float64 = 0
|
|
|
-
|
|
|
- var selectedMaterialHandle: ((_ currentMaterialData: PQEditVisionTrackMaterialsModel?, _ selectedPhotoData: [PQEditVisionTrackMaterialsModel], _ selectedTotalDuration: Float64, _ imageCount: Int) -> Void)? // 选中/取消选中的回调
|
|
|
- var detailMaterialHandle: ((_ indexPath: IndexPath, _ currentMaterialData: PQEditVisionTrackMaterialsModel?) -> Void)? // 点击详情
|
|
|
- /// 滑动的回调
|
|
|
- var scrollViewDidScroll: ((_ contentOffset: CGPoint) -> Void)?
|
|
|
- /// 空白页面点击的回调
|
|
|
- var emptyRefreshHandle: ((_ msgType: material_msgType) -> Void)?
|
|
|
- var msgType: material_msgType = .all { // 默认类型
|
|
|
- didSet {
|
|
|
- photoData.removeAll()
|
|
|
- allPhotos = PHFetchResult<PHAsset>.init()
|
|
|
- photoCollectionView.setContentOffset(CGPoint.zero, animated: false)
|
|
|
- photoCollectionView.reloadData()
|
|
|
- loadLocalData()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- var assetCollection: PHAssetCollection? // 相簿
|
|
|
- lazy var imageManager: PHCachingImageManager = { // 图库缓存管理
|
|
|
- (PHCachingImageManager.default() as? PHCachingImageManager) ?? PHCachingImageManager()
|
|
|
- }()
|
|
|
-
|
|
|
- lazy var photoFlowLayout: UICollectionViewFlowLayout = {
|
|
|
- let photoFlowLayout = UICollectionViewFlowLayout()
|
|
|
- photoFlowLayout.sectionInset = UIEdgeInsets.zero
|
|
|
- photoFlowLayout.minimumLineSpacing = itemSpacing
|
|
|
- photoFlowLayout.minimumInteritemSpacing = itemSpacing
|
|
|
- photoFlowLayout.scrollDirection = .vertical
|
|
|
- photoFlowLayout.itemSize = itemSize
|
|
|
- return photoFlowLayout
|
|
|
- }()
|
|
|
-
|
|
|
- lazy var photoCollectionView: UICollectionView = {
|
|
|
- let photoCollectionView = UICollectionView(frame: CGRect(x: itemSpacing, y: 0, width: view.frame.width, height: view.frame.height), collectionViewLayout: photoFlowLayout)
|
|
|
- photoCollectionView.register(PQChoseMaterialCell.self, forCellWithReuseIdentifier: String(describing: PQChoseMaterialCell.self))
|
|
|
- photoCollectionView.showsVerticalScrollIndicator = false
|
|
|
- photoCollectionView.showsHorizontalScrollIndicator = false
|
|
|
- photoCollectionView.delegate = self
|
|
|
- photoCollectionView.dataSource = self
|
|
|
- photoCollectionView.backgroundColor = UIColor.clear
|
|
|
- if #available(iOS 11.0, *) {
|
|
|
- photoCollectionView.contentInsetAdjustmentBehavior = .never
|
|
|
- } else {
|
|
|
- automaticallyAdjustsScrollViewInsets = false
|
|
|
- }
|
|
|
- return photoCollectionView
|
|
|
- }()
|
|
|
-
|
|
|
- var anthorEmptyData: PQEmptyModel = {
|
|
|
- let anthorEmptyData = PQEmptyModel()
|
|
|
- anthorEmptyData.title = "挑选相册素材"
|
|
|
- anthorEmptyData.summary = "要挑选相册素材,请先授予相册使用权限"
|
|
|
- anthorEmptyData.emptyImage = "icon_authorError"
|
|
|
- anthorEmptyData.isRefreshHidden = false
|
|
|
- anthorEmptyData.refreshBgColor = UIColor.hexColor(hexadecimal: PQBFConfig.shared.styleColor.rawValue)
|
|
|
- return anthorEmptyData
|
|
|
- }()
|
|
|
-
|
|
|
- var emptyData: PQEmptyModel = {
|
|
|
- let emptyData = PQEmptyModel()
|
|
|
- emptyData.title = "此相册中什么都没有"
|
|
|
- emptyData.isRefreshHidden = false
|
|
|
- emptyData.refreshTitle = NSMutableAttributedString(string: "刷新")
|
|
|
- emptyData.refreshBgColor = UIColor.hexColor(hexadecimal: PQBFConfig.shared.styleColor.rawValue)
|
|
|
- emptyData.emptyImage = "material_empty"
|
|
|
- return emptyData
|
|
|
- }()
|
|
|
-
|
|
|
- lazy var emptyRemindView: PQEmptyRemindView = {
|
|
|
- let emptyRemindView = PQEmptyRemindView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
|
|
|
- emptyRemindView.isHidden = true
|
|
|
- photoCollectionView.addSubview(emptyRemindView)
|
|
|
- emptyRemindView.backgroundColor = PQBFConfig.shared.styleBackGroundColor
|
|
|
- emptyRemindView.fullRefreshBloc = { [weak self] _, _ in
|
|
|
- if emptyRemindView.refreshBtn.currentTitle == "授予权限" {
|
|
|
- openAppSetting()
|
|
|
- } else if emptyRemindView.refreshBtn.currentAttributedTitle == NSMutableAttributedString(string: "刷新") {
|
|
|
- self?.loadLocalData()
|
|
|
- } else if self?.emptyRefreshHandle != nil {
|
|
|
- self?.emptyRefreshHandle!(self?.msgType ?? .all)
|
|
|
- }
|
|
|
- }
|
|
|
- emptyRemindView.remindLab.textColor = UIColor.hexColor(hexadecimal: "#999999")
|
|
|
- emptyRemindView.refreshBtn.addCorner(corner: 4)
|
|
|
- return emptyRemindView
|
|
|
- }()
|
|
|
-
|
|
|
- override func viewDidLoad() {
|
|
|
- super.viewDidLoad()
|
|
|
- view.addSubview(photoCollectionView)
|
|
|
- hiddenNavigation()
|
|
|
- view.backgroundColor = PQBFConfig.shared.styleBackGroundColor
|
|
|
- }
|
|
|
-
|
|
|
- /// <#Description#>
|
|
|
- /// - Returns: <#description#>
|
|
|
- func loadLocalData() {
|
|
|
- let authStatus = PHPhotoLibrary.authorizationStatus()
|
|
|
- if authStatus == .notDetermined {
|
|
|
- // 第一次触发授权 alert
|
|
|
- PHPhotoLibrary.requestAuthorization { [weak self] (status: PHAuthorizationStatus) -> Void in
|
|
|
- if status == .authorized {
|
|
|
- if (self?.allPhotos == nil) || (self?.allPhotos.count ?? 0) <= 0 {
|
|
|
- self?.loadPhotoData()
|
|
|
- }
|
|
|
- }
|
|
|
- DispatchQueue.main.async { [weak self] in
|
|
|
- self?.showEmpthView()
|
|
|
- }
|
|
|
- }
|
|
|
- } else if authStatus == .authorized {
|
|
|
- BFLog(message: "授权成功,开始请求相册数据-\(allPhotos)")
|
|
|
-// if allPhotos.count <= 0 {
|
|
|
- loadPhotoData()
|
|
|
-// }
|
|
|
- } else {
|
|
|
- showEmpthView()
|
|
|
- }
|
|
|
- PHPhotoLibrary.shared().register(self)
|
|
|
- }
|
|
|
-
|
|
|
- /// 加载图库数据
|
|
|
- /// - Returns: <#description#>
|
|
|
- func loadPhotoData() {
|
|
|
- DispatchQueue.main.async { [weak self] in
|
|
|
- PQLoadingHUB.shared.showHUB(superView: self!.view, isVerticality: false)
|
|
|
- }
|
|
|
- DispatchQueue.global().async { [weak self] in
|
|
|
- self?.allPhotos = self?.assetCollection != nil ? PHAsset.fetchAssets(in: (self?.assetCollection)!, options: self?.fetchOptions()) : PHAsset.fetchAssets(with: self?.fetchOptions())
|
|
|
- DispatchQueue.main.async { [weak self] in
|
|
|
- if self?.view != nil {
|
|
|
- PQLoadingHUB.shared.dismissHUB(superView: self!.view)
|
|
|
- }
|
|
|
- self?.photoCollectionView.reloadData()
|
|
|
- self?.showEmpthView()
|
|
|
-// self?.updateCachedAssets()
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// 获取option
|
|
|
- /// - Returns: <#description#>
|
|
|
- func fetchOptions() -> PHFetchOptions {
|
|
|
- if msgType != .all {
|
|
|
- let fetchOptions = PHFetchOptions()
|
|
|
- fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
|
|
|
- fetchOptions.predicate = NSPredicate(format: "mediaType = %d", msgType == .video ? PHAssetMediaType.video.rawValue : PHAssetMediaType.image.rawValue)
|
|
|
- return fetchOptions
|
|
|
- } else {
|
|
|
- return creaFetchOptions
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// 展示空页面
|
|
|
- func showEmpthView() {
|
|
|
- emptyRemindView.isHidden = allPhotos.count > 0
|
|
|
- if !emptyRemindView.isHidden {
|
|
|
- let authStatus = PHPhotoLibrary.authorizationStatus()
|
|
|
- if authStatus == .denied {
|
|
|
- emptyRemindView.emptyData = anthorEmptyData
|
|
|
- emptyRemindView.refreshBtn.setTitle("授予权限", for: .normal)
|
|
|
- } else {
|
|
|
- switch msgType {
|
|
|
- case .video:
|
|
|
- emptyData.title = "此相册中没有视频"
|
|
|
- emptyData.emptyImage = "stuckPoint_video_empty"
|
|
|
- emptyData.refreshTitle = NSMutableAttributedString(string: "去选照片")
|
|
|
- case .image:
|
|
|
- emptyData.title = "此相册中没有照片"
|
|
|
- emptyData.emptyImage = "stuckPoint_image_empty"
|
|
|
- emptyData.refreshTitle = NSMutableAttributedString(string: "去选视频")
|
|
|
- default:
|
|
|
- emptyData.title = "此相册中什么都没有"
|
|
|
- emptyData.emptyImage = "material_empty"
|
|
|
- emptyData.refreshTitle = NSMutableAttributedString(string: "刷新")
|
|
|
- }
|
|
|
- emptyData.summary = nil
|
|
|
- emptyRemindView.emptyData = emptyData
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// 更新frame
|
|
|
- /// - Parameter newFrame: <#newFrame description#>
|
|
|
- /// - Returns: <#description#>
|
|
|
- func updateFrame(newFrame: CGRect, isAnimate: Bool = false, isScroll _: Bool = false) {
|
|
|
- if isAnimate {
|
|
|
- UIView.animate(withDuration: 0.5, delay: 0, options: .allowUserInteraction) { [weak self] in
|
|
|
- // 调整位置
|
|
|
- self?.view.frame = newFrame
|
|
|
- self?.photoCollectionView.frame = self?.view.bounds ?? CGRect.zero
|
|
|
- self?.emptyRemindView.frame = self?.photoCollectionView.bounds ?? CGRect.zero
|
|
|
- } completion: { _ in
|
|
|
- }
|
|
|
- } else {
|
|
|
- view.frame = newFrame
|
|
|
- photoCollectionView.frame = view.bounds
|
|
|
- emptyRemindView.frame = photoCollectionView.bounds
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension PQPhotoMaterialController: UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate {
|
|
|
- func collectionView(_: UICollectionView, numberOfItemsInSection _: Int) -> Int {
|
|
|
- return allPhotos.count
|
|
|
- }
|
|
|
-
|
|
|
- func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
|
|
- let cell = PQChoseMaterialCell.choseMaterialCell(collectionView: collectionView, indexPath: indexPath)
|
|
|
- cell.isShowMediaTag = isShowMediaTag
|
|
|
- cell.isAdded = isAdded
|
|
|
- if photoData.count <= indexPath.item {
|
|
|
- let itemData: PQEditVisionTrackMaterialsModel!
|
|
|
- let asset = allPhotos.object(at: indexPath.item)
|
|
|
- let selectedItem = selectedPhotoData.first { (item) -> Bool in
|
|
|
- item.asset == asset
|
|
|
- }
|
|
|
- if selectedItem != nil {
|
|
|
- itemData = selectedItem
|
|
|
- } else {
|
|
|
- itemData = PQEditVisionTrackMaterialsModel()
|
|
|
- itemData.downloadState = .compelte
|
|
|
- itemData.asset = asset
|
|
|
- itemData.height = Float(itemData.asset?.pixelHeight ?? 0)
|
|
|
- itemData.width = Float(itemData.asset?.pixelWidth ?? 0)
|
|
|
- itemData.type = asset.mediaType == .image ? StickerType.IMAGE.rawValue : StickerType.VIDEO.rawValue
|
|
|
- itemData.volumeGain = asset.mediaType == .image ? 0 : 100
|
|
|
- itemData.duration = asset.mediaType == .image ? imageDuration : asset.duration
|
|
|
- itemData.out = itemData.duration
|
|
|
- }
|
|
|
- photoData.append(itemData)
|
|
|
- }
|
|
|
- if photoData.count > indexPath.item {
|
|
|
- let itemData = photoData[indexPath.item]
|
|
|
- cell.materialData = itemData
|
|
|
- cell.representedAssetIdentifier = itemData.asset?.localIdentifier
|
|
|
- if itemData.coverImageUI == nil, itemData.asset != nil {
|
|
|
- imageManager.requestImage(for: itemData.asset!, targetSize: itemSize, contentMode: .aspectFill, options: nil) { image, info in
|
|
|
- if info?.keys.contains("PHImageResultIsDegradedKey") ?? false, "\(info?["PHImageResultIsDegradedKey"] ?? "0")" == "0", cell.representedAssetIdentifier == itemData.asset?.localIdentifier {
|
|
|
- if image != nil {
|
|
|
- itemData.coverImageUI = image
|
|
|
- cell.materialImageView.image = image
|
|
|
- } else if image == nil, info?.keys.contains("PHImageResultIsInCloudKey") ?? false {
|
|
|
- let option = PHImageRequestOptions()
|
|
|
- option.isNetworkAccessAllowed = true
|
|
|
- option.resizeMode = .fast
|
|
|
- self.imageManager.requestImageData(for: itemData.asset!, options: option) { data, _, _, _ in
|
|
|
- if data != nil {
|
|
|
- let image = UIImage(data: data!)
|
|
|
- itemData.coverImageUI = image
|
|
|
- cell.materialImageView.image = image
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- cell.materialData = PQEditVisionTrackMaterialsModel()
|
|
|
- }
|
|
|
- cell.materialClicHandle = { [weak self] _, materialData in
|
|
|
- if (self?.photoData.count ?? 0) > indexPath.item {
|
|
|
- // 处理相册选择
|
|
|
- self?.dealWithSelectedMaterial(indexPath: indexPath, materialData: materialData)
|
|
|
- } else {
|
|
|
-// collectionView.reloadData()
|
|
|
- }
|
|
|
- }
|
|
|
- return cell
|
|
|
- }
|
|
|
-
|
|
|
- func collectionView(_: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
|
|
- if photoData.count <= indexPath.item {
|
|
|
-// collectionView.reloadData()
|
|
|
- return
|
|
|
- }
|
|
|
- if detailMaterialHandle != nil {
|
|
|
- detailMaterialHandle!(indexPath, photoData[indexPath.item])
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func collectionView(_: UICollectionView, willDisplay _: UICollectionViewCell, forItemAt _: IndexPath) {
|
|
|
- if !isAdded, !isShowMediaTag {
|
|
|
-// // 卡点音乐素材选择曝光上报
|
|
|
-// PQEventTrackViewModel.baseReportUpload(businessType: .bt_windowView, objectType: .ot_view_selectSyncedUpMaterial, pageSource: .sp_stuck_selectMaterial, extParams: nil, remindmsg: "卡点音乐素材选择曝光上报")
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// 点击选择的回调
|
|
|
- /// - Parameter materialData: <#materialData description#>
|
|
|
- /// - Returns: description
|
|
|
- func dealWithSelectedMaterial(indexPath: IndexPath?, materialData: PQEditVisionTrackMaterialsModel?) {
|
|
|
- let ratio = (materialData?.width ?? 0) / (materialData?.height ?? 1)
|
|
|
- if ratio < 0.4 || ratio > 4.2 {
|
|
|
- cShowHUB(superView: nil, msg: "暂不支持该比例的素材")
|
|
|
- return
|
|
|
- }
|
|
|
- if materialData != nil, indexPath != nil {
|
|
|
- materialData?.isSelected = !(materialData?.isSelected ?? false)
|
|
|
- if materialData?.isSelected ?? false {
|
|
|
- selectedPhotoData.append(materialData!)
|
|
|
- if materialData?.type == StickerType.IMAGE.rawValue {
|
|
|
- selectedImageDataCount = selectedImageDataCount + 1
|
|
|
- }
|
|
|
- materialData?.selectedIndex = selectedPhotoData.count
|
|
|
- if materialData?.asset != nil && materialData?.asset?.mediaType != .video && (materialData?.coverImageUI == nil || (materialData?.locationPath.count ?? 0) <= 0) {
|
|
|
- PQPHAssetVideoParaseUtil.requestAssetOringinImage(asset: (materialData?.asset)!) { [weak self] _, data, image, _ in
|
|
|
- if image == nil {
|
|
|
- BFLog(message: "图片数据为空!!!!!")
|
|
|
- }
|
|
|
- // 1,图片,gif的原文件数据,和视频的封面
|
|
|
- var newImage: UIImage?
|
|
|
- if image != nil {
|
|
|
- newImage = UIImage.nx_fixOrientation(image, isFront: false).nx_scaleWithMaxLength(maxLength: 1920)
|
|
|
- }
|
|
|
- materialData?.coverImageUI = newImage
|
|
|
- materialData?.originalData = data
|
|
|
- let timeInterval: TimeInterval = Date().timeIntervalSince1970
|
|
|
- let imageCacheName = "images_\(timeInterval)"
|
|
|
- let imageCachePath = downloadImagesDirectory + imageCacheName
|
|
|
- if !directoryIsExists(dicPath: downloadImagesDirectory) {
|
|
|
- BFLog(message: "文件夹不存在 \(downloadImagesDirectory)")
|
|
|
- createDirectory(path: downloadImagesDirectory)
|
|
|
- }
|
|
|
- // 创建目录
|
|
|
- if newImage != nil {
|
|
|
- try? newImage?.pngData()?.write(to: URL(fileURLWithPath: imageCachePath))
|
|
|
- } else {
|
|
|
- try? data?.write(to: URL(fileURLWithPath: imageCachePath))
|
|
|
- }
|
|
|
- if materialData?.asset?.mediaType != .video, newImage != nil || data != nil {
|
|
|
- materialData?.locationPath = imageCachePath.replacingOccurrences(of: documensDirectory, with: "")
|
|
|
- }
|
|
|
- materialData?.width = Float(materialData?.asset?.pixelWidth ?? 0)
|
|
|
- materialData?.height = Float(materialData?.asset?.pixelHeight ?? 0)
|
|
|
- if self?.selectedMaterialHandle != nil {
|
|
|
- self?.selectedTotalDuration = (self?.selectedTotalDuration ?? 0) + (materialData?.duration ?? 0.0)
|
|
|
- if indexPath != nil {
|
|
|
- self?.photoCollectionView.reloadItems(at: [indexPath!])
|
|
|
- }
|
|
|
- // 处理已选择的数据
|
|
|
- self?.dealWithSelectedData(materialData: materialData)
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- selectedTotalDuration = selectedTotalDuration + (materialData?.duration ?? 0.0)
|
|
|
- if indexPath != nil {
|
|
|
- photoCollectionView.reloadItems(at: [indexPath!])
|
|
|
- }
|
|
|
- // 处理已选择的数据
|
|
|
- dealWithSelectedData(materialData: materialData)
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 处理取消选择数据
|
|
|
- deSeletedMaterialData(materialData: materialData)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// 处理取消选择数据
|
|
|
- /// - Parameter materialData: <#materialData description#>
|
|
|
- /// - Returns: <#description#>
|
|
|
- func deSeletedMaterialData(materialData: PQEditVisionTrackMaterialsModel?) {
|
|
|
- selectedPhotoData.removeAll(where: { (item) -> Bool in
|
|
|
- item.asset == materialData?.asset
|
|
|
- })
|
|
|
- for item in photoData {
|
|
|
- if item.isSelected, item.selectedIndex > (materialData?.selectedIndex ?? 1) {
|
|
|
- item.selectedIndex = item.selectedIndex - 1
|
|
|
- }
|
|
|
- }
|
|
|
- if materialData?.type == StickerType.IMAGE.rawValue {
|
|
|
- selectedImageDataCount = selectedImageDataCount - 1
|
|
|
- }
|
|
|
- selectedTotalDuration = selectedTotalDuration - (materialData?.duration ?? 0.0)
|
|
|
- photoCollectionView.reloadData()
|
|
|
- // 处理已选择的数据
|
|
|
- dealWithSelectedData(materialData: materialData)
|
|
|
- }
|
|
|
-
|
|
|
- /// 处理已选择的数据
|
|
|
- /// - Parameters:
|
|
|
- /// - indexPath: <#indexPath description#>
|
|
|
- /// - materialData: <#materialData description#>
|
|
|
- /// - Returns: <#description#>
|
|
|
- func dealWithSelectedData(materialData: PQEditVisionTrackMaterialsModel?) {
|
|
|
-// if materialData?.asset != nil && materialData?.asset?.mediaType == .video && (materialData?.locationPath == nil || (materialData?.locationPath.count ?? 0) <= 0) {
|
|
|
-// PQPHAssetVideoParaseUtil.parasToAVAsset(phAsset: (materialData?.asset)!) { [weak self] avAsset, _, _, _ in
|
|
|
-// if avAsset is AVURLAsset {
|
|
|
-// materialData?.locationPath = (avAsset as? AVURLAsset)?.url.absoluteString.replacingOccurrences(of: "file:///", with: "") ?? ""
|
|
|
-// if self?.selectedMaterialHandle != nil {
|
|
|
-// DispatchQueue.main.async {
|
|
|
-// self?.selectedMaterialHandle!(materialData, self?.selectedPhotoData ?? [], self?.selectedTotalDuration ?? 0)
|
|
|
-// }
|
|
|
-// }
|
|
|
-// } else if self?.selectedMaterialHandle != nil {
|
|
|
-// DispatchQueue.main.async {
|
|
|
-// self?.selectedMaterialHandle!(materialData, self?.selectedPhotoData ?? [], self?.selectedTotalDuration ?? 0)
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// } else
|
|
|
- if selectedMaterialHandle != nil {
|
|
|
- selectedMaterialHandle!(materialData, selectedPhotoData, selectedTotalDuration, selectedImageDataCount)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// <#Description#>
|
|
|
- /// - Parameter scrollView: <#scrollView description#>
|
|
|
- func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
|
- if scrollViewDidScroll != nil {
|
|
|
- scrollViewDidScroll!(scrollView.contentOffset)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// 更新数据
|
|
|
- /// - Parameter isMaterialSelected:
|
|
|
- /// - Parameter materialData: <#materialData description#>
|
|
|
- /// - Returns: <#description#>
|
|
|
- func updateMaterials(isSelected: Bool, materialData: PQEditVisionTrackMaterialsModel?) {
|
|
|
- let photoIndexPath = selectedPhotoData.firstIndex { (item) -> Bool in
|
|
|
- materialData?.asset == item.asset
|
|
|
- }
|
|
|
- materialData?.isSelected = isSelected
|
|
|
- if isSelected {
|
|
|
- if photoIndexPath == nil {
|
|
|
- selectedPhotoData.append(materialData!)
|
|
|
- }
|
|
|
- materialData?.selectedIndex = selectedPhotoData.count
|
|
|
- selectedTotalDuration = selectedTotalDuration + (materialData?.duration ?? 0.0)
|
|
|
- } else if photoIndexPath != nil {
|
|
|
- selectedPhotoData.remove(at: photoIndexPath ?? 0)
|
|
|
- for item in selectedPhotoData {
|
|
|
- if item.isSelected, item.selectedIndex > (materialData?.selectedIndex ?? 1) {
|
|
|
- item.selectedIndex = item.selectedIndex - 1
|
|
|
- }
|
|
|
- }
|
|
|
- selectedTotalDuration = selectedTotalDuration - (materialData?.duration ?? 0.0)
|
|
|
- }
|
|
|
- photoCollectionView.reloadData()
|
|
|
- if selectedMaterialHandle != nil {
|
|
|
- selectedMaterialHandle!(materialData, selectedPhotoData, selectedTotalDuration, selectedImageDataCount)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension PQPhotoMaterialController: PHPhotoLibraryChangeObserver {
|
|
|
- func photoLibraryDidChange(_ changeInstance: PHChange) {
|
|
|
- DispatchQueue.main.sync {
|
|
|
- // Check each of the three top-level fetches for changes.
|
|
|
- guard let collectionChanges = changeInstance.changeDetails(for: allPhotos)
|
|
|
- else {
|
|
|
- return
|
|
|
- }
|
|
|
- if !collectionChanges.hasIncrementalChanges || collectionChanges.hasMoves {
|
|
|
- return
|
|
|
- }
|
|
|
- // Update the cached fetch result.
|
|
|
- allPhotos = collectionChanges.fetchResultAfterChanges
|
|
|
- photoData.removeAll()
|
|
|
- photoCollectionView.reloadData()
|
|
|
-// photoCollectionView.setContentOffset(CGPoint.zero, animated: false)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private func resetCachedAssets() {
|
|
|
- imageManager.stopCachingImagesForAllAssets()
|
|
|
- previousPreheatRect = .zero
|
|
|
- }
|
|
|
-
|
|
|
- private func updateCachedAssets() {
|
|
|
- if allPhotos.count <= 0 {
|
|
|
- return
|
|
|
- }
|
|
|
- guard isViewLoaded, view.window != nil else { return }
|
|
|
- let visibleRect = CGRect(origin: photoCollectionView.contentOffset, size: photoCollectionView.bounds.size)
|
|
|
- let preheatRect = visibleRect.insetBy(dx: 0, dy: -0.5 * visibleRect.height)
|
|
|
- let delta = abs(preheatRect.midY - previousPreheatRect.midY)
|
|
|
- guard delta > view.bounds.height / 3 else { return }
|
|
|
- let (addedRects, removedRects) = differencesBetweenRects(previousPreheatRect, preheatRect)
|
|
|
- let addedAssets: [PHAsset]? = addedRects
|
|
|
- .flatMap { rect in photoCollectionView.indexPathsForElements(in: rect) }
|
|
|
- .map { indexPath in
|
|
|
- if indexPath.item < allPhotos.count {
|
|
|
- return allPhotos.object(at: indexPath.item)
|
|
|
- } else {
|
|
|
- return PHAsset()
|
|
|
- }
|
|
|
- }
|
|
|
- let removedAssets: [PHAsset]? = removedRects
|
|
|
- .flatMap { rect in photoCollectionView.indexPathsForElements(in: rect) }
|
|
|
- .map { indexPath in
|
|
|
- if indexPath.item < allPhotos.count {
|
|
|
- return allPhotos.object(at: indexPath.item)
|
|
|
- } else {
|
|
|
- return PHAsset()
|
|
|
- }
|
|
|
- }
|
|
|
- if addedAssets != nil, (addedAssets?.count ?? 0) > 0 {
|
|
|
- imageManager.startCachingImages(for: addedAssets!,
|
|
|
- targetSize: itemSize, contentMode: .aspectFill, options: nil)
|
|
|
- }
|
|
|
- if removedAssets != nil, (removedAssets?.count ?? 0) > 0 {
|
|
|
- imageManager.stopCachingImages(for: removedAssets!,
|
|
|
- targetSize: itemSize, contentMode: .aspectFill, options: nil)
|
|
|
- }
|
|
|
- previousPreheatRect = preheatRect
|
|
|
- }
|
|
|
-
|
|
|
- private func differencesBetweenRects(_ old: CGRect, _ new: CGRect) -> (added: [CGRect], removed: [CGRect]) {
|
|
|
- if old.intersects(new) {
|
|
|
- var added = [CGRect]()
|
|
|
- if new.maxY > old.maxY {
|
|
|
- added += [CGRect(x: new.origin.x, y: old.maxY,
|
|
|
- width: new.width, height: new.maxY - old.maxY)]
|
|
|
- }
|
|
|
- if old.minY > new.minY {
|
|
|
- added += [CGRect(x: new.origin.x, y: new.minY,
|
|
|
- width: new.width, height: old.minY - new.minY)]
|
|
|
- }
|
|
|
- var removed = [CGRect]()
|
|
|
- if new.maxY < old.maxY {
|
|
|
- removed += [CGRect(x: new.origin.x, y: new.maxY,
|
|
|
- width: new.width, height: old.maxY - new.maxY)]
|
|
|
- }
|
|
|
- if old.minY < new.minY {
|
|
|
- removed += [CGRect(x: new.origin.x, y: old.minY,
|
|
|
- width: new.width, height: new.minY - old.minY)]
|
|
|
- }
|
|
|
- return (added, removed)
|
|
|
- } else {
|
|
|
- return ([new], [old])
|
|
|
- }
|
|
|
- }
|
|
|
-}
|