Fix crash when pasting screenshots, not being able to paste gifs

This commit is contained in:
Shadowfacts 2023-04-17 20:03:31 -04:00
parent 436159bd46
commit 849882287f
3 changed files with 14 additions and 16 deletions

View File

@ -1,6 +1,6 @@
// //
// PostService.swift // PostService.swift
// Tusker // ComposeUI
// //
// Created by Shadowfacts on 4/27/22. // Created by Shadowfacts on 4/27/22.
// Copyright © 2022 Shadowfacts. All rights reserved. // Copyright © 2022 Shadowfacts. All rights reserved.

View File

@ -72,8 +72,7 @@ class AttachmentsListController: ViewController {
draft.attachments.remove(atOffsets: indices) draft.attachments.remove(atOffsets: indices)
} }
@MainActor private func insertAttachments(at offset: Int, itemProviders: [NSItemProvider]) {
private func insertAttachments(at offset: Int, itemProviders: [NSItemProvider]) async {
for provider in itemProviders where provider.canLoadObject(ofClass: DraftAttachment.self) { for provider in itemProviders where provider.canLoadObject(ofClass: DraftAttachment.self) {
provider.loadObject(ofClass: DraftAttachment.self) { object, error in provider.loadObject(ofClass: DraftAttachment.self) { object, error in
guard let attachment = object as? DraftAttachment else { return } guard let attachment = object as? DraftAttachment else { return }
@ -87,9 +86,7 @@ class AttachmentsListController: ViewController {
private func addImage() { private func addImage() {
parent.config.presentAssetPicker?({ results in parent.config.presentAssetPicker?({ results in
Task { self.insertAttachments(at: self.draft.attachments.count, itemProviders: results.map(\.itemProvider))
await self.insertAttachments(at: self.draft.attachments.count, itemProviders: results.map(\.itemProvider))
}
}) })
} }
@ -147,11 +144,14 @@ class AttachmentsListController: ViewController {
.onDelete(perform: controller.deleteAttachments) .onDelete(perform: controller.deleteAttachments)
.conditionally(controller.canAddAttachment) { .conditionally(controller.canAddAttachment) {
$0.onInsert(of: DraftAttachment.readableTypeIdentifiersForItemProvider, perform: { offset, providers in $0.onInsert(of: DraftAttachment.readableTypeIdentifiersForItemProvider, perform: { offset, providers in
Task { controller.insertAttachments(at: offset, itemProviders: providers)
await controller.insertAttachments(at: offset, itemProviders: providers)
}
}) })
} }
// only sort of works, see #240
.onDrop(of: DraftAttachment.readableTypeIdentifiersForItemProvider, isTargeted: nil) { providers in
controller.insertAttachments(at: 0, itemProviders: providers)
return true
}
} }
private var addImageButton: some View { private var addImageButton: some View {

View File

@ -50,10 +50,10 @@ public final class DraftAttachment: NSObject, Codable, ObservableObject, Identif
} }
} }
private let imageType = UTType.image.identifier private let jpegType = UTType.jpeg.identifier
private let pngType = UTType.png.identifier
private let mp4Type = UTType.mpeg4Movie.identifier private let mp4Type = UTType.mpeg4Movie.identifier
private let quickTimeType = UTType.quickTimeMovie.identifier private let quickTimeType = UTType.quickTimeMovie.identifier
private let dataType = UTType.data.identifier
private let gifType = UTType.gif.identifier private let gifType = UTType.gif.identifier
extension DraftAttachment: NSItemProviderWriting { extension DraftAttachment: NSItemProviderWriting {
@ -91,7 +91,7 @@ extension DraftAttachment: NSItemProviderReading {
// todo: is there a better way of handling movies than manually adding all possible UTI types? // todo: is there a better way of handling movies than manually adding all possible UTI types?
// just using kUTTypeMovie doesn't work, because we need the actually type in order to get the file extension // just using kUTTypeMovie doesn't work, because we need the actually type in order to get the file extension
// without the file extension, getting the thumbnail and exporting the video for attachment upload fails // without the file extension, getting the thumbnail and exporting the video for attachment upload fails
[typeIdentifier] + UIImage.readableTypeIdentifiersForItemProvider + [mp4Type, quickTimeType] + NSURL.readableTypeIdentifiersForItemProvider [typeIdentifier, gifType, jpegType, pngType, mp4Type, quickTimeType]
} }
public static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> DraftAttachment { public static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> DraftAttachment {
@ -101,15 +101,13 @@ extension DraftAttachment: NSItemProviderReading {
return DraftAttachment(data: .gif(data)) return DraftAttachment(data: .gif(data))
} else if UIImage.readableTypeIdentifiersForItemProvider.contains(typeIdentifier) { } else if UIImage.readableTypeIdentifiersForItemProvider.contains(typeIdentifier) {
return DraftAttachment(data: .image(data, originalType: UTType(typeIdentifier)!)) return DraftAttachment(data: .image(data, originalType: UTType(typeIdentifier)!))
} else if let type = UTType(typeIdentifier), type == .mpeg4Movie || type == .quickTimeMovie { } else if typeIdentifier == mp4Type || typeIdentifier == quickTimeType {
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
let temporaryFileName = ProcessInfo().globallyUniqueString let temporaryFileName = ProcessInfo().globallyUniqueString
let fileExt = type.preferredFilenameExtension! let fileExt = UTType(typeIdentifier)!.preferredFilenameExtension!
let temporaryFileURL = temporaryDirectoryURL.appendingPathComponent(temporaryFileName).appendingPathExtension(fileExt) let temporaryFileURL = temporaryDirectoryURL.appendingPathComponent(temporaryFileName).appendingPathExtension(fileExt)
try data.write(to: temporaryFileURL) try data.write(to: temporaryFileURL)
return DraftAttachment(data: .video(temporaryFileURL)) return DraftAttachment(data: .video(temporaryFileURL))
} else if NSURL.readableTypeIdentifiersForItemProvider.contains(typeIdentifier), let url = try? NSURL.object(withItemProviderData: data, typeIdentifier: typeIdentifier) as URL {
return DraftAttachment(data: .video(url))
} else { } else {
throw ItemProviderError.incompatibleTypeIdentifier throw ItemProviderError.incompatibleTypeIdentifier
} }