From 29677954249cb830f64dc2136f73398b31973f41 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 23 Apr 2023 20:40:31 +0400 Subject: [PATCH] Maybe fix bulk photo upload --- .../FetchPhotoLibraryImageResource.swift | 94 ++++++++++--------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/submodules/LocalMediaResources/Sources/FetchPhotoLibraryImageResource.swift b/submodules/LocalMediaResources/Sources/FetchPhotoLibraryImageResource.swift index e623472588..3ee6571835 100644 --- a/submodules/LocalMediaResources/Sources/FetchPhotoLibraryImageResource.swift +++ b/submodules/LocalMediaResources/Sources/FetchPhotoLibraryImageResource.swift @@ -82,6 +82,9 @@ extension UIImage.Orientation { } } +private let fetchPhotoWorkers = ThreadPool(threadCount: 3, threadPriority: 0.2) +private let fetchPhotoQueue = ThreadPoolQueue(threadPool: fetchPhotoWorkers) + public func fetchPhotoLibraryResource(localIdentifier: String) -> Signal { return Signal { subscriber in let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil) @@ -102,56 +105,61 @@ public func fetchPhotoLibraryResource(localIdentifier: String) -> Signal Void in - Queue.concurrentDefaultQueue().async { - requestId.with { current -> Void in - if !current.invalidated { - current.id = nil - current.invalidated = true + fetchPhotoQueue.addTask(ThreadPoolTask({ _ in + let semaphore = DispatchSemaphore(value: 0) + let requestIdValue = PHImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: option, resultHandler: { (image, info) -> Void in + Queue.concurrentDefaultQueue().async { + requestId.with { current -> Void in + if !current.invalidated { + current.id = nil + current.invalidated = true + } } - } - if let image = image { - if let info = info, let degraded = info[PHImageResultIsDegradedKey], (degraded as AnyObject).boolValue!{ + if let image = image { + if let info = info, let degraded = info[PHImageResultIsDegradedKey], (degraded as AnyObject).boolValue!{ + if !madeProgress.swap(true) { + //subscriber.putNext(.reset) + } + } else { +#if DEBUG + print("load completion \((CACurrentMediaTime() - startTime) * 1000.0) ms") +#endif + + _ = madeProgress.swap(true) + + let scale = min(1.0, min(size.width / max(1.0, image.size.width), size.height / max(1.0, image.size.height))) + let scaledSize = CGSize(width: floor(image.size.width * scale), height: floor(image.size.height * scale)) + let scaledImage = resizedImage(image, for: scaledSize) + +#if DEBUG + print("scaled completion \((CACurrentMediaTime() - startTime) * 1000.0) ms") +#endif + + if let scaledImage = scaledImage, let data = compressImageToJPEG(scaledImage, quality: 0.6) { +#if DEBUG + print("compression completion \((CACurrentMediaTime() - startTime) * 1000.0) ms") +#endif + subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< Int64(data.count), complete: true)) + subscriber.putCompletion() + } else { + subscriber.putCompletion() + } + } + } else { if !madeProgress.swap(true) { //subscriber.putNext(.reset) } - } else { - #if DEBUG - print("load completion \((CACurrentMediaTime() - startTime) * 1000.0) ms") - #endif - - _ = madeProgress.swap(true) - - let scale = min(1.0, min(size.width / max(1.0, image.size.width), size.height / max(1.0, image.size.height))) - let scaledSize = CGSize(width: floor(image.size.width * scale), height: floor(image.size.height * scale)) - let scaledImage = resizedImage(image, for: scaledSize) - - #if DEBUG - print("scaled completion \((CACurrentMediaTime() - startTime) * 1000.0) ms") - #endif - - if let scaledImage = scaledImage, let data = compressImageToJPEG(scaledImage, quality: 0.6) { - #if DEBUG - print("compression completion \((CACurrentMediaTime() - startTime) * 1000.0) ms") - #endif - subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< Int64(data.count), complete: true)) - subscriber.putCompletion() - } else { - subscriber.putCompletion() - } - } - } else { - if !madeProgress.swap(true) { - //subscriber.putNext(.reset) } + semaphore.signal() + } + }) + requestId.with { current -> Void in + if !current.invalidated { + current.id = requestIdValue } } - }) - requestId.with { current -> Void in - if !current.invalidated { - current.id = requestIdValue - } - } + semaphore.wait() + })) } else { subscriber.putNext(.reset) }