damus

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

commit 7c0e1c5ded1b6a7849da49ec2a6d2df50ee44456
parent f6e34ad999454868b40382bd821013f3ac562b4a
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 16 Oct 2024 08:48:25 -0700

Merge multiple image uploads

Changelog-Changed: Allow multiple images to be uploaded at the same time (swiftcoder)

Diffstat:
Mdamus/Views/MediaPicker.swift | 4++--
Mdamus/Views/PostView.swift | 79++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
2 files changed, 48 insertions(+), 35 deletions(-)

diff --git a/damus/Views/MediaPicker.swift b/damus/Views/MediaPicker.swift @@ -115,9 +115,9 @@ struct MediaPicker: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> PHPickerViewController { var configuration = PHPickerConfiguration(photoLibrary: .shared()) - configuration.selectionLimit = 1 + configuration.selectionLimit = 0 // Allows multiple media selection configuration.filter = imagesOnly ? .images : .any(of: [.images, .videos]) - + configuration.selection = .ordered // images are returned in the order they were selected + numbered badge displayed let picker = PHPickerViewController(configuration: configuration) picker.delegate = context.coordinator as any PHPickerViewControllerDelegate return picker diff --git a/damus/Views/PostView.swift b/damus/Views/PostView.swift @@ -62,7 +62,7 @@ struct PostView: View { @State var newCursorIndex: Int? @State var textHeight: CGFloat? = nil - @State var preUploadedMedia: PreUploadedMedia? = nil + @State var preUploadedMedia: [PreUploadedMedia] = [] @StateObject var image_upload: ImageUploadModel = ImageUploadModel() @StateObject var tagModel: TagModel = TagModel() @@ -153,6 +153,7 @@ struct PostView: View { var ImageButton: some View { Button(action: { + preUploadedMedia.removeAll() attach_media = true }, label: { Image("images") @@ -321,34 +322,36 @@ struct PostView: View { .padding() .padding(.top, 15) } - - func handle_upload(media: MediaUpload) { + + @discardableResult + func handle_upload(media: MediaUpload) async -> Bool { let uploader = damus_state.settings.default_media_uploader - Task { - let img = getImage(media: media) - print("img size w:\(img.size.width) h:\(img.size.height)") - async let blurhash = calculate_blurhash(img: img) - let res = await image_upload.start(media: media, uploader: uploader, keypair: damus_state.keypair) - - switch res { - case .success(let url): - guard let url = URL(string: url) else { - self.error = "Error uploading image :(" - return - } - let blurhash = await blurhash - let meta = blurhash.map { bh in calculate_image_metadata(url: url, img: img, blurhash: bh) } - let uploadedMedia = UploadedMedia(localURL: media.localURL, uploadedURL: url, representingImage: img, metadata: meta) - uploadedMedias.append(uploadedMedia) - - case .failed(let error): - if let error { - self.error = error.localizedDescription - } else { - self.error = "Error uploading image :(" - } + + let img = getImage(media: media) + print("img size w:\(img.size.width) h:\(img.size.height)") + + async let blurhash = calculate_blurhash(img: img) + let res = await image_upload.start(media: media, uploader: uploader, keypair: damus_state.keypair) + + switch res { + case .success(let url): + guard let url = URL(string: url) else { + self.error = "Error uploading image :(" + return false } + let blurhash = await blurhash + let meta = blurhash.map { bh in calculate_image_metadata(url: url, img: img, blurhash: bh) } + let uploadedMedia = UploadedMedia(localURL: media.localURL, uploadedURL: url, representingImage: img, metadata: meta) + uploadedMedias.append(uploadedMedia) + return true + case .failed(let error): + if let error { + self.error = error.localizedDescription + } else { + self.error = "Error uploading image :(" + } + return false } } @@ -449,16 +452,23 @@ struct PostView: View { .background(DamusColors.adaptableWhite.edgesIgnoringSafeArea(.all)) .sheet(isPresented: $attach_media) { MediaPicker(image_upload_confirm: $image_upload_confirm){ media in - self.preUploadedMedia = media + self.preUploadedMedia.append(media) } - .alert(NSLocalizedString("Are you sure you want to upload this media?", comment: "Alert message asking if the user wants to upload media."), isPresented: $image_upload_confirm) { + .alert(NSLocalizedString("Are you sure you want to upload the selected media?", comment: "Alert message asking if the user wants to upload media."), isPresented: $image_upload_confirm) { Button(NSLocalizedString("Upload", comment: "Button to proceed with uploading."), role: .none) { - if let mediaToUpload = generateMediaUpload(preUploadedMedia) { - self.handle_upload(media: mediaToUpload) - self.attach_media = false + // initiate asynchronous uploading Task for multiple-images + Task { + for media in preUploadedMedia { + if let mediaToUpload = generateMediaUpload(media) { + await self.handle_upload(media: mediaToUpload) + } + } } + self.attach_media = false + } + Button(NSLocalizedString("Cancel", comment: "Button to cancel the upload."), role: .cancel) { + preUploadedMedia.removeAll() } - Button(NSLocalizedString("Cancel", comment: "Button to cancel the upload."), role: .cancel) {} } } .sheet(isPresented: $attach_camera) { @@ -472,7 +482,9 @@ struct PostView: View { Button(NSLocalizedString("Upload", comment: "Button to proceed with uploading."), role: .none) { if let image = imagePastedFromPasteboard, let mediaToUpload = generateMediaUpload(PreUploadedMedia.uiimage(image)) { - self.handle_upload(media: mediaToUpload) + Task { + await self.handle_upload(media: mediaToUpload) + } } } Button(NSLocalizedString("Cancel", comment: "Button to cancel the upload."), role: .cancel) {} @@ -500,6 +512,7 @@ struct PostView: View { if isEmpty() { clear_draft() } + preUploadedMedia.removeAll() } } }