From 1a5c47df2fd5d65e8c87193af0bcde17c801d46d Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 29 Nov 2018 15:08:12 -0700 Subject: [PATCH] Fix SAE, limit max attachments --- .../ConversationViewController.m | 34 +++++++------- .../SharingThreadPickerViewController.m | 45 ++++++++++--------- .../attachments/SignalAttachment.swift | 10 +++++ SignalMessaging/utils/ThreadUtil.h | 1 + SignalMessaging/utils/ThreadUtil.m | 2 +- .../ShareViewController.swift | 19 ++++---- 6 files changed, 63 insertions(+), 48 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 7e6aefde9..e537d2afb 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -90,8 +90,6 @@ @import Photos; -#define FEATURE_FLAG_ALBUM_SEND_ENABLED - NS_ASSUME_NONNULL_BEGIN static const CGFloat kLoadMoreHeaderHeight = 60.f; @@ -2640,17 +2638,20 @@ typedef enum : NSUInteger { return; } -#ifdef FEATURE_FLAG_ALBUM_SEND_ENABLED - OWSImagePickerGridController *picker = [OWSImagePickerGridController new]; - picker.delegate = self; + UIViewController *pickerModal; + if (SignalAttachment.isMultiSendEnabled) { + OWSImagePickerGridController *picker = [OWSImagePickerGridController new]; + picker.delegate = self; - OWSNavigationController *pickerModal = [[OWSNavigationController alloc] initWithRootViewController:picker]; -#else - UIImagePickerController *pickerModal = [UIImagePickerController new]; - pickerModal.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; - pickerModal.delegate = self; - pickerModal.mediaTypes = @[ (__bridge NSString *)kUTTypeImage, (__bridge NSString *)kUTTypeMovie ]; -#endif + pickerModal = [[OWSNavigationController alloc] initWithRootViewController:picker]; + } else { + UIImagePickerController *picker = [UIImagePickerController new]; + picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; + picker.delegate = self; + picker.mediaTypes = @[ (__bridge NSString *)kUTTypeImage, (__bridge NSString *)kUTTypeMovie ]; + + pickerModal = picker; + } [self dismissKeyBoard]; [self presentViewController:pickerModal animated:YES completion:nil]; @@ -2762,10 +2763,11 @@ typedef enum : NSUInteger { }]; } else { // Non-Video image picked from library -#ifdef FEATURE_FLAG_ALBUM_SEND_ENABLED - OWSFailDebug( - @"Only use UIImagePicker for camera/video capture. Picking media from UIImagePicker is not supported. "); -#endif + if (SignalAttachment.isMultiSendEnabled) { + OWSFailDebug(@"Only use UIImagePicker for camera/video capture. Picking media from UIImagePicker is not " + @"supported. "); + } + // To avoid re-encoding GIF and PNG's as JPEG we have to get the raw data of // the selected item vs. using the UIImagePickerControllerOriginalImage diff --git a/SignalMessaging/ViewControllers/SharingThreadPickerViewController.m b/SignalMessaging/ViewControllers/SharingThreadPickerViewController.m index 5fe6e46af..38deaced6 100644 --- a/SignalMessaging/ViewControllers/SharingThreadPickerViewController.m +++ b/SignalMessaging/ViewControllers/SharingThreadPickerViewController.m @@ -260,30 +260,33 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); #pragma mark - AttachmentApprovalViewControllerDelegate -- (void)attachmentApproval:(AttachmentApprovalViewController *)approvalViewController - didApproveAttachments:(NSArray *)attachments +- (void)attachmentApproval:(AttachmentApprovalViewController *_Nonnull)attachmentApproval + didApproveAttachments:(NSArray *_Nonnull)attachments + messageText:(NSString *_Nullable)messageText { [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread]; - [self tryToSendMessageWithBlock:^(SendCompletionBlock sendCompletion) { - OWSAssertIsOnMainThread(); - - __block TSOutgoingMessage *outgoingMessage = nil; - // DURABLE CLEANUP - SAE uses non-durable sending to make sure the app is running long enough to complete - // the sending operation. Alternatively, we could use a durable send, but do more to make sure the - // SAE runs as long as it needs. - // TODO ALBUMS - send album via SAE - outgoingMessage = [ThreadUtil sendMessageNonDurablyWithAttachments:attachments - inThread:self.thread - quotedReplyModel:nil - messageSender:self.messageSender - completion:^(NSError *_Nullable error) { - sendCompletion(error, outgoingMessage); - }]; + [self + tryToSendMessageWithBlock:^(SendCompletionBlock sendCompletion) { + OWSAssertIsOnMainThread(); + + __block TSOutgoingMessage *outgoingMessage = nil; + // DURABLE CLEANUP - SAE uses non-durable sending to make sure the app is running long enough to complete + // the sending operation. Alternatively, we could use a durable send, but do more to make sure the + // SAE runs as long as it needs. + // TODO ALBUMS - send album via SAE + outgoingMessage = [ThreadUtil sendMessageNonDurablyWithAttachments:attachments + inThread:self.thread + messageBody:messageText + quotedReplyModel:nil + messageSender:self.messageSender + completion:^(NSError *_Nullable error) { + sendCompletion(error, outgoingMessage); + }]; - // This is necessary to show progress. - self.outgoingMessage = outgoingMessage; - } - fromViewController:approvalViewController]; + // This is necessary to show progress. + self.outgoingMessage = outgoingMessage; + } + fromViewController:attachmentApproval]; } - (void)attachmentApproval:(AttachmentApprovalViewController *)attachmentApproval diff --git a/SignalMessaging/attachments/SignalAttachment.swift b/SignalMessaging/attachments/SignalAttachment.swift index 8f5320244..f9d0de947 100644 --- a/SignalMessaging/attachments/SignalAttachment.swift +++ b/SignalMessaging/attachments/SignalAttachment.swift @@ -190,6 +190,16 @@ public class SignalAttachment: NSObject { static let kMaxFileSizeAudio = OWSMediaUtils.kMaxFileSizeAudio static let kMaxFileSizeGeneric = OWSMediaUtils.kMaxFileSizeGeneric + // MARK: + + @objc + public static let isMultiSendEnabled = true + + @objc + public static var maxAttachmentsAllowed: Int { + return isMultiSendEnabled ? 32 : 1 + } + // MARK: Constructor // This method should not be called directly; use the factory diff --git a/SignalMessaging/utils/ThreadUtil.h b/SignalMessaging/utils/ThreadUtil.h index 7973ae0ea..1c2cdbc1a 100644 --- a/SignalMessaging/utils/ThreadUtil.h +++ b/SignalMessaging/utils/ThreadUtil.h @@ -74,6 +74,7 @@ NS_ASSUME_NONNULL_BEGIN // Used by SAE, otherwise we should use the durable `enqueue` counterpart + (TSOutgoingMessage *)sendMessageNonDurablyWithAttachments:(NSArray *)attachments inThread:(TSThread *)thread + messageBody:(nullable NSString *)messageBody quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel messageSender:(OWSMessageSender *)messageSender completion:(void (^_Nullable)(NSError *_Nullable error))completion; diff --git a/SignalMessaging/utils/ThreadUtil.m b/SignalMessaging/utils/ThreadUtil.m index 2ac2cff92..b6d562279 100644 --- a/SignalMessaging/utils/ThreadUtil.m +++ b/SignalMessaging/utils/ThreadUtil.m @@ -215,6 +215,7 @@ NS_ASSUME_NONNULL_BEGIN + (TSOutgoingMessage *)sendMessageNonDurablyWithAttachments:(NSArray *)attachments inThread:(TSThread *)thread + messageBody:(nullable NSString *)messageBody quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel messageSender:(OWSMessageSender *)messageSender completion:(void (^_Nullable)(NSError *_Nullable error))completion @@ -229,7 +230,6 @@ NS_ASSUME_NONNULL_BEGIN uint32_t expiresInSeconds = (configuration.isEnabled ? configuration.durationSeconds : 0); BOOL isVoiceMessage = (attachments.count == 1 && attachments.firstObject.isVoiceMessage); - NSString *_Nullable messageBody = (attachments.count == 1 ? attachments.firstObject.captionText : nil); TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread diff --git a/SignalShareExtension/ShareViewController.swift b/SignalShareExtension/ShareViewController.swift index db8035f63..1514423ed 100644 --- a/SignalShareExtension/ShareViewController.swift +++ b/SignalShareExtension/ShareViewController.swift @@ -966,14 +966,15 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed } private func buildAttachments() -> Promise<[SignalAttachment]> { - let promise = selectItemProviders().then { [weak self] (itemProviders) -> Promise<[SignalAttachment]> in + return selectItemProviders().then { [weak self] (itemProviders) -> Promise<[SignalAttachment]> in guard let strongSelf = self else { let error = ShareViewControllerError.assertionError(description: "expired") return Promise(error: error) } var loadPromises = [Promise]() - for itemProvider in itemProviders { + + for itemProvider in itemProviders.prefix(SignalAttachment.maxAttachmentsAllowed) { let loadPromise = strongSelf.loadItemProvider(itemProvider: itemProvider) .then({ (loadedItem) -> Promise in return strongSelf.buildAttachment(forLoadedItem: loadedItem) @@ -982,15 +983,13 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed loadPromises.append(loadPromise) } return when(fulfilled: loadPromises) - }.map { (signalAttachments) -> [SignalAttachment] in - guard signalAttachments.count > 0 else { - let error = ShareViewControllerError.assertionError(description: "no valid attachments") - throw error - } - return signalAttachments + }.map { (signalAttachments) -> [SignalAttachment] in + guard signalAttachments.count > 0 else { + let error = ShareViewControllerError.assertionError(description: "no valid attachments") + throw error } - promise.retainUntilComplete() - return promise + return signalAttachments + } } // Some host apps (e.g. iOS Photos.app) sometimes auto-converts some video formats (e.g. com.apple.quicktime-movie)