damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit d9f2317728e7152d6fce47ae75f8554bd209cd21
parent 4effaa432424e877f15fe7d50939d1e92ee711e9
Author: William Casarin <jb55@jb55.com>
Date:   Mon, 21 Oct 2024 09:44:10 -0700

Merge 'Maintain images preview as per the selection order' from 'github/pr/2595'

Swift Coder (2):
      Maintain images preview as per the selection order
      document

Diffstat:
Mdamus/Views/MediaPicker.swift | 49++++++++++++++++++++++++++++++++++++-------------
1 file changed, 36 insertions(+), 13 deletions(-)

diff --git a/damus/Views/MediaPicker.swift b/damus/Views/MediaPicker.swift @@ -20,7 +20,12 @@ struct MediaPicker: UIViewControllerRepresentable { final class Coordinator: NSObject, PHPickerViewControllerDelegate { - let parent: MediaPicker + var parent: MediaPicker + + // properties used for returning medias in the same order as picking + let dispatchGroup: DispatchGroup = DispatchGroup() + var orderIds: [String] = [] + var orderMap: [String: PreUploadedMedia] = [:] init(_ parent: MediaPicker) { self.parent = parent @@ -32,6 +37,11 @@ struct MediaPicker: UIViewControllerRepresentable { } for result in results { + + let orderId = result.assetIdentifier ?? UUID().uuidString + orderIds.append(orderId) + dispatchGroup.enter() + if result.itemProvider.hasItemConformingToTypeIdentifier(UTType.image.identifier) { result.itemProvider.loadItem(forTypeIdentifier: UTType.image.identifier, options: nil) { (item, error) in guard let url = item as? URL else { return } @@ -50,7 +60,7 @@ struct MediaPicker: UIViewControllerRepresentable { do { try imageData.write(to: destinationURL) Task { - await self.chooseMedia(.processed_image(destinationURL)) + await self.chooseMedia(.processed_image(destinationURL), orderId: orderId) } } catch { @@ -64,13 +74,13 @@ struct MediaPicker: UIViewControllerRepresentable { url: url, fallback: processImage, unprocessedEnum: {.unprocessed_image($0)}, - processedEnum: {.processed_image($0)} - ) + processedEnum: {.processed_image($0)}, + orderId: orderId) } else { // Media was taken from camera result.itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in if let image = image as? UIImage, error == nil { - self.chooseMedia(.uiimage(image)) + self.chooseMedia(.uiimage(image), orderId: orderId) } } } @@ -83,35 +93,48 @@ struct MediaPicker: UIViewControllerRepresentable { url: url, fallback: processVideo, unprocessedEnum: {.unprocessed_video($0)}, - processedEnum: {.processed_video($0)} + processedEnum: {.processed_video($0)}, orderId: orderId ) } } } + + dispatchGroup.notify(queue: .main) { [weak self] in + guard let self = self else { return } + var arrMedia: [PreUploadedMedia] = [] + for id in self.orderIds { + if let media = self.orderMap[id] { + arrMedia.append(media) + self.parent.onMediaPicked(media) + } + } + } } - private func chooseMedia(_ media: PreUploadedMedia) { - self.parent.onMediaPicked(media) + + private func chooseMedia(_ media: PreUploadedMedia, orderId: String) { self.parent.image_upload_confirm = true + self.orderMap[orderId] = media + self.dispatchGroup.leave() } - private func attemptAcquireResourceAndChooseMedia(url: URL, fallback: (URL) -> URL?, unprocessedEnum: (URL) -> PreUploadedMedia, processedEnum: (URL) -> PreUploadedMedia) { + private func attemptAcquireResourceAndChooseMedia(url: URL, fallback: (URL) -> URL?, unprocessedEnum: (URL) -> PreUploadedMedia, processedEnum: (URL) -> PreUploadedMedia, orderId: String) { if url.startAccessingSecurityScopedResource() { // Have permission from system to use url out of scope print("Acquired permission to security scoped resource") - self.chooseMedia(unprocessedEnum(url)) + self.chooseMedia(unprocessedEnum(url), orderId: orderId) } else { // Need to copy URL to non-security scoped location guard let newUrl = fallback(url) else { return } - self.chooseMedia(processedEnum(newUrl)) + self.chooseMedia(processedEnum(newUrl), orderId: orderId) } } } func makeCoordinator() -> Coordinator { - Coordinator(self) - } + Coordinator(self) + } func makeUIViewController(context: Context) -> PHPickerViewController { var configuration = PHPickerConfiguration(photoLibrary: .shared())