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 png = "public.png"
case tiff = "public.tiff"
case video = "public.video"
case movie = "public.movie"
case mp4 = "public.mpeg-4"
case gif = "public.gif"
case gif2 = "com.compuserve.gif"
case quickTimeMovie = "com.apple.quicktime-movie"
case uiimage = "com.apple.uikit.image"
static func types() -> [UTType] {
[.url, .text, .plainText, .image, .jpeg, .png, .tiff, .video, .mpeg4Movie, .gif, .movie, .quickTimeMovie]
}
var isVideo: Bool {
switch self {
case .video, .movie, .mp4, .quickTimeMovie:
@ -36,7 +36,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
return false
}
}
var isGif: Bool {
switch self {
case .gif, .gif2:
@ -45,7 +45,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
return false
}
}
func loadItemContent(item: NSItemProvider) async throws -> Any? {
let result = try await item.loadItem(forTypeIdentifier: rawValue)
if isVideo, let transferable = await getVideoTransferable(item: item) {
@ -79,7 +79,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
return nil
}
}
private func getVideoTransferable(item: NSItemProvider) async -> MovieFileTranseferable? {
return await withCheckedContinuation { continuation in
_ = item.loadTransferable(type: MovieFileTranseferable.self) { result in
@ -92,7 +92,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
}
}
}
private func getGifTransferable(item: NSItemProvider) async -> GifFileTranseferable? {
return await withCheckedContinuation { continuation in
_ = item.loadTransferable(type: GifFileTranseferable.self) { result in
@ -105,7 +105,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
}
}
}
private func getImageTansferable(item: NSItemProvider) async -> ImageFileTranseferable? {
return await withCheckedContinuation { continuation in
_ = item.loadTransferable(type: ImageFileTranseferable.self) { result in
@ -140,7 +140,7 @@ struct MovieFileTranseferable: Transferable {
}
}
}
static var transferRepresentation: some TransferRepresentation {
FileRepresentation(contentType: .movie) { movie in
SentTransferredFile(movie.url)
@ -152,11 +152,10 @@ struct MovieFileTranseferable: Transferable {
struct ImageFileTranseferable: Transferable {
let url: 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())
static var transferRepresentation: some TransferRepresentation {
FileRepresentation(contentType: .image) { image in
SentTransferredFile(image.url)
@ -168,11 +167,11 @@ struct ImageFileTranseferable: Transferable {
struct GifFileTranseferable: Transferable {
let url: URL
var data: Data? {
try? Data(contentsOf: url)
}
static var transferRepresentation: some TransferRepresentation {
FileRepresentation(contentType: .gif) { gif in
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
do {
if let index = indexOf(container: newContainer) {
if let image = originalContainer.image,
let data = image.jpegData(compressionQuality: 0.90)
{
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)
if let image = originalContainer.image {
let data: Data?
// Mastodon API don't support images over 5K
if image.size.height > 5000 || image.size.width > 5000 {
data = image.resized(to: .init(width: image.size.width / 4,
height: image.size.height / 4))
.jpegData(compressionQuality: 0.80)
} else {
data = image.jpegData(compressionQuality: 0.80)
}
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,
let data = try? Data(contentsOf: videoURL)