forked from shadowfacts/Tusker
Include filename extension for attachments
Fixes posting attachments on pleroma resulting in them served as application/octet-stream, even though we're sending the mime type as well
This commit is contained in:
parent
9fa352d4f8
commit
037b717e60
|
@ -48,13 +48,13 @@ enum CompositionAttachmentData {
|
|||
}
|
||||
}
|
||||
|
||||
func getData(completion: @escaping (Result<(Data, String), Error>) -> Void) {
|
||||
func getData(completion: @escaping (Result<(Data, UTType), Error>) -> Void) {
|
||||
switch self {
|
||||
case let .image(image):
|
||||
// Export as JPEG instead of PNG, otherweise photos straight from the camera are too large
|
||||
// for Mastodon in its default configuration (max of 10MB).
|
||||
// The quality of 0.8 was chosen completely arbitrarily, it may need to be tuned in the future.
|
||||
completion(.success((image.jpegData(compressionQuality: 0.8)!, "image/jpeg")))
|
||||
completion(.success((image.jpegData(compressionQuality: 0.8)!, .jpeg)))
|
||||
case let .asset(asset):
|
||||
if asset.mediaType == .image {
|
||||
let options = PHImageRequestOptions()
|
||||
|
@ -68,19 +68,19 @@ enum CompositionAttachmentData {
|
|||
return
|
||||
}
|
||||
|
||||
let mimeType: String
|
||||
let utType: UTType
|
||||
if dataUTI == "public.heic" {
|
||||
// neither Mastodon nor Pleroma handles HEIC well, so convert to JPEG
|
||||
let image = CIImage(data: data)!
|
||||
let context = CIContext()
|
||||
let colorSpace = image.colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!
|
||||
data = context.jpegRepresentation(of: image, colorSpace: colorSpace, options: [:])!
|
||||
mimeType = "image/jpeg"
|
||||
utType = .jpeg
|
||||
} else {
|
||||
mimeType = UTType(dataUTI)!.preferredMIMEType!
|
||||
utType = UTType(dataUTI)!
|
||||
}
|
||||
|
||||
completion(.success((data, mimeType)))
|
||||
completion(.success((data, utType)))
|
||||
}
|
||||
} else if asset.mediaType == .video {
|
||||
let options = PHVideoRequestOptions()
|
||||
|
@ -109,11 +109,11 @@ enum CompositionAttachmentData {
|
|||
|
||||
case let .drawing(drawing):
|
||||
let image = drawing.imageInLightMode(from: drawing.bounds, scale: 1)
|
||||
completion(.success((image.pngData()!, "image/png")))
|
||||
completion(.success((image.pngData()!, .png)))
|
||||
}
|
||||
}
|
||||
|
||||
private static func exportVideoData(session: AVAssetExportSession, completion: @escaping (Result<(Data, String), Error>) -> Void) {
|
||||
private static func exportVideoData(session: AVAssetExportSession, completion: @escaping (Result<(Data, UTType), Error>) -> Void) {
|
||||
session.outputFileType = .mp4
|
||||
session.outputURL = FileManager.default.temporaryDirectory.appendingPathComponent("exported_video_\(UUID())").appendingPathExtension("mp4")
|
||||
session.exportAsynchronously {
|
||||
|
@ -123,7 +123,7 @@ enum CompositionAttachmentData {
|
|||
}
|
||||
do {
|
||||
let data = try Data(contentsOf: session.outputURL!)
|
||||
completion(.success((data, "video/mp4")))
|
||||
completion(.success((data, .mpeg4Movie)))
|
||||
} catch {
|
||||
completion(.failure(.videoExport(error)))
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import Foundation
|
||||
import Pachyderm
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
class PostService: ObservableObject {
|
||||
private let mastodonController: MastodonController
|
||||
|
@ -66,15 +67,15 @@ class PostService: ObservableObject {
|
|||
attachments.reserveCapacity(draft.attachments.count)
|
||||
for (index, attachment) in draft.attachments.enumerated() {
|
||||
let data: Data
|
||||
let mimeType: String
|
||||
let utType: UTType
|
||||
do {
|
||||
(data, mimeType) = try await getData(for: attachment)
|
||||
(data, utType) = try await getData(for: attachment)
|
||||
currentStep += 1
|
||||
} catch let error as CompositionAttachmentData.Error {
|
||||
throw Error.attachmentData(index: index, cause: error)
|
||||
}
|
||||
do {
|
||||
let uploaded = try await uploadAttachment(data: data, mimeType: mimeType, description: attachment.attachmentDescription)
|
||||
let uploaded = try await uploadAttachment(data: data, utType: utType, description: attachment.attachmentDescription)
|
||||
attachments.append(uploaded)
|
||||
currentStep += 1
|
||||
} catch let error as Client.Error {
|
||||
|
@ -84,7 +85,7 @@ class PostService: ObservableObject {
|
|||
return attachments
|
||||
}
|
||||
|
||||
private func getData(for attachment: CompositionAttachment) async throws -> (Data, String) {
|
||||
private func getData(for attachment: CompositionAttachment) async throws -> (Data, UTType) {
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
attachment.data.getData { result in
|
||||
switch result {
|
||||
|
@ -97,8 +98,8 @@ class PostService: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
private func uploadAttachment(data: Data, mimeType: String, description: String?) async throws -> Attachment {
|
||||
let formAttachment = FormAttachment(mimeType: mimeType, data: data, fileName: "file")
|
||||
private func uploadAttachment(data: Data, utType: UTType, description: String?) async throws -> Attachment {
|
||||
let formAttachment = FormAttachment(mimeType: utType.preferredMIMEType!, data: data, fileName: "file.\(utType.preferredFilenameExtension!)")
|
||||
let req = Client.upload(attachment: formAttachment, description: description)
|
||||
return try await mastodonController.run(req).0
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue