This commit fixes GIF uploads and improves GIF support: - MediaPicker will now skip location data removal processing, as it is not needed on GIF images and causes them to be converted to JPEG images - The uploader now sets more accurate MIME types on the upload request Issue Repro ----------- Device: iPhone 13 Mini iOS: 17.4.1 Damus: `ada99418f6fcdb1354bc5c1c3f3cc3b4db994ce6` Steps: 1. Download a GIF from GIPHY to the iOS photo gallery 2. Upload that and attach into a post in Damus 3. Check if GIF is animated. Results: GIF is not animated. Issue is reproduced. Testing ------- PASS Device: iPhone 13 Mini iOS: 17.4.1 Damus: this commit Steps: 1. Create a new post 2. Upload the same GIF as the repro and post 3. Make sure GIF is animated. PASS 4. Create a new post 5. Upload a new GIF image (that has never been uploaded by the user on the app) and post 6. Make sure the GIF is animated on the post. PASS 7. Make sure that JPEGs can still be successfully uploaded. PASS 8. Make sure that MP4s can be uploaded. 9. Make a new post that contains 1 JPEG, 1 MP4 file, and 2 GIF files. Make sure they are all uploaded correctly and all GIF files are animated. PASS Closes: https://github.com/damus-io/damus/issues/2157 Changelog-Fixed: Fix broken GIF uploads Signed-off-by: Daniel D’Aquino <daniel@daquino.me> Reviewed-by: William Casarin <jb55@jb55.com>
108 lines
2.8 KiB
Swift
108 lines
2.8 KiB
Swift
//
|
|
// ImageUploadModel.swift
|
|
// damus
|
|
//
|
|
// Created by William Casarin on 2023-03-16.
|
|
//
|
|
|
|
import Foundation
|
|
import UIKit
|
|
|
|
enum PreUploadedMedia {
|
|
case uiimage(UIImage)
|
|
case processed_image(URL)
|
|
case unprocessed_image(URL)
|
|
case processed_video(URL)
|
|
case unprocessed_video(URL)
|
|
}
|
|
|
|
enum MediaUpload {
|
|
case image(URL)
|
|
case video(URL)
|
|
|
|
var genericFileName: String {
|
|
"damus_generic_filename.\(file_extension)"
|
|
}
|
|
|
|
var file_extension: String {
|
|
switch self {
|
|
case .image(let url):
|
|
return url.pathExtension
|
|
case .video(let url):
|
|
return url.pathExtension
|
|
}
|
|
}
|
|
|
|
var localURL: URL {
|
|
switch self {
|
|
case .image(let url):
|
|
return url
|
|
case .video(let url):
|
|
return url
|
|
}
|
|
}
|
|
|
|
var is_image: Bool {
|
|
if case .image = self {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
var mime_type: String {
|
|
switch self.file_extension {
|
|
case "jpg", "jpeg":
|
|
return "image/jpg"
|
|
case "png":
|
|
return "image/png"
|
|
case "gif":
|
|
return "image/gif"
|
|
case "tiff", "tif":
|
|
return "image/tiff"
|
|
case "mp4":
|
|
return "video/mp4"
|
|
case "ogg":
|
|
return "video/ogg"
|
|
case "webm":
|
|
return "video/webm"
|
|
default:
|
|
switch self {
|
|
case .image:
|
|
return "image/jpg"
|
|
case .video:
|
|
return "video/mp4"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class ImageUploadModel: NSObject, URLSessionTaskDelegate, ObservableObject {
|
|
@Published var progress: Double? = nil
|
|
|
|
func start(media: MediaUpload, uploader: MediaUploader, keypair: Keypair? = nil) async -> ImageUploadResult {
|
|
let res = await create_upload_request(mediaToUpload: media, mediaUploader: uploader, progress: self, keypair: keypair)
|
|
|
|
switch res {
|
|
case .success(_):
|
|
DispatchQueue.main.async {
|
|
self.progress = nil
|
|
UINotificationFeedbackGenerator().notificationOccurred(.success)
|
|
}
|
|
case .failed(_):
|
|
DispatchQueue.main.async {
|
|
self.progress = nil
|
|
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
|
}
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
|
|
DispatchQueue.main.async {
|
|
self.progress = Double(totalBytesSent) / Double(totalBytesExpectedToSend)
|
|
}
|
|
}
|
|
}
|