|  |  |  | @ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN | 
		
	
		
			
				|  |  |  |  | @property (nonatomic, readonly) OWSMessageSender *messageSender; | 
		
	
		
			
				|  |  |  |  | @property (nonatomic) TSThread *thread; | 
		
	
		
			
				|  |  |  |  | @property (nonatomic, readonly, weak) id<ShareViewDelegate> shareViewDelegate; | 
		
	
		
			
				|  |  |  |  | @property (nonatomic, readonly) UIProgressView *progressView; | 
		
	
		
			
				|  |  |  |  | @property (nullable, atomic) TSOutgoingMessage *outgoingMessage; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | @end | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -50,9 +52,20 @@ NS_ASSUME_NONNULL_BEGIN | 
		
	
		
			
				|  |  |  |  |     _contactsManager = [Environment current].contactsManager; | 
		
	
		
			
				|  |  |  |  |     _messageSender = [Environment current].messageSender; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     _progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; | 
		
	
		
			
				|  |  |  |  |     self.title = NSLocalizedString(@"SEND_EXTERNAL_FILE_VIEW_TITLE", @"Title for the 'send external file' view."); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | - (void)viewDidLoad | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     [super viewDidLoad]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     [[NSNotificationCenter defaultCenter] addObserver:self | 
		
	
		
			
				|  |  |  |  |                                              selector:@selector(attachmentUploadProgress:) | 
		
	
		
			
				|  |  |  |  |                                                  name:kAttachmentUploadProgressNotification | 
		
	
		
			
				|  |  |  |  |                                                object:nil]; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | - (BOOL)canSelectBlockedContact | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return NO; | 
		
	
	
		
			
				
					|  |  |  | @ -150,22 +163,142 @@ NS_ASSUME_NONNULL_BEGIN | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #pragma mark - AttachmentApprovalViewControllerDelegate | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | - (void)didApproveAttachmentWithAttachment:(SignalAttachment *)attachment | 
		
	
		
			
				|  |  |  |  | - (void)attachmentApproval:(AttachmentApprovalViewController *)attachmentApproval | 
		
	
		
			
				|  |  |  |  |       didApproveAttachment:(SignalAttachment *)attachment | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread]; | 
		
	
		
			
				|  |  |  |  |     [ThreadUtil sendMessageWithAttachment:self.attachment inThread:self.thread messageSender:self.messageSender]; | 
		
	
		
			
				|  |  |  |  |     [self tryToSendAttachment:attachment fromViewController:attachmentApproval]; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | - (void)attachmentApproval:(AttachmentApprovalViewController *)attachmentApproval | 
		
	
		
			
				|  |  |  |  |        didCancelAttachment:(SignalAttachment *)attachment | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     [self cancelShareExperience]; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #pragma mark - Helpers | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     // This is just a temporary hack while testing to hopefully not dismiss too early. | 
		
	
		
			
				|  |  |  |  |     // FIXME Show progress dialog | 
		
	
		
			
				|  |  |  |  |     // FIXME don't dismiss until sending is complete | 
		
	
		
			
				|  |  |  |  |     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ | 
		
	
		
			
				|  |  |  |  | - (void)tryToSendAttachment:(SignalAttachment *)attachment fromViewController:(UIViewController *)fromViewController | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     // Reset progress in case we're retrying | 
		
	
		
			
				|  |  |  |  |     self.progressView.progress = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     self.attachment = attachment; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     NSString *progressTitle = NSLocalizedString(@"SHARE_EXTENSION_SENDING_IN_PROGRESS_TITLE", @"Alert title"); | 
		
	
		
			
				|  |  |  |  |     UIAlertController *progressAlert = [UIAlertController alertControllerWithTitle:progressTitle | 
		
	
		
			
				|  |  |  |  |                                                                            message:nil | 
		
	
		
			
				|  |  |  |  |                                                                     preferredStyle:UIAlertControllerStyleAlert]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     UIAlertAction *progressCancelAction = [UIAlertAction actionWithTitle:[CommonStrings cancelButton] | 
		
	
		
			
				|  |  |  |  |                                                                    style:UIAlertActionStyleCancel | 
		
	
		
			
				|  |  |  |  |                                                                  handler:^(UIAlertAction *_Nonnull action) { | 
		
	
		
			
				|  |  |  |  |                                                                      [self.shareViewDelegate shareViewWasCancelled]; | 
		
	
		
			
				|  |  |  |  |                                                                  }]; | 
		
	
		
			
				|  |  |  |  |     [progressAlert addAction:progressCancelAction]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     // Adding a subview to the alert controller like this is a total hack. | 
		
	
		
			
				|  |  |  |  |     // ...but it looks good, and given how short a progress view is and how | 
		
	
		
			
				|  |  |  |  |     // little the alert controller changes, I'm not super worried about it. | 
		
	
		
			
				|  |  |  |  | #ifdef DEBUG | 
		
	
		
			
				|  |  |  |  |     if (@available(iOS 12, *)) { | 
		
	
		
			
				|  |  |  |  |         // Congratulations! You survived to see another iOS release. | 
		
	
		
			
				|  |  |  |  |         OWSFail(@"Make sure progress view still looks good increment this version canary."); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |     [progressAlert.view addSubview:self.progressView]; | 
		
	
		
			
				|  |  |  |  |     [self.progressView autoPinWidthToSuperviewWithMargin:24]; | 
		
	
		
			
				|  |  |  |  |     [self.progressView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:progressAlert.view withOffset:4]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     void (^presentRetryDialog)(NSError *error) = ^(NSError *error) { | 
		
	
		
			
				|  |  |  |  |         [fromViewController | 
		
	
		
			
				|  |  |  |  |             dismissViewControllerAnimated:YES | 
		
	
		
			
				|  |  |  |  |                                completion:^(void) { | 
		
	
		
			
				|  |  |  |  |                                    AssertIsOnMainThread(); | 
		
	
		
			
				|  |  |  |  |                                    NSString *failureTitle | 
		
	
		
			
				|  |  |  |  |                                        = NSLocalizedString(@"SHARE_EXTENSION_SENDING_FAILURE_TITLE", @"Alert title"); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                    UIAlertController *failureAlert = | 
		
	
		
			
				|  |  |  |  |                                        [UIAlertController alertControllerWithTitle:failureTitle | 
		
	
		
			
				|  |  |  |  |                                                                            message:error.localizedDescription | 
		
	
		
			
				|  |  |  |  |                                                                     preferredStyle:UIAlertControllerStyleAlert]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                    UIAlertAction *failureCancelAction = | 
		
	
		
			
				|  |  |  |  |                                        [UIAlertAction actionWithTitle:[CommonStrings cancelButton] | 
		
	
		
			
				|  |  |  |  |                                                                 style:UIAlertActionStyleCancel | 
		
	
		
			
				|  |  |  |  |                                                               handler:^(UIAlertAction *_Nonnull action) { | 
		
	
		
			
				|  |  |  |  |                                                                   [self.shareViewDelegate shareViewWasCancelled]; | 
		
	
		
			
				|  |  |  |  |                                                               }]; | 
		
	
		
			
				|  |  |  |  |                                    [failureAlert addAction:failureCancelAction]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                    UIAlertAction *retryAction = | 
		
	
		
			
				|  |  |  |  |                                        [UIAlertAction actionWithTitle:[CommonStrings retryButton] | 
		
	
		
			
				|  |  |  |  |                                                                 style:UIAlertActionStyleDefault | 
		
	
		
			
				|  |  |  |  |                                                               handler:^(UIAlertAction *action) { | 
		
	
		
			
				|  |  |  |  |                                                                   [self tryToSendAttachment:attachment | 
		
	
		
			
				|  |  |  |  |                                                                          fromViewController:fromViewController]; | 
		
	
		
			
				|  |  |  |  |                                                               }]; | 
		
	
		
			
				|  |  |  |  |                                    [failureAlert addAction:retryAction]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                    [fromViewController presentViewController:failureAlert animated:YES completion:nil]; | 
		
	
		
			
				|  |  |  |  |                                }]; | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     void (^sendCompletion)(NSError *_Nullable) = ^(NSError *_Nullable error) { | 
		
	
		
			
				|  |  |  |  |         AssertIsOnMainThread(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if (error) { | 
		
	
		
			
				|  |  |  |  |             DDLogInfo(@"%@ Sending attachment failed with error: %@", self.logTag, error); | 
		
	
		
			
				|  |  |  |  |             presentRetryDialog(error); | 
		
	
		
			
				|  |  |  |  |             return; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         DDLogInfo(@"%@ Sending attachment succeeded.", self.logTag); | 
		
	
		
			
				|  |  |  |  |         [self.shareViewDelegate shareViewWasCompleted]; | 
		
	
		
			
				|  |  |  |  |     }); | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     [fromViewController presentViewController:progressAlert | 
		
	
		
			
				|  |  |  |  |                                      animated:YES | 
		
	
		
			
				|  |  |  |  |                                    completion:^(void) { | 
		
	
		
			
				|  |  |  |  |                                        TSOutgoingMessage *outgoingMessage = | 
		
	
		
			
				|  |  |  |  |                                            [ThreadUtil sendMessageWithAttachment:self.attachment | 
		
	
		
			
				|  |  |  |  |                                                                         inThread:self.thread | 
		
	
		
			
				|  |  |  |  |                                                                    messageSender:self.messageSender | 
		
	
		
			
				|  |  |  |  |                                                                       completion:sendCompletion]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                        self.outgoingMessage = outgoingMessage; | 
		
	
		
			
				|  |  |  |  |                                    }]; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | - (void)didCancelAttachmentWithAttachment:(SignalAttachment *)attachment | 
		
	
		
			
				|  |  |  |  | - (void)attachmentUploadProgress:(NSNotification *)notification | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     [self cancelShareExperience]; | 
		
	
		
			
				|  |  |  |  |     DDLogDebug(@"%@ upload progress.", self.logTag); | 
		
	
		
			
				|  |  |  |  |     AssertIsOnMainThread(); | 
		
	
		
			
				|  |  |  |  |     OWSAssert(self.progressView); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     if (!self.outgoingMessage) { | 
		
	
		
			
				|  |  |  |  |         DDLogDebug(@"%@ Ignoring upload progress until there is an outgoing message.", self.logTag); | 
		
	
		
			
				|  |  |  |  |         return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     NSString *attachmentRecordId = self.outgoingMessage.attachmentIds.firstObject; | 
		
	
		
			
				|  |  |  |  |     if (!attachmentRecordId) { | 
		
	
		
			
				|  |  |  |  |         DDLogDebug(@"%@ Ignoring upload progress until outgoing message has an attachment record id", self.logTag); | 
		
	
		
			
				|  |  |  |  |         return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     NSDictionary *userinfo = [notification userInfo]; | 
		
	
		
			
				|  |  |  |  |     float progress = [[userinfo objectForKey:kAttachmentUploadProgressKey] floatValue]; | 
		
	
		
			
				|  |  |  |  |     NSString *attachmentID = [userinfo objectForKey:kAttachmentUploadAttachmentIDKey]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     if ([attachmentRecordId isEqual:attachmentID]) { | 
		
	
		
			
				|  |  |  |  |         if (!isnan(progress)) { | 
		
	
		
			
				|  |  |  |  |             [self.progressView setProgress:progress animated:YES]; | 
		
	
		
			
				|  |  |  |  |         } else { | 
		
	
		
			
				|  |  |  |  |             OWSFail(@"%@ Invalid attachment progress.", self.logTag); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | @end | 
		
	
	
		
			
				
					|  |  |  | 
 |