diff --git a/ConversationsClassic/AppCore/Actions/SharingActions.swift b/ConversationsClassic/AppCore/Actions/SharingActions.swift index 98d0578..7280298 100644 --- a/ConversationsClassic/AppCore/Actions/SharingActions.swift +++ b/ConversationsClassic/AppCore/Actions/SharingActions.swift @@ -14,7 +14,7 @@ enum SharingAction: Stateable { case setGalleryAccess(Bool) case fetchGallery case galleryFetched([SharingGalleryItem]) - case thumbnailUpdated(Data, String) + case thumbnailUpdated(data: Data, id: String) case cameraCaptured(media: Data, type: SharingCameraMediaType) case flushCameraCaptured diff --git a/ConversationsClassic/AppCore/Middlewares/SharingMiddleware.swift b/ConversationsClassic/AppCore/Middlewares/SharingMiddleware.swift index 88cfffa..3a8c1bb 100644 --- a/ConversationsClassic/AppCore/Middlewares/SharingMiddleware.swift +++ b/ConversationsClassic/AppCore/Middlewares/SharingMiddleware.swift @@ -69,26 +69,48 @@ final class SharingMiddleware { .eraseToAnyPublisher() case .sharingAction(.galleryFetched(let items)): - DispatchQueue.global(qos: .background).async { - // for item in items { - // switch item.type { - // case .photo: - // self.makePhotoThumbnail(assetId: PHAsset.fetchAssets(withLocalIdentifiers: [item.id], options: nil).firstObject!) { data in - // if let data { - // DispatchQueue.main.async { - // store.dispatch(.sharingAction(.thumbnailUpdated(data, item.id))) - // } - // } - // } - // - // case .video: - // self.fetchVideo(asset: PHAsset.fetchAssets(withLocalIdentifiers: [item.id], options: nil).firstObject!) { newItem in - // if let newItem { - // newItems.append(newItem) - // } - // } - // } - // } + DispatchQueue.global().async { + let ids = items + .filter { $0.thumbnail == nil } + .map { $0.id } + let assets = PHAsset.fetchAssets(withLocalIdentifiers: ids, options: nil) + assets.enumerateObjects { asset, _, _ in + if asset.mediaType == .image { + PHImageManager.default().requestImage( + for: asset, + targetSize: PHImageManagerMaximumSize, + contentMode: .aspectFill, + options: nil + ) { image, _ in + image?.scaleAndCropImage(toExampleSize: CGSize(width: Const.galleryGridSize, height: Const.galleryGridSize)) { image in + if let image { + let data = image.jpegData(compressionQuality: 1.0) ?? Data() + store.dispatch(.sharingAction(.thumbnailUpdated(data: data, id: asset.localIdentifier))) + } + } + } + } else if asset.mediaType == .video { + PHImageManager.default().requestAVAsset(forVideo: asset, options: nil) { avAsset, _, _ in + if let avAsset { + let imageGenerator = AVAssetImageGenerator(asset: avAsset) + imageGenerator.appliesPreferredTrackTransform = true + let time = CMTimeMake(value: 1, timescale: 2) + do { + let imageRef = try imageGenerator.copyCGImage(at: time, actualTime: nil) + let thumbnail = UIImage(cgImage: imageRef) + thumbnail.scaleAndCropImage(toExampleSize: CGSize(width: Const.galleryGridSize, height: Const.galleryGridSize)) { image in + if let image { + let data = image.jpegData(compressionQuality: 1.0) ?? Data() + store.dispatch(.sharingAction(.thumbnailUpdated(data: data, id: asset.localIdentifier))) + } + } + } catch { + print("Failed to create thumbnail image") + } + } + } + } + } } return Empty().eraseToAnyPublisher() @@ -97,156 +119,3 @@ final class SharingMiddleware { } } } - -private extension SharingMiddleware { - func makePhotoThumbnail(asset: PHAsset, completion: @escaping (Data?) -> Void) { - PHImageManager.default().requestImage( - for: asset, - targetSize: PHImageManagerMaximumSize, - contentMode: .aspectFill, - options: nil - ) { _, _ in - // guard let image = image?.scaleAndCropImage(toExampleSize: CGSize(width: Const.galleryGridSize, height: Const.galleryGridSize)) else { - // completion(nil) - // return - // } - // let data = image.jpegData(compressionQuality: 1.0) ?? Data() - // completion(.init(id: asset.localIdentifier, type: .photo, thumbnail: data)) - completion(.init(id: asset.localIdentifier, type: .photo, thumbnail: Data())) - } - } - - func fetchVideo(asset: PHAsset, completion: @escaping (SharingGalleryItem?) -> Void) { - PHImageManager.default().requestAVAsset(forVideo: asset, options: nil) { _, _, _ in - // if let avAsset { - // let imageGenerator = AVAssetImageGenerator(asset: avAsset) - // imageGenerator.appliesPreferredTrackTransform = true - // let time = CMTimeMake(value: 1, timescale: 2) - // do { - // let imageRef = try imageGenerator.copyCGImage(at: time, actualTime: nil) - // let thumbnail = UIImage(cgImage: imageRef) - // guard let image = thumbnail.scaleAndCropImage(toExampleSize: CGSize(width: Const.galleryGridSize, height: Const.galleryGridSize)) else { - // completion(nil) - // return - // } - // let data = image.jpegData(compressionQuality: 1.0) ?? Data() - // completion(.init(id: asset.localIdentifier, type: .video, thumbnail: data, duration: asset.duration.minAndSec)) - // } catch { - // print("Failed to create thumbnail image") - // completion(nil) - // } - // } else { - // completion(nil) - // } - completion(.init(id: asset.localIdentifier, type: .photo, thumbnail: Data())) - } - } -} - -// case .sharingAction(.fetchGallery): -// return Future { promise in -// DispatchQueue.global(qos: .background).async { -// let fetchOptions = PHFetchOptions() -// fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] -// let assets = PHAsset.fetchAssets(with: fetchOptions) -// -// let manager = PHImageManager.default() -// let option = PHImageRequestOptions() -// option.isSynchronous = true -// -// var items: [SharingGalleryItem] = [] -// let group = DispatchGroup() -// assets.enumerateObjects { asset, _, _ in -// if asset.mediaType == .image { -// group.enter() -// manager.requestImage( -// for: asset, -// targetSize: PHImageManagerMaximumSize, -// contentMode: .aspectFill, -// options: option -// ) { image, _ in -// if image != nil { -// items.append(.init(id: asset.localIdentifier, type: .photo)) -// group.leave() -// } -// } -// } else if asset.mediaType == .video { -// group.enter() -// manager.requestAVAsset(forVideo: asset, options: nil) { avAsset, _, _ in -// if avAsset != nil { -// items.append(.init(id: asset.localIdentifier, type: .video, duration: asset.duration.minAndSec)) -// group.leave() -// } -// } -// } -// } -// group.notify(queue: .main) { -// promise(.success(.sharingAction(.galleryFetched(items)))) -// } -// } -// } -// .eraseToAnyPublisher() -// -// case .sharingAction(.galleryFetched(let items)): -// return Future { promise in -// DispatchQueue.global(qos: .background).async { -// let ids = items -// .filter { $0.thumbnail == nil } -// .map { $0.id } -// let assets = PHAsset.fetchAssets(withLocalIdentifiers: ids, options: nil) -// -// var newItems: [SharingGalleryItem] = [] -// let group = DispatchGroup() -// -// assets.enumerateObjects { asset, _, _ in -// let manager = PHImageManager.default() -// group.enter() -// if asset.mediaType == .image { -// manager.requestImage( -// for: asset, -// targetSize: PHImageManagerMaximumSize, -// contentMode: .aspectFill, -// options: nil -// ) { image, _ in -// image?.scaleAndCropImage(toExampleSize: CGSize(width: Const.galleryGridSize, height: Const.galleryGridSize)) { image in -// if let image { -// let data = image.jpegData(compressionQuality: 1.0) ?? Data() -// newItems.append(.init(id: asset.localIdentifier, type: .photo, thumbnail: data)) -// } -// group.leave() -// } -// } -// } else if asset.mediaType == .video { -// manager.requestAVAsset(forVideo: asset, options: nil) { avAsset, _, _ in -// if let avAsset { -// let imageGenerator = AVAssetImageGenerator(asset: avAsset) -// imageGenerator.appliesPreferredTrackTransform = true -// let time = CMTimeMake(value: 1, timescale: 2) -// do { -// let imageRef = try imageGenerator.copyCGImage(at: time, actualTime: nil) -// let thumbnail = UIImage(cgImage: imageRef) -// thumbnail.scaleAndCropImage(toExampleSize: CGSize(width: Const.galleryGridSize, height: Const.galleryGridSize), completion: { image in -// if let image { -// let data = image.jpegData(compressionQuality: 1.0) ?? Data() -// newItems.append(.init(id: asset.localIdentifier, type: .video, thumbnail: data, duration: asset.duration.minAndSec)) -// } -// group.leave() -// }) -// } catch { -// print("Failed to create thumbnail image") -// group.leave() -// } -// } else { -// group.leave() -// } -// } -// } else { -// group.leave() -// } -// } -// group.notify(queue: .main) { -// promise(.success(.sharingAction(.thumbnailUpdated(newItems)))) -// } -// } -// } -// .eraseToAnyPublisher()