// // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSUploadOperation.h" #import "MIMETypeUtil.h" #import "NSError+MessageSending.h" #import "NSNotificationCenter+OWS.h" #import "OWSDispatch.h" #import "OWSError.h" #import "OWSOperation.h" #import #import "SSKEnvironment.h" #import "TSAttachmentStream.h" #import #import #import NS_ASSUME_NONNULL_BEGIN NSString *const kAttachmentUploadProgressNotification = @"kAttachmentUploadProgressNotification"; NSString *const kAttachmentUploadProgressKey = @"kAttachmentUploadProgressKey"; NSString *const kAttachmentUploadAttachmentIDKey = @"kAttachmentUploadAttachmentIDKey"; // Use a slightly non-zero value to ensure that the progress // indicator shows up as quickly as possible. static const CGFloat kAttachmentUploadProgressTheta = 0.001f; @interface OWSUploadOperation () @property (readonly, nonatomic) NSString *attachmentId; @property (readonly, nonatomic) NSString *threadID; @property (readonly, nonatomic) YapDatabaseConnection *dbConnection; @end #pragma mark - @implementation OWSUploadOperation - (instancetype)initWithAttachmentId:(NSString *)attachmentId threadID:(NSString *)threadID dbConnection:(YapDatabaseConnection *)dbConnection { self = [super init]; if (!self) { return self; } self.remainingRetries = 4; _attachmentId = attachmentId; _threadID = threadID; _dbConnection = dbConnection; return self; } - (void)run { __block TSAttachmentStream *attachmentStream; [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { attachmentStream = [TSAttachmentStream fetchObjectWithUniqueID:self.attachmentId transaction:transaction]; }]; if (!attachmentStream) { NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError(); // Not finding a local attachment is a terminal failure error.isRetryable = NO; [self reportError:error]; return; } if (attachmentStream.isUploaded) { OWSLogDebug(@"Attachment previously uploaded."); [self reportSuccess]; return; } [self fireNotificationWithProgress:0]; SNOpenGroup *publicChat = [LKStorage.shared getOpenGroupForThreadID:self.threadID]; NSString *server = (publicChat != nil) ? publicChat.server : SNFileServerAPI.server; [[SNFileServerAPI uploadAttachment:attachmentStream withID:self.attachmentId toServer:server] .thenOn(dispatch_get_main_queue(), ^() { [self reportSuccess]; }) .catchOn(dispatch_get_main_queue(), ^(NSError *error) { [self reportError:error]; }) retainUntilComplete]; } - (void)fireNotificationWithProgress:(CGFloat)aProgress { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; CGFloat progress = MAX(kAttachmentUploadProgressTheta, aProgress); [notificationCenter postNotificationNameAsync:kAttachmentUploadProgressNotification object:nil userInfo:@{ kAttachmentUploadProgressKey : @(progress), kAttachmentUploadAttachmentIDKey : self.attachmentId }]; } @end NS_ASSUME_NONNULL_END