Merge branch 'charlesmchen/lazyLoadAttachmentsCR'
This commit is contained in:
commit
90eebb3d7d
@ -369,7 +369,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||
return NO;
|
||||
}
|
||||
|
||||
id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:url];
|
||||
DataSource *_Nullable dataSource = [DataSourcePath dataSourceWithURL:url];
|
||||
if (!dataSource) {
|
||||
DDLogError(@"Application opened with URL with unloadable content: %@", url);
|
||||
[OWSAlerts showAlertWithTitle:
|
||||
|
||||
@ -72,7 +72,10 @@ class SignalAttachment: NSObject {
|
||||
return dataSource.dataUrl()
|
||||
}
|
||||
public var sourceFilename: String? {
|
||||
return dataSource.sourceFilename()
|
||||
return dataSource.sourceFilename
|
||||
}
|
||||
public var isValidImage: Bool {
|
||||
return dataSource.isValidImage()
|
||||
}
|
||||
|
||||
// Attachment types are identified using UTIs.
|
||||
@ -288,18 +291,6 @@ class SignalAttachment: NSObject {
|
||||
return SignalAttachment.audioUTISet.contains(dataUTI)
|
||||
}
|
||||
|
||||
public var isValidImage: Bool {
|
||||
if let dataPath = dataSource.dataPathIfOnDisk() {
|
||||
// if ows_isValidImage is given a file path, it will
|
||||
// avoid loading most of the data into memory, which
|
||||
// is considerably more performant, so try to do that.
|
||||
return NSData.ows_isValidImage(atPath:dataPath)
|
||||
}
|
||||
|
||||
let data = dataSource.data()
|
||||
return (data as NSData).ows_isValidImage()
|
||||
}
|
||||
|
||||
public class func pasteboardHasPossibleAttachment() -> Bool {
|
||||
return UIPasteboard.general.numberOfItems > 0
|
||||
}
|
||||
@ -471,7 +462,7 @@ class SignalAttachment: NSObject {
|
||||
}
|
||||
|
||||
Logger.verbose("\(TAG) Compressing attachment as image/jpeg")
|
||||
return compressImageAsJPEG(image : image, attachment : attachment, filename:dataSource.sourceFilename())
|
||||
return compressImageAsJPEG(image : image, attachment : attachment, filename:dataSource.sourceFilename)
|
||||
}
|
||||
}
|
||||
|
||||
@ -512,7 +503,7 @@ class SignalAttachment: NSObject {
|
||||
|
||||
guard let image = image else {
|
||||
let dataSource = DataSourceValue.emptyDataSource()
|
||||
dataSource.setSourceFilename(filename)
|
||||
dataSource.sourceFilename = filename
|
||||
let attachment = SignalAttachment(dataSource:dataSource, dataUTI: dataUTI)
|
||||
attachment.error = .missingData
|
||||
return attachment
|
||||
@ -520,7 +511,7 @@ class SignalAttachment: NSObject {
|
||||
|
||||
// Make a placeholder attachment on which to hang errors if necessary.
|
||||
let dataSource = DataSourceValue.emptyDataSource()
|
||||
dataSource.setSourceFilename(filename)
|
||||
dataSource.sourceFilename = filename
|
||||
let attachment = SignalAttachment(dataSource : dataSource, dataUTI: dataUTI)
|
||||
attachment.image = image
|
||||
|
||||
@ -550,7 +541,7 @@ class SignalAttachment: NSObject {
|
||||
attachment.error = .couldNotConvertToJpeg
|
||||
return attachment
|
||||
}
|
||||
dataSource.setSourceFilename(filename)
|
||||
dataSource.sourceFilename = filename
|
||||
|
||||
if UInt(jpgImageData.count) <= kMaxFileSizeImage {
|
||||
let recompressedAttachment = SignalAttachment(dataSource : dataSource, dataUTI: kUTTypeJPEG as String)
|
||||
|
||||
@ -1681,7 +1681,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
BOOL didAddToProfileWhitelist = [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
|
||||
TSOutgoingMessage *message;
|
||||
if ([text lengthOfBytesUsingEncoding:NSUTF8StringEncoding] >= kOversizeTextMessageSizeThreshold) {
|
||||
id<DataSource> _Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:text];
|
||||
DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:text];
|
||||
SignalAttachment *attachment =
|
||||
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:kOversizeTextAttachmentUTI];
|
||||
message =
|
||||
@ -3206,7 +3206,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
|
||||
OWSAssert(type);
|
||||
OWSAssert(filename);
|
||||
id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:url];
|
||||
DataSource *_Nullable dataSource = [DataSourcePath dataSourceWithURL:url];
|
||||
if (!dataSource) {
|
||||
OWSFail(@"%@ attachment data was unexpectedly empty for picked document url: %@", self.tag, url);
|
||||
|
||||
@ -3386,7 +3386,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
}
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
id<DataSource> _Nullable dataSource =
|
||||
DataSource *_Nullable dataSource =
|
||||
[DataSourceValue dataSourceWithData:imageData utiType:dataUTI];
|
||||
[dataSource setSourceFilename:filename];
|
||||
SignalAttachment *attachment =
|
||||
@ -3477,9 +3477,11 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
}
|
||||
|
||||
[modalActivityIndicator dismissWithCompletion:^{
|
||||
id<DataSource> _Nullable dataSource =
|
||||
DataSource *_Nullable dataSource =
|
||||
[DataSourcePath dataSourceWithURL:compressedVideoUrl];
|
||||
[dataSource setSourceFilename:filename];
|
||||
// Remove temporary file when complete.
|
||||
[dataSource setShouldDeleteOnDeallocation];
|
||||
SignalAttachment *attachment =
|
||||
[SignalAttachment attachmentWithDataSource:dataSource
|
||||
dataUTI:(NSString *)kUTTypeMPEG4];
|
||||
@ -3523,6 +3525,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
|
||||
- (void)yapDatabaseModified:(NSNotification *)notification
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
// Currently, we update thread and message state every time
|
||||
// the database is modified. That doesn't seem optimal, but
|
||||
// in practice it's efficient enough.
|
||||
@ -3642,6 +3646,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
}
|
||||
}
|
||||
completion:^(BOOL success) {
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
if (!success) {
|
||||
[self resetContentAndLayout];
|
||||
}
|
||||
@ -3859,7 +3865,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithURL:self.audioRecorder.url];
|
||||
DataSource *_Nullable dataSource = [DataSourcePath dataSourceWithURL:self.audioRecorder.url];
|
||||
self.audioRecorder = nil;
|
||||
|
||||
if (!dataSource) {
|
||||
@ -3871,6 +3877,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
NSString *filename = [NSLocalizedString(@"VOICE_MESSAGE_FILE_NAME", @"Filename for voice messages.")
|
||||
stringByAppendingPathExtension:@"m4a"];
|
||||
[dataSource setSourceFilename:filename];
|
||||
// Remove temporary file when complete.
|
||||
[dataSource setShouldDeleteOnDeallocation];
|
||||
SignalAttachment *attachment =
|
||||
[SignalAttachment voiceMessageAttachmentWithDataSource:dataSource dataUTI:(NSString *)kUTTypeMPEG4Audio];
|
||||
if (!attachment || [attachment hasError]) {
|
||||
@ -4091,7 +4099,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
||||
|
||||
if (newGroupModel.groupImage) {
|
||||
NSData *data = UIImagePNGRepresentation(newGroupModel.groupImage);
|
||||
id<DataSource> _Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
||||
DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
||||
[self.messageSender sendAttachmentData:dataSource
|
||||
contentType:OWSMimeTypeImagePng
|
||||
sourceFilename:nil
|
||||
|
||||
@ -325,7 +325,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSMessageSender *messageSender = [Environment getCurrent].messageSender;
|
||||
NSString *filename = [filePath lastPathComponent];
|
||||
NSString *utiType = [MIMETypeUtil utiTypeForFileExtension:filename.pathExtension];
|
||||
id<DataSource> _Nullable dataSource = [DataSourcePath dataSourceWithFilePath:filePath];
|
||||
DataSource *_Nullable dataSource = [DataSourcePath dataSourceWithFilePath:filePath];
|
||||
[dataSource setSourceFilename:filename];
|
||||
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType];
|
||||
OWSAssert(attachment);
|
||||
@ -585,7 +585,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@"lorem, in rhoncus nisi."];
|
||||
}
|
||||
|
||||
id<DataSource> _Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:message];
|
||||
DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:message];
|
||||
SignalAttachment *attachment =
|
||||
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:kOversizeTextAttachmentUTI];
|
||||
[ThreadUtil sendMessageWithAttachment:attachment inThread:thread messageSender:messageSender];
|
||||
@ -611,7 +611,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
+ (void)sendRandomAttachment:(TSThread *)thread uti:(NSString *)uti length:(NSUInteger)length
|
||||
{
|
||||
OWSMessageSender *messageSender = [Environment getCurrent].messageSender;
|
||||
id<DataSource> _Nullable dataSource =
|
||||
DataSource *_Nullable dataSource =
|
||||
[DataSourceValue dataSourceWithData:[self createRandomNSDataOfSize:length] utiType:uti];
|
||||
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:uti];
|
||||
[ThreadUtil sendMessageWithAttachment:attachment inThread:thread messageSender:messageSender ignoreErrors:YES];
|
||||
|
||||
@ -497,7 +497,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
|
||||
|
||||
if (model.groupImage) {
|
||||
NSData *data = UIImagePNGRepresentation(model.groupImage);
|
||||
id<DataSource> _Nullable dataSource =
|
||||
DataSource *_Nullable dataSource =
|
||||
[DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
||||
[self.messageSender sendAttachmentData:dataSource
|
||||
contentType:OWSMimeTypeImagePng
|
||||
|
||||
@ -113,7 +113,7 @@ NSString *const kTSStorageManagerOWSContactsSyncingLastMessageKey =
|
||||
|
||||
self.isRequestInFlight = YES;
|
||||
|
||||
id<DataSource> dataSource =
|
||||
DataSource *dataSource =
|
||||
[DataSourceValue dataSourceWithSyncMessage:[syncContactsMessage buildPlainTextAttachmentData]];
|
||||
[self.messageSender sendTemporaryAttachmentData:dataSource
|
||||
contentType:OWSMimeTypeApplicationOctetStream
|
||||
|
||||
@ -44,7 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (nullable NSData *)readDataFromFileWithError:(NSError **)error;
|
||||
- (BOOL)writeData:(NSData *)data error:(NSError **)error;
|
||||
- (BOOL)writeDataSource:(id<DataSource>)dataSource;
|
||||
- (BOOL)writeDataSource:(DataSource *)dataSource;
|
||||
|
||||
+ (void)deleteAttachments;
|
||||
+ (NSString *)attachmentsFolder;
|
||||
|
||||
@ -158,7 +158,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return [data writeToFile:filePath options:0 error:error];
|
||||
}
|
||||
|
||||
- (BOOL)writeDataSource:(id<DataSource>)dataSource
|
||||
- (BOOL)writeDataSource:(DataSource *)dataSource
|
||||
{
|
||||
OWSAssert(dataSource);
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ NS_SWIFT_NAME(MessageSender)
|
||||
* Takes care of allocating and uploading the attachment, then sends the message.
|
||||
* Only necessary to call once. If sending fails, retry with `sendMessage:`.
|
||||
*/
|
||||
- (void)sendAttachmentData:(id<DataSource>)dataSource
|
||||
- (void)sendAttachmentData:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
sourceFilename:(nullable NSString *)sourceFilename
|
||||
inMessage:(TSOutgoingMessage *)outgoingMessage
|
||||
@ -83,7 +83,7 @@ NS_SWIFT_NAME(MessageSender)
|
||||
* Same as `sendAttachmentData:`, but deletes the local copy of the attachment after sending.
|
||||
* Used for sending sync request data, not for user visible attachments.
|
||||
*/
|
||||
- (void)sendTemporaryAttachmentData:(id<DataSource>)dataSource
|
||||
- (void)sendTemporaryAttachmentData:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
inMessage:(TSOutgoingMessage *)outgoingMessage
|
||||
success:(void (^)())successHandler
|
||||
|
||||
@ -486,7 +486,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
failure:failureHandler];
|
||||
}
|
||||
|
||||
- (void)sendTemporaryAttachmentData:(id<DataSource>)dataSource
|
||||
- (void)sendTemporaryAttachmentData:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
inMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)())successHandler
|
||||
@ -516,7 +516,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
failure:failureWithDeleteHandler];
|
||||
}
|
||||
|
||||
- (void)sendAttachmentData:(id<DataSource>)dataSource
|
||||
- (void)sendAttachmentData:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
sourceFilename:(nullable NSString *)sourceFilename
|
||||
inMessage:(TSOutgoingMessage *)message
|
||||
|
||||
@ -743,7 +743,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[[OWSSyncContactsMessage alloc] initWithSignalAccounts:self.contactsManager.signalAccounts
|
||||
identityManager:self.identityManager
|
||||
profileManager:self.profileManager];
|
||||
id<DataSource> dataSource =
|
||||
DataSource *dataSource =
|
||||
[DataSourceValue dataSourceWithSyncMessage:[syncContactsMessage buildPlainTextAttachmentData]];
|
||||
[self.messageSender sendTemporaryAttachmentData:dataSource
|
||||
contentType:OWSMimeTypeApplicationOctetStream
|
||||
@ -756,7 +756,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}];
|
||||
} else if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeGroups) {
|
||||
OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] init];
|
||||
id<DataSource> dataSource =
|
||||
DataSource *dataSource =
|
||||
[DataSourceValue dataSourceWithSyncMessage:[syncGroupsMessage buildPlainTextAttachmentData]];
|
||||
[self.messageSender sendTemporaryAttachmentData:dataSource
|
||||
contentType:OWSMimeTypeApplicationOctetStream
|
||||
@ -882,7 +882,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
if (gThread.groupModel.groupImage) {
|
||||
NSData *data = UIImagePNGRepresentation(gThread.groupModel.groupImage);
|
||||
id<DataSource> _Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
||||
DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
||||
[self.messageSender sendAttachmentData:dataSource
|
||||
contentType:OWSMimeTypeImagePng
|
||||
sourceFilename:nil
|
||||
|
||||
@ -9,7 +9,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
//
|
||||
// * Lazy-load if possible.
|
||||
// * Avoid duplicate reads & writes.
|
||||
@protocol DataSource
|
||||
@interface DataSource : NSObject
|
||||
|
||||
@property (nonatomic, nullable) NSString *sourceFilename;
|
||||
|
||||
// Should not be called unless necessary as it can involve an expensive read.
|
||||
- (NSData *)data;
|
||||
@ -21,50 +23,43 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// Will only return nil in the error case.
|
||||
- (nullable NSURL *)dataUrl;
|
||||
|
||||
// The file path for the data, if it already exists on disk.
|
||||
//
|
||||
// This method is safe to call as it will not do any expensive reads or writes.
|
||||
//
|
||||
// May return nil if the data does not (yet) reside on disk.
|
||||
//
|
||||
// Use dataUrl instead if you need to access the data; it will
|
||||
// ensure the data is on disk and return a URL, barring an error.
|
||||
- (nullable NSString *)dataPathIfOnDisk;
|
||||
|
||||
// Will return zero in the error case.
|
||||
- (NSUInteger)dataLength;
|
||||
|
||||
// Returns YES on success.
|
||||
- (BOOL)writeToPath:(NSString *)dstFilePath;
|
||||
|
||||
- (nullable NSString *)sourceFilename;
|
||||
- (void)setSourceFilename:(NSString *_Nullable)sourceFilename;
|
||||
// If called, this data source will try to delete its on-disk contents
|
||||
// when it is deallocated.
|
||||
- (void)setShouldDeleteOnDeallocation;
|
||||
|
||||
- (BOOL)isValidImage;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface DataSourceValue : NSObject <DataSource>
|
||||
@interface DataSourceValue : DataSource
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithData:(NSData *)data fileExtension:(NSString *)fileExtension;
|
||||
+ (nullable DataSource *)dataSourceWithData:(NSData *)data fileExtension:(NSString *)fileExtension;
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithData:(NSData *)data utiType:(NSString *)utiType;
|
||||
+ (nullable DataSource *)dataSourceWithData:(NSData *)data utiType:(NSString *)utiType;
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithOversizeText:(NSString *_Nullable)text;
|
||||
+ (nullable DataSource *)dataSourceWithOversizeText:(NSString *_Nullable)text;
|
||||
|
||||
+ (id<DataSource>)dataSourceWithSyncMessage:(NSData *)data;
|
||||
+ (DataSource *)dataSourceWithSyncMessage:(NSData *)data;
|
||||
|
||||
+ (id<DataSource>)emptyDataSource;
|
||||
+ (DataSource *)emptyDataSource;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface DataSourcePath : NSObject <DataSource>
|
||||
@interface DataSourcePath : DataSource
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithURL:(NSURL *)fileUrl;
|
||||
+ (nullable DataSource *)dataSourceWithURL:(NSURL *)fileUrl;
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithFilePath:(NSString *)filePath;
|
||||
+ (nullable DataSource *)dataSourceWithFilePath:(NSString *)filePath;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -4,9 +4,94 @@
|
||||
|
||||
#import "DataSource.h"
|
||||
#import "MIMETypeUtil.h"
|
||||
#import "NSData+Image.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DataSource ()
|
||||
|
||||
@property (nonatomic) BOOL shouldDeleteOnDeallocation;
|
||||
|
||||
// The file path for the data, if it already exists on disk.
|
||||
//
|
||||
// This method is safe to call as it will not do any expensive reads or writes.
|
||||
//
|
||||
// May return nil if the data does not (yet) reside on disk.
|
||||
//
|
||||
// Use dataUrl instead if you need to access the data; it will
|
||||
// ensure the data is on disk and return a URL, barring an error.
|
||||
- (nullable NSString *)dataPathIfOnDisk;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation DataSource
|
||||
|
||||
- (NSData *)data
|
||||
{
|
||||
OWSFail(@"%@ Missing required method: data", self.tag);
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable NSURL *)dataUrl
|
||||
{
|
||||
OWSFail(@"%@ Missing required method: dataUrl", self.tag);
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable NSString *)dataPathIfOnDisk
|
||||
{
|
||||
OWSFail(@"%@ Missing required method: dataPathIfOnDisk", self.tag);
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSUInteger)dataLength
|
||||
{
|
||||
OWSFail(@"%@ Missing required method: dataLength", self.tag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (BOOL)writeToPath:(NSString *)dstFilePath
|
||||
{
|
||||
OWSFail(@"%@ Missing required method: writeToPath:", self.tag);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setShouldDeleteOnDeallocation
|
||||
{
|
||||
self.shouldDeleteOnDeallocation = YES;
|
||||
}
|
||||
|
||||
- (BOOL)isValidImage
|
||||
{
|
||||
NSString *_Nullable dataPath = [self dataPathIfOnDisk];
|
||||
if (dataPath) {
|
||||
// if ows_isValidImage is given a file path, it will
|
||||
// avoid loading most of the data into memory, which
|
||||
// is considerably more performant, so try to do that.
|
||||
return [NSData ows_isValidImageAtPath:dataPath];
|
||||
}
|
||||
NSData *data = [self data];
|
||||
return [data ows_isValidImage];
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
+ (NSString *)tag
|
||||
{
|
||||
return [NSString stringWithFormat:@"[%@]", self.class];
|
||||
}
|
||||
|
||||
- (NSString *)tag
|
||||
{
|
||||
return self.class.tag;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface DataSourceValue ()
|
||||
|
||||
@property (nonatomic) NSData *dataValue;
|
||||
@ -16,15 +101,29 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// This property is lazy-populated.
|
||||
@property (nonatomic) NSString *cachedFilePath;
|
||||
|
||||
@property (nonatomic, nullable) NSString *sourceFilename;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation DataSourceValue
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithData:(NSData *)data fileExtension:(NSString *)fileExtension
|
||||
- (void)dealloc
|
||||
{
|
||||
if (self.shouldDeleteOnDeallocation) {
|
||||
NSString *filePath = self.cachedFilePath;
|
||||
if (filePath) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSError *error;
|
||||
BOOL success = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
|
||||
if (!success || error) {
|
||||
OWSCFail(@"DataSourceValue could not delete file: %@, %@", filePath, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (nullable DataSource *)dataSourceWithData:(NSData *)data fileExtension:(NSString *)fileExtension
|
||||
{
|
||||
OWSAssert(data);
|
||||
|
||||
@ -35,19 +134,19 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
DataSourceValue *instance = [DataSourceValue new];
|
||||
instance.dataValue = data;
|
||||
instance.fileExtension = fileExtension;
|
||||
// Always try to clean up temp files created by this instance.
|
||||
[instance setShouldDeleteOnDeallocation];
|
||||
return instance;
|
||||
}
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithData:(NSData *)data utiType:(NSString *)utiType
|
||||
+ (nullable DataSource *)dataSourceWithData:(NSData *)data utiType:(NSString *)utiType
|
||||
{
|
||||
NSString *fileExtension = [MIMETypeUtil fileExtensionForUTIType:utiType];
|
||||
return [self dataSourceWithData:data fileExtension:fileExtension];
|
||||
}
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithOversizeText:(NSString *_Nullable)text
|
||||
+ (nullable DataSource *)dataSourceWithOversizeText:(NSString *_Nullable)text
|
||||
{
|
||||
OWSAssert(text);
|
||||
|
||||
if (!text) {
|
||||
return nil;
|
||||
}
|
||||
@ -56,12 +155,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return [self dataSourceWithData:data fileExtension:kOversizeTextAttachmentFileExtension];
|
||||
}
|
||||
|
||||
+ (id<DataSource>)dataSourceWithSyncMessage:(NSData *)data
|
||||
+ (DataSource *)dataSourceWithSyncMessage:(NSData *)data
|
||||
{
|
||||
return [self dataSourceWithData:data fileExtension:kSyncMessageFileExtension];
|
||||
}
|
||||
|
||||
+ (id<DataSource>)emptyDataSource
|
||||
+ (DataSource *)emptyDataSource
|
||||
{
|
||||
return [self dataSourceWithData:[NSData new] fileExtension:@"bin"];
|
||||
}
|
||||
@ -89,7 +188,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
NSString *dirPath = NSTemporaryDirectory();
|
||||
NSString *fileName = [[[NSUUID UUID] UUIDString] stringByAppendingPathExtension:self.fileExtension];
|
||||
NSString *filePath = [dirPath stringByAppendingPathComponent:fileName];
|
||||
DDLogError(@"%@ ---- writing data", self.tag);
|
||||
if ([self writeToPath:filePath]) {
|
||||
self.cachedFilePath = filePath;
|
||||
} else {
|
||||
@ -155,15 +253,29 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic) NSData *cachedData;
|
||||
@property (nonatomic) NSNumber *cachedDataLength;
|
||||
|
||||
@property (nonatomic, nullable) NSString *sourceFilename;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation DataSourcePath
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithURL:(NSURL *)fileUrl;
|
||||
- (void)dealloc
|
||||
{
|
||||
if (self.shouldDeleteOnDeallocation) {
|
||||
NSString *filePath = self.filePath;
|
||||
if (filePath) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSError *error;
|
||||
BOOL success = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
|
||||
if (!success || error) {
|
||||
OWSCFail(@"DataSourcePath could not delete file: %@, %@", filePath, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (nullable DataSource *)dataSourceWithURL:(NSURL *)fileUrl;
|
||||
{
|
||||
OWSAssert(fileUrl);
|
||||
|
||||
@ -175,7 +287,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return instance;
|
||||
}
|
||||
|
||||
+ (nullable id<DataSource>)dataSourceWithFilePath:(NSString *)filePath;
|
||||
+ (nullable DataSource *)dataSourceWithFilePath:(NSString *)filePath;
|
||||
{
|
||||
OWSAssert(filePath);
|
||||
|
||||
@ -238,7 +350,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
NSDictionary<NSFileAttributeKey, id> *_Nullable attributes =
|
||||
[[NSFileManager defaultManager] attributesOfItemAtPath:self.filePath error:&error];
|
||||
if (!attributes || error) {
|
||||
OWSFail(@"%@ Could not read data length from disk: %@", self.tag, self.filePath);
|
||||
OWSFail(@"%@ Could not read data length from disk: %@, %@", self.tag, self.filePath, error);
|
||||
self.cachedDataLength = @(0);
|
||||
} else {
|
||||
uint64_t fileSize = [attributes fileSize];
|
||||
@ -256,7 +368,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
NSError *error;
|
||||
BOOL success = [[NSFileManager defaultManager] copyItemAtPath:self.filePath toPath:dstFilePath error:&error];
|
||||
if (!success || error) {
|
||||
OWSFail(@"%@ Could not write data from path: %@, to path: %@", self.tag, self.filePath, dstFilePath);
|
||||
OWSFail(@"%@ Could not write data from path: %@, to path: %@, %@", self.tag, self.filePath, dstFilePath, error);
|
||||
return NO;
|
||||
} else {
|
||||
return YES;
|
||||
|
||||
@ -24,8 +24,8 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) {
|
||||
OWSErrorCodeMessageSendDisabledDueToPreKeyUpdateFailures = 777405,
|
||||
OWSErrorCodeMessageSendFailedToBlockList = 777406,
|
||||
OWSErrorCodeMessageSendNoValidRecipients = 777407,
|
||||
OWSErrorCodeContactsUpdaterRateLimit = 777407,
|
||||
OWSErrorCodeCouldNotWriteAttachmentData = 777408,
|
||||
OWSErrorCodeContactsUpdaterRateLimit = 777408,
|
||||
OWSErrorCodeCouldNotWriteAttachmentData = 777409,
|
||||
};
|
||||
|
||||
extern NSError *OWSErrorWithCodeDescription(OWSErrorCode code, NSString *description);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user