Composer: Scale down image that are too big for upload

This commit is contained in:
Thomas Ricouard 2023-02-23 21:21:21 +01:00
parent fa0ad34bea
commit 3cc589851f
2 changed files with 43 additions and 26 deletions

View File

@ -14,20 +14,20 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
case jpeg = "public.jpeg" case jpeg = "public.jpeg"
case png = "public.png" case png = "public.png"
case tiff = "public.tiff" case tiff = "public.tiff"
case video = "public.video" case video = "public.video"
case movie = "public.movie" case movie = "public.movie"
case mp4 = "public.mpeg-4" case mp4 = "public.mpeg-4"
case gif = "public.gif" case gif = "public.gif"
case gif2 = "com.compuserve.gif" case gif2 = "com.compuserve.gif"
case quickTimeMovie = "com.apple.quicktime-movie" case quickTimeMovie = "com.apple.quicktime-movie"
case uiimage = "com.apple.uikit.image" case uiimage = "com.apple.uikit.image"
static func types() -> [UTType] { static func types() -> [UTType] {
[.url, .text, .plainText, .image, .jpeg, .png, .tiff, .video, .mpeg4Movie, .gif, .movie, .quickTimeMovie] [.url, .text, .plainText, .image, .jpeg, .png, .tiff, .video, .mpeg4Movie, .gif, .movie, .quickTimeMovie]
} }
var isVideo: Bool { var isVideo: Bool {
switch self { switch self {
case .video, .movie, .mp4, .quickTimeMovie: case .video, .movie, .mp4, .quickTimeMovie:
@ -36,7 +36,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
return false return false
} }
} }
var isGif: Bool { var isGif: Bool {
switch self { switch self {
case .gif, .gif2: case .gif, .gif2:
@ -45,7 +45,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
return false return false
} }
} }
func loadItemContent(item: NSItemProvider) async throws -> Any? { func loadItemContent(item: NSItemProvider) async throws -> Any? {
let result = try await item.loadItem(forTypeIdentifier: rawValue) let result = try await item.loadItem(forTypeIdentifier: rawValue)
if isVideo, let transferable = await getVideoTransferable(item: item) { if isVideo, let transferable = await getVideoTransferable(item: item) {
@ -79,7 +79,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
return nil return nil
} }
} }
private func getVideoTransferable(item: NSItemProvider) async -> MovieFileTranseferable? { private func getVideoTransferable(item: NSItemProvider) async -> MovieFileTranseferable? {
return await withCheckedContinuation { continuation in return await withCheckedContinuation { continuation in
_ = item.loadTransferable(type: MovieFileTranseferable.self) { result in _ = item.loadTransferable(type: MovieFileTranseferable.self) { result in
@ -92,7 +92,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
} }
} }
} }
private func getGifTransferable(item: NSItemProvider) async -> GifFileTranseferable? { private func getGifTransferable(item: NSItemProvider) async -> GifFileTranseferable? {
return await withCheckedContinuation { continuation in return await withCheckedContinuation { continuation in
_ = item.loadTransferable(type: GifFileTranseferable.self) { result in _ = item.loadTransferable(type: GifFileTranseferable.self) { result in
@ -105,7 +105,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
} }
} }
} }
private func getImageTansferable(item: NSItemProvider) async -> ImageFileTranseferable? { private func getImageTansferable(item: NSItemProvider) async -> ImageFileTranseferable? {
return await withCheckedContinuation { continuation in return await withCheckedContinuation { continuation in
_ = item.loadTransferable(type: ImageFileTranseferable.self) { result in _ = item.loadTransferable(type: ImageFileTranseferable.self) { result in
@ -140,7 +140,7 @@ struct MovieFileTranseferable: Transferable {
} }
} }
} }
static var transferRepresentation: some TransferRepresentation { static var transferRepresentation: some TransferRepresentation {
FileRepresentation(contentType: .movie) { movie in FileRepresentation(contentType: .movie) { movie in
SentTransferredFile(movie.url) SentTransferredFile(movie.url)
@ -152,11 +152,10 @@ struct MovieFileTranseferable: Transferable {
struct ImageFileTranseferable: Transferable { struct ImageFileTranseferable: Transferable {
let url: URL let url: URL
lazy var data: Data? = try? Data(contentsOf: url) lazy var data: Data? = try? Data(contentsOf: url)
lazy var compressedData: Data? = image?.jpegData(compressionQuality: 0.80)
lazy var image: UIImage? = UIImage(data: data ?? Data()) lazy var image: UIImage? = UIImage(data: data ?? Data())
static var transferRepresentation: some TransferRepresentation { static var transferRepresentation: some TransferRepresentation {
FileRepresentation(contentType: .image) { image in FileRepresentation(contentType: .image) { image in
SentTransferredFile(image.url) SentTransferredFile(image.url)
@ -168,11 +167,11 @@ struct ImageFileTranseferable: Transferable {
struct GifFileTranseferable: Transferable { struct GifFileTranseferable: Transferable {
let url: URL let url: URL
var data: Data? { var data: Data? {
try? Data(contentsOf: url) try? Data(contentsOf: url)
} }
static var transferRepresentation: some TransferRepresentation { static var transferRepresentation: some TransferRepresentation {
FileRepresentation(contentType: .gif) { gif in FileRepresentation(contentType: .gif) { gif in
SentTransferredFile(gif.url) SentTransferredFile(gif.url)
@ -197,3 +196,12 @@ public extension URL {
} }
} }
} }
extension UIImage {
func resized(to size: CGSize) -> UIImage {
UIGraphicsImageRenderer(size: size).image { _ in
draw(in: CGRect(origin: .zero, size: size))
}
}
}

View File

@ -572,17 +572,26 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
mediasImages[index] = newContainer mediasImages[index] = newContainer
do { do {
if let index = indexOf(container: newContainer) { if let index = indexOf(container: newContainer) {
if let image = originalContainer.image, if let image = originalContainer.image {
let data = image.jpegData(compressionQuality: 0.90) let data: Data?
{ // Mastodon API don't support images over 5K
let uploadedMedia = try await uploadMedia(data: data, mimeType: "image/jpeg") if image.size.height > 5000 || image.size.width > 5000 {
mediasImages[index] = .init(image: mode.isInShareExtension ? originalContainer.image : nil, data = image.resized(to: .init(width: image.size.width / 4,
movieTransferable: nil, height: image.size.height / 4))
gifTransferable: nil, .jpegData(compressionQuality: 0.80)
mediaAttachment: uploadedMedia, } else {
error: nil) data = image.jpegData(compressionQuality: 0.80)
if let uploadedMedia, uploadedMedia.url == nil { }
scheduleAsyncMediaRefresh(mediaAttachement: uploadedMedia) if let data {
let uploadedMedia = try await uploadMedia(data: data, mimeType: "image/jpeg")
mediasImages[index] = .init(image: mode.isInShareExtension ? originalContainer.image : nil,
movieTransferable: nil,
gifTransferable: nil,
mediaAttachment: uploadedMedia,
error: nil)
if let uploadedMedia, uploadedMedia.url == nil {
scheduleAsyncMediaRefresh(mediaAttachement: uploadedMedia)
}
} }
} else if let videoURL = await originalContainer.movieTransferable?.compressedVideoURL, } else if let videoURL = await originalContainer.movieTransferable?.compressedVideoURL,
let data = try? Data(contentsOf: videoURL) let data = try? Data(contentsOf: videoURL)