Switch from deprecated UTI functions to UTType
This commit is contained in:
parent
96a2890d21
commit
c2fd39a95c
@ -7,6 +7,7 @@ import CoreServices
|
||||
import Photos
|
||||
import SignalServiceKit
|
||||
import SignalUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
extension ConversationViewController: ConversationInputToolbarDelegate {
|
||||
|
||||
@ -729,19 +730,17 @@ extension ConversationViewController: UIDocumentPickerDelegate {
|
||||
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
|
||||
Logger.debug("Picked document at url: \(url)")
|
||||
|
||||
let typeIdentifier: String = {
|
||||
let contentType: UTType = {
|
||||
do {
|
||||
let resourceValues = try url.resourceValues(forKeys: Set([
|
||||
.typeIdentifierKey
|
||||
]))
|
||||
guard let typeIdentifier = resourceValues.typeIdentifier else {
|
||||
owsFailDebug("Missing typeIdentifier.")
|
||||
return kUTTypeData as String
|
||||
let resourceValues = try url.resourceValues(forKeys: [.contentTypeKey])
|
||||
guard let contentType = resourceValues.contentType else {
|
||||
owsFailDebug("Missing contentType.")
|
||||
return .data
|
||||
}
|
||||
return typeIdentifier
|
||||
return contentType
|
||||
} catch {
|
||||
owsFailDebug("Error: \(error)")
|
||||
return kUTTypeData as String
|
||||
return .data
|
||||
}
|
||||
}()
|
||||
let isDirectory: Bool = {
|
||||
@ -802,12 +801,12 @@ extension ConversationViewController: UIDocumentPickerDelegate {
|
||||
// Although we want to be able to send higher quality attachments through the document picker
|
||||
// it's more important that we ensure the sent format is one all clients can accept (e.g. *not* quicktime .mov)
|
||||
if SignalAttachment.isVideoThatNeedsCompression(dataSource: dataSource,
|
||||
dataUTI: typeIdentifier) {
|
||||
dataUTI: contentType.identifier) {
|
||||
self.showApprovalDialogAfterProcessingVideoURL(url, filename: filename)
|
||||
return
|
||||
}
|
||||
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: typeIdentifier)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: contentType.identifier)
|
||||
showApprovalDialog(forAttachment: attachment)
|
||||
}
|
||||
|
||||
@ -831,7 +830,7 @@ extension ConversationViewController: UIDocumentPickerDelegate {
|
||||
dataSource.sourceFilename = filename
|
||||
let promise = Promise.wrapAsync({
|
||||
return try await SignalAttachment.compressVideoAsMp4(dataSource: dataSource,
|
||||
dataUTI: kUTTypeMPEG4 as String)
|
||||
dataUTI: UTType.mpeg4Movie.identifier)
|
||||
})
|
||||
promise.done(on: DispatchQueue.main) { (attachment: SignalAttachment) in
|
||||
if modalActivityIndicator.wasCancelled {
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
import CoreServices
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
protocol VoiceMessageSendableDraft {
|
||||
func prepareForSending() throws -> URL
|
||||
@ -27,7 +28,7 @@ extension VoiceMessageSendableDraft {
|
||||
let dataSource = try DataSourcePath.dataSource(with: attachmentUrl, shouldDeleteOnDeallocation: true)
|
||||
dataSource.sourceFilename = userVisibleFilename(currentDate: Date())
|
||||
|
||||
let attachment = SignalAttachment.voiceMessageAttachment(dataSource: dataSource, dataUTI: kUTTypeMPEG4Audio as String)
|
||||
let attachment = SignalAttachment.voiceMessageAttachment(dataSource: dataSource, dataUTI: UTType.mpeg4Audio.identifier)
|
||||
guard !attachment.hasError else {
|
||||
throw OWSAssertionError("Failed to create voice message attachment: \(attachment.errorName ?? "Unknown Error")")
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
import CoreServices
|
||||
import SignalServiceKit
|
||||
import SignalUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
class AvatarSettingsViewController: OWSTableViewController2 {
|
||||
let context: AvatarContext
|
||||
@ -334,7 +335,7 @@ class AvatarSettingsViewController: OWSTableViewController2 {
|
||||
picker.delegate = self
|
||||
picker.allowsEditing = false
|
||||
picker.sourceType = .camera
|
||||
picker.mediaTypes = [kUTTypeImage as String]
|
||||
picker.mediaTypes = [UTType.image.identifier]
|
||||
self.present(picker, animated: true)
|
||||
}
|
||||
}
|
||||
@ -352,7 +353,7 @@ class AvatarSettingsViewController: OWSTableViewController2 {
|
||||
let picker = OWSImagePickerController()
|
||||
picker.delegate = self
|
||||
picker.sourceType = .photoLibrary
|
||||
picker.mediaTypes = [kUTTypeImage as String]
|
||||
picker.mediaTypes = [UTType.image.identifier]
|
||||
self.present(picker, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import CoreServices
|
||||
import LibSignalClient
|
||||
import SignalServiceKit
|
||||
import SignalUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
#if USE_DEBUG_UI
|
||||
|
||||
@ -101,7 +102,7 @@ class DebugUIMessages: DebugUIPage, Dependencies {
|
||||
DebugUIMessages.sendRandomAttachmentInThread(thread, uti: MimeTypeUtil.unknownTestAttachmentUti)
|
||||
}),
|
||||
OWSTableItem(title: "Send pdf", actionBlock: {
|
||||
DebugUIMessages.sendRandomAttachmentInThread(thread, uti: kUTTypePDF as String)
|
||||
DebugUIMessages.sendRandomAttachmentInThread(thread, uti: UTType.pdf.identifier)
|
||||
}),
|
||||
OWSTableItem(title: "Create all system messages", actionBlock: {
|
||||
DebugUIMessages.createSystemMessagesInThread(thread)
|
||||
@ -1739,12 +1740,12 @@ class DebugUIMessages: DebugUIPage, Dependencies {
|
||||
sendUnsafeFile = {
|
||||
guard let filename = filenames.popLast() else { return }
|
||||
|
||||
let utiType = kUTTypeData as String
|
||||
let type = UTType.data
|
||||
let dataLength: UInt32 = 32
|
||||
guard let dataSource = DataSourceValue.dataSource(with: createRandomDataOfSize(dataLength), utiType: utiType) else { return }
|
||||
guard let dataSource = DataSourceValue.dataSource(with: createRandomDataOfSize(dataLength), utiType: type.identifier) else { return }
|
||||
|
||||
dataSource.sourceFilename = filename
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: utiType)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: type.identifier)
|
||||
|
||||
guard attachment.hasError else {
|
||||
Logger.error("attachment[\(String(describing: attachment.sourceFilename))]: \(String(describing: attachment.errorName))")
|
||||
|
||||
@ -14,6 +14,7 @@ import CoreServices
|
||||
import MapKit
|
||||
import SignalServiceKit
|
||||
import SignalUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
public protocol LocationPickerDelegate: AnyObject {
|
||||
func didPickLocation(_ locationPicker: LocationPicker, location: Location)
|
||||
@ -496,8 +497,8 @@ public class Location: NSObject {
|
||||
throw LocationError.assertion
|
||||
}
|
||||
|
||||
let dataSource = DataSourceValue.dataSource(with: jpegData, utiType: kUTTypeJPEG as String)
|
||||
return SignalAttachment.attachment(dataSource: dataSource, dataUTI: kUTTypeJPEG as String)
|
||||
let dataSource = DataSourceValue.dataSource(with: jpegData, utiType: UTType.jpeg.identifier)
|
||||
return SignalAttachment.attachment(dataSource: dataSource, dataUTI: UTType.jpeg.identifier)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -844,7 +844,7 @@ class CameraCaptureSession: NSObject {
|
||||
return handleVideoCaptureError(PhotoCaptureError.captureFailed)
|
||||
}
|
||||
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: kUTTypeMPEG4 as String)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: UTType.mpeg4Movie.identifier)
|
||||
delegate.cameraCaptureSession(self, didFinishProcessing: attachment)
|
||||
}
|
||||
|
||||
@ -1010,9 +1010,9 @@ extension CameraCaptureSession: PhotoCaptureDelegate {
|
||||
case .failure(let error):
|
||||
delegate.cameraCaptureSession(self, didFailWith: error)
|
||||
case .success(let photoData):
|
||||
let dataSource = DataSourceValue.dataSource(with: photoData, utiType: kUTTypeJPEG as String)
|
||||
let dataSource = DataSourceValue.dataSource(with: photoData, utiType: UTType.jpeg.identifier)
|
||||
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: kUTTypeJPEG as String)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: UTType.jpeg.identifier)
|
||||
delegate.cameraCaptureSession(self, didFinishProcessing: attachment)
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ class PhotoAlbumContents {
|
||||
let baseFilename: String?
|
||||
if let onDiskVideo = video as? AVURLAsset {
|
||||
let url = onDiskVideo.url
|
||||
dataUTI = MimeTypeUtil.utiTypeForFileExtension(url.pathExtension) ?? kUTTypeVideo as String
|
||||
dataUTI = MimeTypeUtil.utiTypeForFileExtension(url.pathExtension) ?? UTType.video.identifier
|
||||
|
||||
if let dataSource = try? DataSourcePath.dataSource(with: url, shouldDeleteOnDeallocation: false) {
|
||||
if !SignalAttachment.isVideoThatNeedsCompression(dataSource: dataSource, dataUTI: dataUTI) {
|
||||
@ -204,7 +204,7 @@ class PhotoAlbumContents {
|
||||
|
||||
baseFilename = url.lastPathComponent
|
||||
} else {
|
||||
dataUTI = kUTTypeVideo as String
|
||||
dataUTI = UTType.video.identifier
|
||||
baseFilename = nil
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
import CoreServices
|
||||
import SignalServiceKit
|
||||
import SignalUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
class SetWallpaperViewController: OWSTableViewController2 {
|
||||
lazy var collectionView = WallpaperCollectionView(container: self, shouldDimInDarkMode: shouldDimInDarkMode) { [weak self] wallpaper in
|
||||
@ -84,7 +85,7 @@ class SetWallpaperViewController: OWSTableViewController2 {
|
||||
let vc = UIImagePickerController()
|
||||
vc.delegate = self
|
||||
vc.sourceType = .photoLibrary
|
||||
vc.mediaTypes = [kUTTypeImage as String]
|
||||
vc.mediaTypes = [UTType.image.identifier]
|
||||
self.presentFormSheet(vc, animated: true)
|
||||
}
|
||||
photosSection.add(choosePhotoItem)
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
import XCTest
|
||||
import CoreServices
|
||||
import SignalServiceKit
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
class SignalAttachmentTest: SignalBaseTest {
|
||||
// MARK: - Utilities
|
||||
@ -16,7 +17,7 @@ class SignalAttachmentTest: SignalBaseTest {
|
||||
let dataSource = try DataSourcePath.dataSource(with: url, shouldDeleteOnDeallocation: false)
|
||||
let attachment = SignalAttachment.attachment(
|
||||
dataSource: dataSource,
|
||||
dataUTI: kUTTypeJPEG as String
|
||||
dataUTI: UTType.jpeg.identifier
|
||||
)
|
||||
let newSize = attachment.data.imageMetadata(withPath: nil, mimeType: "image/jpeg").pixelSize
|
||||
|
||||
@ -60,7 +61,7 @@ class SignalAttachmentTest: SignalBaseTest {
|
||||
|
||||
let attachment = SignalAttachment.attachment(
|
||||
dataSource: dataSource,
|
||||
dataUTI: kUTTypePNG as String
|
||||
dataUTI: UTType.png.identifier
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
@ -98,7 +99,7 @@ class SignalAttachmentTest: SignalBaseTest {
|
||||
|
||||
let attachment = SignalAttachment.attachment(
|
||||
dataSource: dataSource,
|
||||
dataUTI: kUTTypePNG as String
|
||||
dataUTI: UTType.png.identifier
|
||||
)
|
||||
|
||||
XCTAssert(
|
||||
|
||||
@ -433,10 +433,7 @@ public class SignalAttachment: NSObject {
|
||||
if dataUTI == MimeTypeUtil.unknownTestAttachmentUti {
|
||||
return MimeType.unknownMimetype.rawValue
|
||||
}
|
||||
guard let mimeType = UTTypeCopyPreferredTagWithClass(dataUTI as CFString, kUTTagClassMIMEType) else {
|
||||
return MimeType.applicationOctetStream.rawValue
|
||||
}
|
||||
return mimeType.takeRetainedValue() as String
|
||||
return UTType(dataUTI)?.preferredMIMEType ?? MimeType.applicationOctetStream.rawValue
|
||||
}
|
||||
|
||||
// Use the filename if known. If not, e.g. if the attachment was copy/pasted, we'll generate a filename
|
||||
@ -502,7 +499,7 @@ public class SignalAttachment: NSObject {
|
||||
}
|
||||
|
||||
private class var outputVideoUTISet: Set<String> {
|
||||
return Set([kUTTypeMPEG4 as String])
|
||||
[UTType.mpeg4Movie.identifier]
|
||||
}
|
||||
|
||||
// Returns the set of UTIs that correspond to valid animated image formats
|
||||
@ -557,11 +554,12 @@ public class SignalAttachment: NSObject {
|
||||
}
|
||||
|
||||
public var isText: Bool {
|
||||
return UTTypeConformsTo(dataUTI as CFString, kUTTypeText) || isOversizeText
|
||||
let isText = UTType(dataUTI)?.conforms(to: .text) ?? false
|
||||
return isText || isOversizeText
|
||||
}
|
||||
|
||||
public var isUrl: Bool {
|
||||
return UTTypeConformsTo(dataUTI as CFString, kUTTypeURL)
|
||||
UTType(dataUTI)?.conforms(to: .url) ?? false
|
||||
}
|
||||
|
||||
public class func pasteboardHasPossibleAttachment() -> Bool {
|
||||
@ -608,13 +606,13 @@ public class SignalAttachment: NSObject {
|
||||
var hasTextUTIType = false
|
||||
var hasNonTextUTIType = false
|
||||
for utiType in pasteboardUTISet {
|
||||
if UTTypeConformsTo(utiType as CFString, kUTTypeText) {
|
||||
if let type = UTType(utiType), type.conforms(to: .text) {
|
||||
hasTextUTIType = true
|
||||
} else if mediaUTISet.contains(utiType) {
|
||||
hasNonTextUTIType = true
|
||||
}
|
||||
}
|
||||
if pasteboardUTISet.contains(kUTTypeURL as String) {
|
||||
if pasteboardUTISet.contains(UTType.url.identifier) {
|
||||
// Treat URL as a textual UTI type.
|
||||
hasTextUTIType = true
|
||||
}
|
||||
@ -659,8 +657,8 @@ public class SignalAttachment: NSObject {
|
||||
// and png uti types when sending memoji stickers and
|
||||
// `inputImageUTISet` is unordered, so without this check there
|
||||
// is a 50/50 chance that we'd pick the jpg.
|
||||
if pasteboardUTISet.isSuperset(of: [kUTTypeJPEG as String, kUTTypePNG as String]) {
|
||||
pasteboardUTISet.remove(kUTTypeJPEG as String)
|
||||
if pasteboardUTISet.isSuperset(of: [UTType.jpeg.identifier, UTType.png.identifier]) {
|
||||
pasteboardUTISet.remove(UTType.jpeg.identifier)
|
||||
}
|
||||
|
||||
for dataUTI in inputImageUTISet {
|
||||
@ -762,7 +760,7 @@ public class SignalAttachment: NSObject {
|
||||
}
|
||||
|
||||
// Never re-encode animated images (i.e. GIFs) as JPEGs.
|
||||
if dataUTI == (kUTTypePNG as String) {
|
||||
if dataUTI == UTType.png.identifier {
|
||||
do {
|
||||
return try attachment.removingImageMetadata()
|
||||
} catch {
|
||||
@ -777,7 +775,7 @@ public class SignalAttachment: NSObject {
|
||||
if let sourceFilename = dataSource.sourceFilename,
|
||||
let sourceFileExtension = sourceFilename.fileExtension,
|
||||
["heic", "heif"].contains(sourceFileExtension.lowercased()),
|
||||
dataUTI == kUTTypeJPEG as String {
|
||||
dataUTI == UTType.jpeg.identifier as String {
|
||||
|
||||
// If a .heic file actually contains jpeg data, update the extension to match.
|
||||
//
|
||||
@ -822,7 +820,7 @@ public class SignalAttachment: NSObject {
|
||||
// JPEGs and instead go through the recompresing step.
|
||||
// This is an iOS bug (FB13285956) still present in iOS 17 and should
|
||||
// be revisitied in the future to see if JPEG support can be reenabled.
|
||||
guard dataUTI != (kUTTypeJPEG as String) else { return false }
|
||||
guard dataUTI != UTType.jpeg.identifier else { return false }
|
||||
|
||||
guard SignalAttachment.outputImageUTISet.contains(dataUTI) else { return false }
|
||||
guard dataSource.dataLength <= imageQuality.maxFileSize else { return false }
|
||||
@ -909,7 +907,7 @@ public class SignalAttachment: NSObject {
|
||||
// so we can keep the image out of memory.
|
||||
|
||||
let dataFileExtension: String
|
||||
let dataUTI: CFString
|
||||
let dataType: UTType
|
||||
|
||||
// We convert everything that's not sticker-like to jpg, because
|
||||
// often images with alpha channels don't actually have any
|
||||
@ -918,15 +916,15 @@ public class SignalAttachment: NSObject {
|
||||
// are any transparent pixels in an image.
|
||||
if dataSource.hasStickerLikeProperties {
|
||||
dataFileExtension = "png"
|
||||
dataUTI = kUTTypePNG
|
||||
dataType = .png
|
||||
} else {
|
||||
dataFileExtension = "jpg"
|
||||
dataUTI = kUTTypeJPEG
|
||||
dataType = .jpeg
|
||||
imageProperties[kCGImageDestinationLossyCompressionQuality] = compressionQuality(for: pixelSize)
|
||||
}
|
||||
|
||||
let tempFileUrl = OWSFileSystem.temporaryFileUrl(fileExtension: dataFileExtension)
|
||||
guard let destination = CGImageDestinationCreateWithURL(tempFileUrl as CFURL, dataUTI, 1, nil) else {
|
||||
guard let destination = CGImageDestinationCreateWithURL(tempFileUrl as CFURL, dataType.identifier as CFString, 1, nil) else {
|
||||
owsFailDebug("Failed to create CGImageDestination for attachment")
|
||||
return .error(error: .couldNotConvertImage)
|
||||
}
|
||||
@ -950,7 +948,7 @@ public class SignalAttachment: NSObject {
|
||||
outputDataSource.sourceFilename = newFilenameWithExtension
|
||||
|
||||
if outputDataSource.dataLength <= imageQuality.maxFileSize, outputDataSource.dataLength <= kMaxFileSizeImage {
|
||||
let recompressedAttachment = attachment.replacingDataSource(with: outputDataSource, dataUTI: dataUTI as String)
|
||||
let recompressedAttachment = attachment.replacingDataSource(with: outputDataSource, dataUTI: dataType.identifier)
|
||||
return .signalAttachment(signalAttachment: recompressedAttachment)
|
||||
}
|
||||
|
||||
@ -1065,7 +1063,7 @@ public class SignalAttachment: NSObject {
|
||||
private func removingImageMetadata() throws -> SignalAttachment {
|
||||
owsAssertDebug(isImage)
|
||||
|
||||
if dataUTI == (kUTTypePNG as String) {
|
||||
if dataUTI == UTType.png.identifier {
|
||||
let cleanedData = try Self.removeMetadata(fromPng: data)
|
||||
guard let dataSource = DataSourceValue.dataSource(with: cleanedData, utiType: dataUTI) else {
|
||||
throw SignalAttachmentError.couldNotRemoveMetadata
|
||||
@ -1234,7 +1232,7 @@ public class SignalAttachment: NSObject {
|
||||
shouldDeleteOnDeallocation: true)
|
||||
dataSource.sourceFilename = mp4Filename
|
||||
|
||||
return SignalAttachment(dataSource: dataSource, dataUTI: kUTTypeMPEG4 as String)
|
||||
return SignalAttachment(dataSource: dataSource, dataUTI: UTType.mpeg4Movie.identifier)
|
||||
} catch {
|
||||
owsFailDebug("Failed to build data source for exported video URL")
|
||||
let attachment = SignalAttachment(dataSource: DataSourceValue.emptyDataSource(), dataUTI: dataUTI)
|
||||
@ -1323,8 +1321,7 @@ public class SignalAttachment: NSObject {
|
||||
}
|
||||
|
||||
public class func empty() -> SignalAttachment {
|
||||
return SignalAttachment.attachment(dataSource: DataSourceValue.emptyDataSource(),
|
||||
dataUTI: kUTTypeContent as String)
|
||||
SignalAttachment.attachment(dataSource: DataSourceValue.emptyDataSource(), dataUTI: UTType.content.identifier)
|
||||
}
|
||||
|
||||
// MARK: Helper Methods
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreServices
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
public class GiphyAsset: ProxiedContentAssetDescription {
|
||||
let rendition: Rendition
|
||||
@ -114,9 +114,9 @@ extension GiphyAsset {
|
||||
|
||||
public var utiType: String {
|
||||
switch self {
|
||||
case .jpg: return kUTTypeJPEG as String
|
||||
case .gif: return kUTTypeGIF as String
|
||||
case .mp4: return kUTTypeMPEG4 as String
|
||||
case .jpg: return UTType.jpeg.identifier
|
||||
case .gif: return UTType.gif.identifier
|
||||
case .mp4: return UTType.mpeg4Movie.identifier
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
import CoreServices
|
||||
import Foundation
|
||||
import ImageIO
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
@objc
|
||||
public class BadgeAssets: NSObject {
|
||||
@ -148,7 +149,7 @@ public class BadgeAssets: NSObject {
|
||||
guard !OWSFileSystem.fileOrFolderExists(url: destinationUrl) else { return }
|
||||
|
||||
guard let spriteImage = spriteParser.copySprite(variant: variant),
|
||||
let imageDestination = CGImageDestinationCreateWithURL(destinationUrl as CFURL, kUTTypePNG, 1, nil) else {
|
||||
let imageDestination = CGImageDestinationCreateWithURL(destinationUrl as CFURL, UTType.png.identifier as CFString, 1, nil) else {
|
||||
throw OWSAssertionError("Couldn't load image")
|
||||
}
|
||||
CGImageDestinationAddImage(imageDestination, spriteImage, nil)
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
import CoreServices
|
||||
import Foundation
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
public enum MimeType: String {
|
||||
case applicationJson = "application/json"
|
||||
@ -164,12 +165,14 @@ public class MimeTypeUtil: NSObject {
|
||||
|
||||
// MARK: - Conversion Functions for UTI Type / MIME Type / File Extension
|
||||
public static func utiTypeForMimeType(_ mimeType: String) -> String? {
|
||||
UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType as CFString, nil)?.takeRetainedValue() as String?
|
||||
UTType(mimeType: mimeType)?.identifier
|
||||
}
|
||||
|
||||
public static func utiTypeForFileExtension(_ fileExtension: String) -> String? {
|
||||
owsAssertDebug(!fileExtension.isEmpty)
|
||||
return UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension as CFString, nil)?.takeRetainedValue() as String?
|
||||
return UTType(filenameExtension: fileExtension)?.identifier
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func mimeTypeForFileExtension(_ fileExtension: String) -> String? {
|
||||
owsAssertDebug(!fileExtension.isEmpty)
|
||||
@ -183,7 +186,7 @@ public class MimeTypeUtil: NSObject {
|
||||
if utiType == "public.aac-audio" {
|
||||
return "m4a"
|
||||
} else {
|
||||
return UTTypeCopyPreferredTagWithClass(utiType as CFString, kUTTagClassFilenameExtension)?.takeRetainedValue() as String?
|
||||
return UTType(utiType)?.preferredFilenameExtension
|
||||
}
|
||||
}
|
||||
@objc
|
||||
|
||||
@ -8,6 +8,7 @@ import Intents
|
||||
import PureLayout
|
||||
import SignalServiceKit
|
||||
import SignalUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailedViewDelegate {
|
||||
|
||||
@ -574,8 +575,8 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
|
||||
// Handle safari sharing images and PDFs as two separate items one with the object to share and the other as the URL of the data.
|
||||
for extensionItem in extensionItems {
|
||||
for attachment in extensionItem.attachments ?? [] {
|
||||
if attachment.hasItemConformingToTypeIdentifier(kUTTypeData as String)
|
||||
|| attachment.hasItemConformingToTypeIdentifier(kUTTypeFileURL as String)
|
||||
if attachment.hasItemConformingToTypeIdentifier(UTType.data.identifier)
|
||||
|| attachment.hasItemConformingToTypeIdentifier(UTType.fileURL.identifier)
|
||||
|| attachment.hasItemConformingToTypeIdentifier("com.apple.pkpass") {
|
||||
return extensionItem
|
||||
}
|
||||
@ -599,23 +600,23 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
|
||||
var typeIdentifier: String {
|
||||
switch self {
|
||||
case .movie:
|
||||
return kUTTypeMovie as String
|
||||
return UTType.movie.identifier
|
||||
case .image:
|
||||
return kUTTypeImage as String
|
||||
return UTType.image.identifier
|
||||
case .webUrl:
|
||||
return kUTTypeURL as String
|
||||
return UTType.url.identifier
|
||||
case .fileUrl:
|
||||
return kUTTypeFileURL as String
|
||||
return UTType.fileURL.identifier
|
||||
case .contact:
|
||||
return kUTTypeVCard as String
|
||||
return UTType.vCard.identifier
|
||||
case .text:
|
||||
return kUTTypeText as String
|
||||
return UTType.text.identifier
|
||||
case .pdf:
|
||||
return kUTTypePDF as String
|
||||
return UTType.pdf.identifier
|
||||
case .pkPass:
|
||||
return "com.apple.pkpass"
|
||||
case .data:
|
||||
return kUTTypeData as String
|
||||
return UTType.data.identifier
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -710,9 +711,9 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
|
||||
let url: NSURL = try await Self.loadObjectWithKeyedUnarchiverFallback(fromItemProvider: itemProvider, forTypeIdentifier: typedItemProvider.itemType.typeIdentifier, cannotLoadError: .cannotLoadURLObject, failedLoadError: .loadURLObjectFailed)
|
||||
return try Self.createAttachment(withText: (url as URL).absoluteString)
|
||||
case .contact:
|
||||
let contactData = try await Self.loadDataRepresentation(fromItemProvider: itemProvider, forTypeIdentifier: kUTTypeContact as String)
|
||||
let dataSource = DataSourceValue.dataSource(with: contactData, utiType: kUTTypeContact as String)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: kUTTypeContact as String)
|
||||
let contactData = try await Self.loadDataRepresentation(fromItemProvider: itemProvider, forTypeIdentifier: UTType.contact.identifier)
|
||||
let dataSource = DataSourceValue.dataSource(with: contactData, utiType: UTType.contact.identifier)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: UTType.contact.identifier)
|
||||
attachment.isConvertibleToContactShare = true
|
||||
if let attachmentError = attachment.error {
|
||||
throw attachmentError
|
||||
@ -733,7 +734,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated private static func copyAttachment(fromUrl url: URL, defaultTypeIdentifier: String = kUTTypeData as String) throws -> SignalAttachment {
|
||||
nonisolated private static func copyAttachment(fromUrl url: URL, defaultTypeIdentifier: String = UTType.data.identifier) throws -> SignalAttachment {
|
||||
guard let dataSource = try? DataSourcePath.dataSource(with: url, shouldDeleteOnDeallocation: false) else {
|
||||
throw ShareViewControllerError.nonFileUrl
|
||||
}
|
||||
@ -843,7 +844,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
|
||||
|
||||
nonisolated private static func createAttachment(withText text: String) throws -> SignalAttachment {
|
||||
let dataSource = DataSourceValue.dataSource(withOversizeText: text)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: kUTTypeText as String)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: UTType.text.identifier)
|
||||
if let attachmentError = attachment.error {
|
||||
throw attachmentError
|
||||
}
|
||||
@ -855,9 +856,9 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
|
||||
guard let imagePng = image.pngData() else {
|
||||
throw ShareViewControllerError.uiImageMissingOrCorruptImageData
|
||||
}
|
||||
let typeIdentifier = kUTTypePNG as String
|
||||
let dataSource = DataSourceValue.dataSource(with: imagePng, utiType: typeIdentifier)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: typeIdentifier)
|
||||
let type = UTType.png
|
||||
let dataSource = DataSourceValue.dataSource(with: imagePng, utiType: type.identifier)
|
||||
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: type.identifier)
|
||||
if let attachmentError = attachment.error {
|
||||
throw attachmentError
|
||||
}
|
||||
|
||||
@ -684,21 +684,21 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
|
||||
}
|
||||
return dstImage
|
||||
}.map(on: DispatchQueue.global()) { (dstImage: UIImage) -> SignalAttachment in
|
||||
var dataUTI = kUTTypeImage as String
|
||||
var dataType = UTType.image
|
||||
guard let dstData: Data = {
|
||||
let isLossy: Bool = attachmentApprovalItem.attachment.mimeType.caseInsensitiveCompare(MimeType.imageJpeg.rawValue) == .orderedSame
|
||||
if isLossy {
|
||||
dataUTI = kUTTypeJPEG as String
|
||||
dataType = .jpeg
|
||||
return dstImage.jpegData(compressionQuality: 0.9)
|
||||
} else {
|
||||
dataUTI = kUTTypePNG as String
|
||||
dataType = .png
|
||||
return dstImage.pngData()
|
||||
}
|
||||
}() else {
|
||||
owsFailDebug("Could not export for output.")
|
||||
return attachmentApprovalItem.attachment
|
||||
}
|
||||
guard let dataSource = DataSourceValue.dataSource(with: dstData, utiType: dataUTI) else {
|
||||
guard let dataSource = DataSourceValue.dataSource(with: dstData, utiType: dataType.identifier) else {
|
||||
owsFailDebug("Could not prepare data source for output.")
|
||||
return attachmentApprovalItem.attachment
|
||||
}
|
||||
@ -706,13 +706,13 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
|
||||
// Rewrite the filename's extension to reflect the output file format.
|
||||
var filename: String? = attachmentApprovalItem.attachment.sourceFilename
|
||||
if let sourceFilename = attachmentApprovalItem.attachment.sourceFilename {
|
||||
if let fileExtension: String = MimeTypeUtil.fileExtensionForUtiType(dataUTI) {
|
||||
if let fileExtension: String = MimeTypeUtil.fileExtensionForUtiType(dataType.identifier) {
|
||||
filename = (sourceFilename as NSString).deletingPathExtension.appendingFileExtension(fileExtension)
|
||||
}
|
||||
}
|
||||
dataSource.sourceFilename = filename
|
||||
|
||||
let dstAttachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: dataUTI)
|
||||
let dstAttachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: dataType.identifier)
|
||||
if let attachmentError = dstAttachment.error {
|
||||
owsFailDebug("Could not prepare attachment for output: \(attachmentError).")
|
||||
return attachmentApprovalItem.attachment
|
||||
|
||||
Loading…
Reference in New Issue
Block a user