forked from shadowfacts/Tusker
Fix crash when fetching attachment data fails
This commit is contained in:
parent
e65ed3e773
commit
fa1482a152
|
@ -48,13 +48,13 @@ enum CompositionAttachmentData {
|
|||
}
|
||||
}
|
||||
|
||||
func getData(completion: @escaping (_ data: Data, _ mimeType: String) -> Void) {
|
||||
func getData(completion: @escaping (Result<(Data, String), 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(image.jpegData(compressionQuality: 0.8)!, "image/jpeg")
|
||||
completion(.success((image.jpegData(compressionQuality: 0.8)!, "image/jpeg")))
|
||||
case let .asset(asset):
|
||||
if asset.mediaType == .image {
|
||||
let options = PHImageRequestOptions()
|
||||
|
@ -63,7 +63,10 @@ enum CompositionAttachmentData {
|
|||
options.resizeMode = .none
|
||||
options.isNetworkAccessAllowed = true
|
||||
PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { (data, dataUTI, orientation, info) in
|
||||
guard var data = data, let dataUTI = dataUTI else { fatalError() }
|
||||
guard var data = data, let dataUTI = dataUTI else {
|
||||
completion(.failure(.missingData))
|
||||
return
|
||||
}
|
||||
|
||||
let mimeType: String
|
||||
if dataUTI == "public.heic" {
|
||||
|
@ -77,7 +80,7 @@ enum CompositionAttachmentData {
|
|||
mimeType = UTType(dataUTI)!.preferredMIMEType!
|
||||
}
|
||||
|
||||
completion(data, mimeType)
|
||||
completion(.success((data, mimeType)))
|
||||
}
|
||||
} else if asset.mediaType == .video {
|
||||
let options = PHVideoRequestOptions()
|
||||
|
@ -100,20 +103,23 @@ enum CompositionAttachmentData {
|
|||
|
||||
case let .drawing(drawing):
|
||||
let image = drawing.imageInLightMode(from: drawing.bounds, scale: 1)
|
||||
completion(image.pngData()!, "image/png")
|
||||
completion(.success((image.pngData()!, "image/png")))
|
||||
}
|
||||
}
|
||||
|
||||
private static func exportVideoData(session: AVAssetExportSession, completion: @escaping (Data, String) -> Void) {
|
||||
private static func exportVideoData(session: AVAssetExportSession, completion: @escaping (Result<(Data, String), Error>) -> Void) {
|
||||
session.outputFileType = .mp4
|
||||
session.outputURL = FileManager.default.temporaryDirectory.appendingPathComponent("exported_video_\(UUID())").appendingPathExtension("mp4")
|
||||
session.exportAsynchronously {
|
||||
guard session.status == .completed else { fatalError("video export failed: \(String(describing: session.error))") }
|
||||
guard session.status == .completed else {
|
||||
completion(.failure(.export(session.error!)))
|
||||
return
|
||||
}
|
||||
do {
|
||||
let data = try Data(contentsOf: session.outputURL!)
|
||||
completion(data, "video/mp4")
|
||||
completion(.success((data, "video/mp4")))
|
||||
} catch {
|
||||
fatalError("Unable to load video: \(error)")
|
||||
completion(.failure(.export(error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +127,11 @@ enum CompositionAttachmentData {
|
|||
enum AttachmentType {
|
||||
case image, video
|
||||
}
|
||||
|
||||
enum Error: Swift.Error {
|
||||
case missingData
|
||||
case export(Swift.Error)
|
||||
}
|
||||
}
|
||||
|
||||
extension PHAsset {
|
||||
|
|
|
@ -97,7 +97,18 @@ struct ComposeAttachmentRow: View {
|
|||
mode = .recognizingText
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
self.attachment.data.getData { (data, mimeType) in
|
||||
self.attachment.data.getData { (result) in
|
||||
let data: Data
|
||||
do {
|
||||
try data = result.get().0
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
self.mode = .allowEntry
|
||||
self.isShowingTextRecognitionFailedAlert = true
|
||||
self.textRecognitionErrorMessage = error.localizedDescription
|
||||
}
|
||||
return
|
||||
}
|
||||
let handler = VNImageRequestHandler(data: data, options: [:])
|
||||
let request = VNRecognizeTextRequest { (request, error) in
|
||||
DispatchQueue.main.async {
|
||||
|
|
|
@ -244,17 +244,17 @@ struct ComposeView: View {
|
|||
private func uploadAttachments(_ completion: @escaping (Result<[Attachment], AttachmentUploadError>) -> Void) {
|
||||
let group = DispatchGroup()
|
||||
|
||||
var attachmentDatas = [(Data, String)?]()
|
||||
var attachmentDataResults = [Result<(Data, String), CompositionAttachmentData.Error>?]()
|
||||
|
||||
for (index, compAttachment) in draft.attachments.enumerated() {
|
||||
group.enter()
|
||||
|
||||
attachmentDatas.append(nil)
|
||||
attachmentDataResults.append(nil)
|
||||
|
||||
compAttachment.data.getData { (data, mimeType) in
|
||||
compAttachment.data.getData { (result) in
|
||||
postProgress += 1
|
||||
|
||||
attachmentDatas[index] = (data, mimeType)
|
||||
attachmentDataResults[index] = result
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +271,15 @@ struct ComposeView: View {
|
|||
// posted status reflects order the user set.
|
||||
// Pleroma does respect the order of the `media_ids` parameter.
|
||||
|
||||
for (index, (data, mimeType)) in attachmentDatas.map(\.unsafelyUnwrapped).enumerated() {
|
||||
let datas: [(Data, String)]
|
||||
do {
|
||||
datas = try attachmentDataResults.map { try $0!.get() }
|
||||
} catch {
|
||||
completion(.failure(AttachmentUploadError(errors: [error])))
|
||||
return
|
||||
}
|
||||
|
||||
for (index, (data, mimeType)) in datas.enumerated() {
|
||||
group.enter()
|
||||
|
||||
let compAttachment = draft.attachments[index]
|
||||
|
|
Loading…
Reference in New Issue