Rework preservation of attachment filenames.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 0746b1300d
commit c21a7673c8

@ -366,8 +366,8 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
} }
id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:url]; id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:url];
SignalAttachment *attachment = [dataSource setSourceFilename:filename];
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType filename:filename]; SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType];
if (!attachment) { if (!attachment) {
DDLogError(@"Application opened with URL with invalid content: %@", url); DDLogError(@"Application opened with URL with invalid content: %@", url);
[OWSAlerts showAlertWithTitle: [OWSAlerts showAlertWithTitle:

@ -71,17 +71,15 @@ class SignalAttachment: NSObject {
public var dataUrl: URL? { public var dataUrl: URL? {
return dataSource.dataUrl() return dataSource.dataUrl()
} }
public var sourceFilename: String? {
return dataSource.sourceFilename()
}
// Attachment types are identified using UTIs. // Attachment types are identified using UTIs.
// //
// See: https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html // See: https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html
let dataUTI: String let dataUTI: String
// An optional field that indicates the filename, if known, for this attachment.
//
// TODO: Try to eliminate this property.
let filename: String?
var error: SignalAttachmentError? { var error: SignalAttachmentError? {
didSet { didSet {
AssertIsOnMainThread() AssertIsOnMainThread()
@ -115,10 +113,9 @@ class SignalAttachment: NSObject {
// This method should not be called directly; use the factory // This method should not be called directly; use the factory
// methods instead. // methods instead.
internal required init(dataSource: DataSource, dataUTI: String, filename: String?) { internal required init(dataSource: DataSource, dataUTI: String) {
self.dataSource = dataSource self.dataSource = dataSource
self.dataUTI = dataUTI self.dataUTI = dataUTI
self.filename = filename
super.init() super.init()
} }
@ -165,7 +162,7 @@ class SignalAttachment: NSObject {
return "audio/aac" return "audio/aac"
} }
if let filename = filename { if let filename = sourceFilename {
let fileExtension = (filename as NSString).pathExtension let fileExtension = (filename as NSString).pathExtension
if fileExtension.characters.count > 0 { if fileExtension.characters.count > 0 {
if let mimeType = MIMETypeUtil.mimeType(forFileExtension:fileExtension) { if let mimeType = MIMETypeUtil.mimeType(forFileExtension:fileExtension) {
@ -192,7 +189,7 @@ class SignalAttachment: NSObject {
// Use the filename if known. If not, e.g. if the attachment was copy/pasted, we'll generate a filename // Use the filename if known. If not, e.g. if the attachment was copy/pasted, we'll generate a filename
// like: "signal-2017-04-24-095918.zip" // like: "signal-2017-04-24-095918.zip"
var filenameOrDefault: String { var filenameOrDefault: String {
if let filename = filename { if let filename = sourceFilename {
return filename return filename
} else { } else {
let kDefaultAttachmentName = "signal" let kDefaultAttachmentName = "signal"
@ -213,7 +210,7 @@ class SignalAttachment: NSObject {
// Returns the file extension for this attachment or nil if no file extension // Returns the file extension for this attachment or nil if no file extension
// can be identified. // can be identified.
var fileExtension: String? { var fileExtension: String? {
if let filename = filename { if let filename = sourceFilename {
let fileExtension = (filename as NSString).pathExtension let fileExtension = (filename as NSString).pathExtension
if fileExtension.characters.count > 0 { if fileExtension.characters.count > 0 {
return fileExtension return fileExtension
@ -378,7 +375,7 @@ class SignalAttachment: NSObject {
return nil return nil
} }
let dataSource = DataSourceValue.dataSource(with:data, utiType: dataUTI) let dataSource = DataSourceValue.dataSource(with:data, utiType: dataUTI)
return imageAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: nil) return imageAttachment(dataSource : dataSource, dataUTI : dataUTI)
} }
} }
for dataUTI in videoUTISet { for dataUTI in videoUTISet {
@ -388,7 +385,7 @@ class SignalAttachment: NSObject {
return nil return nil
} }
let dataSource = DataSourceValue.dataSource(with:data, utiType: dataUTI) let dataSource = DataSourceValue.dataSource(with:data, utiType: dataUTI)
return videoAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: nil) return videoAttachment(dataSource : dataSource, dataUTI : dataUTI)
} }
} }
for dataUTI in audioUTISet { for dataUTI in audioUTISet {
@ -398,7 +395,7 @@ class SignalAttachment: NSObject {
return nil return nil
} }
let dataSource = DataSourceValue.dataSource(with:data, utiType: dataUTI) let dataSource = DataSourceValue.dataSource(with:data, utiType: dataUTI)
return audioAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: nil) return audioAttachment(dataSource : dataSource, dataUTI : dataUTI)
} }
} }
@ -408,7 +405,7 @@ class SignalAttachment: NSObject {
return nil return nil
} }
let dataSource = DataSourceValue.dataSource(with:data, utiType: dataUTI) let dataSource = DataSourceValue.dataSource(with:data, utiType: dataUTI)
return genericAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: nil) return genericAttachment(dataSource : dataSource, dataUTI : dataUTI)
} }
// This method should only be called for dataUTIs that // This method should only be called for dataUTIs that
@ -436,17 +433,17 @@ class SignalAttachment: NSObject {
// //
// NOTE: The attachment returned by this method may not be valid. // NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property. // Check the attachment's error property.
private class func imageAttachment(dataSource: DataSource?, dataUTI: String, filename: String?) -> SignalAttachment { private class func imageAttachment(dataSource: DataSource?, dataUTI: String) -> SignalAttachment {
assert(dataUTI.characters.count > 0) assert(dataUTI.characters.count > 0)
assert(dataSource != nil) assert(dataSource != nil)
guard let dataSource = dataSource else { guard let dataSource = dataSource else {
let attachment = SignalAttachment(dataSource : DataSourceValue.emptyDataSource(), dataUTI: dataUTI, filename: filename) let attachment = SignalAttachment(dataSource : DataSourceValue.emptyDataSource(), dataUTI: dataUTI)
attachment.error = .missingData attachment.error = .missingData
return attachment return attachment
} }
let attachment = SignalAttachment(dataSource : dataSource, dataUTI: dataUTI, filename: filename) let attachment = SignalAttachment(dataSource : dataSource, dataUTI: dataUTI)
guard inputImageUTISet.contains(dataUTI) else { guard inputImageUTISet.contains(dataUTI) else {
attachment.error = .invalidFileFormat attachment.error = .invalidFileFormat
@ -480,7 +477,7 @@ class SignalAttachment: NSObject {
} }
Logger.verbose("\(TAG) Compressing attachment as image/jpeg") Logger.verbose("\(TAG) Compressing attachment as image/jpeg")
return compressImageAsJPEG(image : image, attachment : attachment, filename:filename) return compressImageAsJPEG(image : image, attachment : attachment, filename:dataSource.sourceFilename())
} }
} }
@ -520,13 +517,17 @@ class SignalAttachment: NSObject {
assert(dataUTI.characters.count > 0) assert(dataUTI.characters.count > 0)
guard let image = image else { guard let image = image else {
let attachment = SignalAttachment(dataSource : DataSourceValue.emptyDataSource(), dataUTI: dataUTI, filename: filename) let dataSource = DataSourceValue.emptyDataSource()
dataSource.setSourceFilename(filename)
let attachment = SignalAttachment(dataSource:dataSource, dataUTI: dataUTI)
attachment.error = .missingData attachment.error = .missingData
return attachment return attachment
} }
// Make a placeholder attachment on which to hang errors if necessary. // Make a placeholder attachment on which to hang errors if necessary.
let attachment = SignalAttachment(dataSource : DataSourceValue.emptyDataSource(), dataUTI: dataUTI, filename: filename) let dataSource = DataSourceValue.emptyDataSource()
dataSource.setSourceFilename(filename)
let attachment = SignalAttachment(dataSource : dataSource, dataUTI: dataUTI)
attachment.image = image attachment.image = image
Logger.verbose("\(TAG) Writing \(attachment.mimeType) as image/jpeg") Logger.verbose("\(TAG) Writing \(attachment.mimeType) as image/jpeg")
@ -555,9 +556,10 @@ class SignalAttachment: NSObject {
attachment.error = .couldNotConvertToJpeg attachment.error = .couldNotConvertToJpeg
return attachment return attachment
} }
dataSource.setSourceFilename(filename)
if UInt(jpgImageData.count) <= kMaxFileSizeImage { if UInt(jpgImageData.count) <= kMaxFileSizeImage {
let recompressedAttachment = SignalAttachment(dataSource : dataSource, dataUTI: kUTTypeJPEG as String, filename: filename) let recompressedAttachment = SignalAttachment(dataSource : dataSource, dataUTI: kUTTypeJPEG as String)
recompressedAttachment.image = dstImage recompressedAttachment.image = dstImage
return recompressedAttachment return recompressedAttachment
} }
@ -627,12 +629,11 @@ class SignalAttachment: NSObject {
// //
// NOTE: The attachment returned by this method may not be valid. // NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property. // Check the attachment's error property.
private class func videoAttachment(dataSource: DataSource?, dataUTI: String, filename: String?) -> SignalAttachment { private class func videoAttachment(dataSource: DataSource?, dataUTI: String) -> SignalAttachment {
return newAttachment(dataSource : dataSource, return newAttachment(dataSource : dataSource,
dataUTI : dataUTI, dataUTI : dataUTI,
validUTISet : videoUTISet, validUTISet : videoUTISet,
maxFileSize : kMaxFileSizeVideo, maxFileSize : kMaxFileSizeVideo)
filename : filename)
} }
// MARK: Audio Attachments // MARK: Audio Attachments
@ -641,12 +642,11 @@ class SignalAttachment: NSObject {
// //
// NOTE: The attachment returned by this method may not be valid. // NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property. // Check the attachment's error property.
private class func audioAttachment(dataSource: DataSource?, dataUTI: String, filename: String?) -> SignalAttachment { private class func audioAttachment(dataSource: DataSource?, dataUTI: String) -> SignalAttachment {
return newAttachment(dataSource : dataSource, return newAttachment(dataSource : dataSource,
dataUTI : dataUTI, dataUTI : dataUTI,
validUTISet : audioUTISet, validUTISet : audioUTISet,
maxFileSize : kMaxFileSizeAudio, maxFileSize : kMaxFileSizeAudio)
filename : filename)
} }
// MARK: Oversize Text Attachments // MARK: Oversize Text Attachments
@ -660,8 +660,7 @@ class SignalAttachment: NSObject {
return newAttachment(dataSource : dataSource, return newAttachment(dataSource : dataSource,
dataUTI : kOversizeTextAttachmentUTI, dataUTI : kOversizeTextAttachmentUTI,
validUTISet : nil, validUTISet : nil,
maxFileSize : kMaxFileSizeGeneric, maxFileSize : kMaxFileSizeGeneric)
filename : nil)
} }
// MARK: Generic Attachments // MARK: Generic Attachments
@ -670,18 +669,17 @@ class SignalAttachment: NSObject {
// //
// NOTE: The attachment returned by this method may not be valid. // NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property. // Check the attachment's error property.
private class func genericAttachment(dataSource: DataSource?, dataUTI: String, filename: String?) -> SignalAttachment { private class func genericAttachment(dataSource: DataSource?, dataUTI: String) -> SignalAttachment {
return newAttachment(dataSource : dataSource, return newAttachment(dataSource : dataSource,
dataUTI : dataUTI, dataUTI : dataUTI,
validUTISet : nil, validUTISet : nil,
maxFileSize : kMaxFileSizeGeneric, maxFileSize : kMaxFileSizeGeneric)
filename : filename)
} }
// MARK: Voice Messages // MARK: Voice Messages
public class func voiceMessageAttachment(dataSource: DataSource?, dataUTI: String, filename: String?) -> SignalAttachment { public class func voiceMessageAttachment(dataSource: DataSource?, dataUTI: String) -> SignalAttachment {
let attachment = audioAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: filename) let attachment = audioAttachment(dataSource : dataSource, dataUTI : dataUTI)
attachment.isVoiceMessage = true attachment.isVoiceMessage = true
return attachment return attachment
} }
@ -692,22 +690,21 @@ class SignalAttachment: NSObject {
// //
// NOTE: The attachment returned by this method may not be valid. // NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property. // Check the attachment's error property.
public class func attachment(dataSource: DataSource?, dataUTI: String, filename: String?) -> SignalAttachment { public class func attachment(dataSource: DataSource?, dataUTI: String) -> SignalAttachment {
if inputImageUTISet.contains(dataUTI) { if inputImageUTISet.contains(dataUTI) {
return imageAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: filename) return imageAttachment(dataSource : dataSource, dataUTI : dataUTI)
} else if videoUTISet.contains(dataUTI) { } else if videoUTISet.contains(dataUTI) {
return videoAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: filename) return videoAttachment(dataSource : dataSource, dataUTI : dataUTI)
} else if audioUTISet.contains(dataUTI) { } else if audioUTISet.contains(dataUTI) {
return audioAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: filename) return audioAttachment(dataSource : dataSource, dataUTI : dataUTI)
} else { } else {
return genericAttachment(dataSource : dataSource, dataUTI : dataUTI, filename: filename) return genericAttachment(dataSource : dataSource, dataUTI : dataUTI)
} }
} }
public class func empty() -> SignalAttachment { public class func empty() -> SignalAttachment {
return SignalAttachment.attachment(dataSource : DataSourceValue.emptyDataSource(), return SignalAttachment.attachment(dataSource : DataSourceValue.emptyDataSource(),
dataUTI: kUTTypeContent as String, dataUTI: kUTTypeContent as String)
filename:nil)
} }
// MARK: Helper Methods // MARK: Helper Methods
@ -715,18 +712,17 @@ class SignalAttachment: NSObject {
private class func newAttachment(dataSource: DataSource?, private class func newAttachment(dataSource: DataSource?,
dataUTI: String, dataUTI: String,
validUTISet: Set<String>?, validUTISet: Set<String>?,
maxFileSize: UInt, maxFileSize: UInt) -> SignalAttachment {
filename: String?) -> SignalAttachment {
assert(dataUTI.characters.count > 0) assert(dataUTI.characters.count > 0)
assert(dataSource != nil) assert(dataSource != nil)
guard let dataSource = dataSource else { guard let dataSource = dataSource else {
let attachment = SignalAttachment(dataSource : DataSourceValue.emptyDataSource(), dataUTI: dataUTI, filename: filename) let attachment = SignalAttachment(dataSource : DataSourceValue.emptyDataSource(), dataUTI: dataUTI)
attachment.error = .missingData attachment.error = .missingData
return attachment return attachment
} }
let attachment = SignalAttachment(dataSource : dataSource, dataUTI: dataUTI, filename: filename) let attachment = SignalAttachment(dataSource : dataSource, dataUTI: dataUTI)
if let validUTISet = validUTISet { if let validUTISet = validUTISet {
guard validUTISet.contains(dataUTI) else { guard validUTISet.contains(dataUTI) else {

@ -283,10 +283,10 @@ class AttachmentApprovalViewController: OWSViewController, OWSAudioAttachmentPla
} }
private func formattedFileName() -> String? { private func formattedFileName() -> String? {
guard let rawFilename = attachment.filename else { guard let sourceFilename = attachment.sourceFilename else {
return nil return nil
} }
let filename = rawFilename.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) let filename = sourceFilename.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
guard filename.characters.count > 0 else { guard filename.characters.count > 0 else {
return nil return nil
} }

@ -1675,7 +1675,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
if ([text lengthOfBytesUsingEncoding:NSUTF8StringEncoding] >= kOversizeTextMessageSizeThreshold) { if ([text lengthOfBytesUsingEncoding:NSUTF8StringEncoding] >= kOversizeTextMessageSizeThreshold) {
id<DataSource> _Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:text]; id<DataSource> _Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:text];
SignalAttachment *attachment = SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:kOversizeTextAttachmentUTI filename:nil]; [SignalAttachment attachmentWithDataSource:dataSource dataUTI:kOversizeTextAttachmentUTI];
message = message =
[ThreadUtil sendMessageWithAttachment:attachment inThread:self.thread messageSender:self.messageSender]; [ThreadUtil sendMessageWithAttachment:attachment inThread:self.thread messageSender:self.messageSender];
} else { } else {
@ -3207,8 +3207,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
OWSAssert(type); OWSAssert(type);
OWSAssert(filename); OWSAssert(filename);
id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:url]; id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:url];
SignalAttachment *attachment = [dataSource setSourceFilename:filename];
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:type filename:filename]; SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:type];
[self tryToSendAttachmentIfApproved:attachment]; [self tryToSendAttachmentIfApproved:attachment];
} }
@ -3226,13 +3226,17 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
picker.mediaTypes = @[ (__bridge NSString *)kUTTypeImage, (__bridge NSString *)kUTTypeMovie ]; picker.mediaTypes = @[ (__bridge NSString *)kUTTypeImage, (__bridge NSString *)kUTTypeMovie ];
picker.allowsEditing = NO; picker.allowsEditing = NO;
picker.delegate = self; picker.delegate = self;
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]]; [self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]];
}); });
}]; }];
} }
- (void)chooseFromLibrary - (void)chooseFromLibrary
{ {
OWSAssert([NSThread isMainThread]);
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
DDLogError(@"PhotoLibrary ImagePicker source not available"); DDLogError(@"PhotoLibrary ImagePicker source not available");
return; return;
@ -3242,9 +3246,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self; picker.delegate = self;
picker.mediaTypes = @[ (__bridge NSString *)kUTTypeImage, (__bridge NSString *)kUTTypeMovie ]; picker.mediaTypes = @[ (__bridge NSString *)kUTTypeImage, (__bridge NSString *)kUTTypeMovie ];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]]; [self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]];
});
} }
/* /*
@ -3376,8 +3379,9 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
id<DataSource> _Nullable dataSource = id<DataSource> _Nullable dataSource =
[DataSourceValue dataSourceWithData:imageData utiType:dataUTI]; [DataSourceValue dataSourceWithData:imageData utiType:dataUTI];
[dataSource setSourceFilename:filename];
SignalAttachment *attachment = SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:dataUTI filename:filename]; [SignalAttachment attachmentWithDataSource:dataSource dataUTI:dataUTI];
[self dismissViewControllerAnimated:YES [self dismissViewControllerAnimated:YES
completion:^{ completion:^{
OWSAssert([NSThread isMainThread]); OWSAssert([NSThread isMainThread]);
@ -3424,8 +3428,6 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
- (NSURL *)videoTempFolder - (NSURL *)videoTempFolder
{ {
NSString *temporaryDirectory = NSTemporaryDirectory(); NSString *temporaryDirectory = NSTemporaryDirectory();
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
// NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *videoDirPath = [temporaryDirectory stringByAppendingPathComponent:@"videos"]; NSString *videoDirPath = [temporaryDirectory stringByAppendingPathComponent:@"videos"];
if (![[NSFileManager defaultManager] fileExistsAtPath:videoDirPath]) { if (![[NSFileManager defaultManager] fileExistsAtPath:videoDirPath]) {
[[NSFileManager defaultManager] createDirectoryAtPath:videoDirPath [[NSFileManager defaultManager] createDirectoryAtPath:videoDirPath
@ -3436,10 +3438,24 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
return [NSURL fileURLWithPath:videoDirPath]; return [NSURL fileURLWithPath:videoDirPath];
} }
- (NSUInteger)sizeOfFileURL:(NSURL *)movieURL
{
NSError *error;
NSDictionary<NSFileAttributeKey, id> *_Nullable attributes =
[[NSFileManager defaultManager] attributesOfItemAtPath:movieURL.path error:&error];
OWSAssert(attributes);
OWSAssert(!error);
uint64_t fileSize = [attributes fileSize];
return (NSUInteger)fileSize;
}
- (void)sendQualityAdjustedAttachmentForVideo:(NSURL *)movieURL - (void)sendQualityAdjustedAttachmentForVideo:(NSURL *)movieURL
filename:(NSString *)filename filename:(NSString *)filename
skipApprovalDialog:(BOOL)skipApprovalDialog skipApprovalDialog:(BOOL)skipApprovalDialog
{ {
OWSAssert([NSThread isMainThread]);
DDLogError(@"movieURL: %@ %zd", movieURL, [self sizeOfFileURL:movieURL]);
AVAsset *video = [AVAsset assetWithURL:movieURL]; AVAsset *video = [AVAsset assetWithURL:movieURL];
AVAssetExportSession *exportSession = AVAssetExportSession *exportSession =
[AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPresetMediumQuality]; [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPresetMediumQuality];
@ -3449,11 +3465,12 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
URLByAppendingPathComponent:[[[NSUUID UUID] UUIDString] stringByAppendingPathExtension:@"mp4"]]; URLByAppendingPathComponent:[[[NSUUID UUID] UUIDString] stringByAppendingPathExtension:@"mp4"]];
exportSession.outputURL = compressedVideoUrl; exportSession.outputURL = compressedVideoUrl;
[exportSession exportAsynchronouslyWithCompletionHandler:^{ [exportSession exportAsynchronouslyWithCompletionHandler:^{
DDLogError(@"compressedVideoUrl: %@ %zd", compressedVideoUrl, [self sizeOfFileURL:compressedVideoUrl]);
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:compressedVideoUrl]; id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:compressedVideoUrl];
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource [dataSource setSourceFilename:filename];
dataUTI:(NSString *)kUTTypeMPEG4 SignalAttachment *attachment =
filename:filename]; [SignalAttachment attachmentWithDataSource:dataSource dataUTI:(NSString *)kUTTypeMPEG4];
if (!attachment || [attachment hasError]) { if (!attachment || [attachment hasError]) {
DDLogError(@"%@ %s Invalid attachment: %@.", DDLogError(@"%@ %s Invalid attachment: %@.",
self.tag, self.tag,
@ -3832,10 +3849,9 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
NSString *filename = [NSLocalizedString(@"VOICE_MESSAGE_FILE_NAME", @"Filename for voice messages.") NSString *filename = [NSLocalizedString(@"VOICE_MESSAGE_FILE_NAME", @"Filename for voice messages.")
stringByAppendingPathExtension:@"m4a"]; stringByAppendingPathExtension:@"m4a"];
[dataSource setSourceFilename:filename];
SignalAttachment *attachment = [SignalAttachment voiceMessageAttachmentWithDataSource:dataSource SignalAttachment *attachment =
dataUTI:(NSString *)kUTTypeMPEG4Audio [SignalAttachment voiceMessageAttachmentWithDataSource:dataSource dataUTI:(NSString *)kUTTypeMPEG4Audio];
filename:filename];
if (!attachment || [attachment hasError]) { if (!attachment || [attachment hasError]) {
DDLogWarn(@"%@ %s Invalid attachment: %@.", DDLogWarn(@"%@ %s Invalid attachment: %@.",
self.tag, self.tag,

@ -328,11 +328,11 @@ NS_ASSUME_NONNULL_BEGIN
NSString *filename = [filePath lastPathComponent]; NSString *filename = [filePath lastPathComponent];
NSString *utiType = [MIMETypeUtil utiTypeForFileExtension:filename.pathExtension]; NSString *utiType = [MIMETypeUtil utiTypeForFileExtension:filename.pathExtension];
id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithFilePath:filePath]; id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithFilePath:filePath];
SignalAttachment *attachment = [dataSource setSourceFilename:filename];
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType filename:filename]; SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType];
OWSAssert(attachment); OWSAssert(attachment);
if ([attachment hasError]) { if ([attachment hasError]) {
DDLogError(@"attachment[%@]: %@", [attachment filename], [attachment errorName]); DDLogError(@"attachment[%@]: %@", [attachment sourceFilename], [attachment errorName]);
[DDLog flushLog]; [DDLog flushLog];
} }
OWSAssert(![attachment hasError]); OWSAssert(![attachment hasError]);
@ -589,7 +589,7 @@ NS_ASSUME_NONNULL_BEGIN
id<DataSource> _Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:message]; id<DataSource> _Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:message];
SignalAttachment *attachment = SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:kOversizeTextAttachmentUTI filename:nil]; [SignalAttachment attachmentWithDataSource:dataSource dataUTI:kOversizeTextAttachmentUTI];
[ThreadUtil sendMessageWithAttachment:attachment inThread:thread messageSender:messageSender]; [ThreadUtil sendMessageWithAttachment:attachment inThread:thread messageSender:messageSender];
} }
@ -615,7 +615,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSMessageSender *messageSender = [Environment getCurrent].messageSender; OWSMessageSender *messageSender = [Environment getCurrent].messageSender;
id<DataSource> _Nullable dataSource = id<DataSource> _Nullable dataSource =
[DataSourceValue dataSourceWithData:[self createRandomNSDataOfSize:length] utiType:uti]; [DataSourceValue dataSourceWithData:[self createRandomNSDataOfSize:length] utiType:uti];
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:uti filename:nil]; SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:uti];
[ThreadUtil sendMessageWithAttachment:attachment inThread:thread messageSender:messageSender ignoreErrors:YES]; [ThreadUtil sendMessageWithAttachment:attachment inThread:thread messageSender:messageSender ignoreErrors:YES];
} }
+ (OWSSignalServiceProtosEnvelope *)createEnvelopeForThread:(TSThread *)thread + (OWSSignalServiceProtosEnvelope *)createEnvelopeForThread:(TSThread *)thread

@ -141,8 +141,9 @@ NS_ASSUME_NONNULL_BEGIN
// //
// TODO: If we reuse this VC, for example to offer a "forward attachment to other thread", // TODO: If we reuse this VC, for example to offer a "forward attachment to other thread",
// feature, this assumption would no longer apply. // feature, this assumption would no longer apply.
OWSAssert(self.attachment) NSString *filename = OWSAssert(self.attachment);
[self.attachment.filename stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; NSString *filename =
[self.attachment.sourceFilename stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
OWSAssert(filename.length > 0); OWSAssert(filename.length > 0);
const NSUInteger kMaxFilenameLength = 20; const NSUInteger kMaxFilenameLength = 20;
if (filename.length > kMaxFilenameLength) { if (filename.length > kMaxFilenameLength) {

@ -45,6 +45,9 @@ NS_ASSUME_NONNULL_BEGIN
// Returns YES on success. // Returns YES on success.
- (BOOL)writeToPath:(NSString *)dstFilePath; - (BOOL)writeToPath:(NSString *)dstFilePath;
- (nullable NSString *)sourceFilename;
- (void)setSourceFilename:(NSString *_Nullable)sourceFilename;
@end @end
#pragma mark - #pragma mark -

@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN
// This property is lazy-populated. // This property is lazy-populated.
@property (nonatomic) NSString *cachedFilePath; @property (nonatomic) NSString *cachedFilePath;
@property (nonatomic, nullable) NSString *sourceFilename;
@end @end
#pragma mark - #pragma mark -
@ -153,6 +155,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) NSData *cachedData; @property (nonatomic) NSData *cachedData;
@property (nonatomic) NSNumber *cachedDataLength; @property (nonatomic) NSNumber *cachedDataLength;
@property (nonatomic, nullable) NSString *sourceFilename;
@end @end
#pragma mark - #pragma mark -

Loading…
Cancel
Save