Merge branch 'mkirk/limit-attachments'

pull/1/head
Michael Kirk 7 years ago
commit eb613c87c3

@ -90,8 +90,6 @@
@import Photos; @import Photos;
#define FEATURE_FLAG_ALBUM_SEND_ENABLED
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
static const CGFloat kLoadMoreHeaderHeight = 60.f; static const CGFloat kLoadMoreHeaderHeight = 60.f;
@ -2640,17 +2638,20 @@ typedef enum : NSUInteger {
return; return;
} }
#ifdef FEATURE_FLAG_ALBUM_SEND_ENABLED UIViewController *pickerModal;
if (SignalAttachment.isMultiSendEnabled) {
OWSImagePickerGridController *picker = [OWSImagePickerGridController new]; OWSImagePickerGridController *picker = [OWSImagePickerGridController new];
picker.delegate = self; picker.delegate = self;
OWSNavigationController *pickerModal = [[OWSNavigationController alloc] initWithRootViewController:picker]; pickerModal = [[OWSNavigationController alloc] initWithRootViewController:picker];
#else } else {
UIImagePickerController *pickerModal = [UIImagePickerController new]; UIImagePickerController *picker = [UIImagePickerController new];
pickerModal.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
pickerModal.delegate = self; picker.delegate = self;
pickerModal.mediaTypes = @[ (__bridge NSString *)kUTTypeImage, (__bridge NSString *)kUTTypeMovie ]; picker.mediaTypes = @[ (__bridge NSString *)kUTTypeImage, (__bridge NSString *)kUTTypeMovie ];
#endif
pickerModal = picker;
}
[self dismissKeyBoard]; [self dismissKeyBoard];
[self presentViewController:pickerModal animated:YES completion:nil]; [self presentViewController:pickerModal animated:YES completion:nil];
@ -2762,10 +2763,11 @@ typedef enum : NSUInteger {
}]; }];
} else { } else {
// Non-Video image picked from library // Non-Video image picked from library
#ifdef FEATURE_FLAG_ALBUM_SEND_ENABLED if (SignalAttachment.isMultiSendEnabled) {
OWSFailDebug( OWSFailDebug(@"Only use UIImagePicker for camera/video capture. Picking media from UIImagePicker is not "
@"Only use UIImagePicker for camera/video capture. Picking media from UIImagePicker is not supported. "); @"supported. ");
#endif }
// To avoid re-encoding GIF and PNG's as JPEG we have to get the raw data of // 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 // the selected item vs. using the UIImagePickerControllerOriginalImage

@ -387,6 +387,14 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
// MARK: - UICollectionView // MARK: - UICollectionView
override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
guard let indexPathsForSelectedItems = collectionView.indexPathsForSelectedItems else {
return true
}
return indexPathsForSelectedItems.count < SignalAttachment.maxAttachmentsAllowed
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let asset = photoCollectionContents.asset(at: indexPath.item) let asset = photoCollectionContents.asset(at: indexPath.item)

@ -260,11 +260,13 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion);
#pragma mark - AttachmentApprovalViewControllerDelegate #pragma mark - AttachmentApprovalViewControllerDelegate
- (void)attachmentApproval:(AttachmentApprovalViewController *)approvalViewController - (void)attachmentApproval:(AttachmentApprovalViewController *_Nonnull)attachmentApproval
didApproveAttachments:(NSArray<SignalAttachment *> *)attachments didApproveAttachments:(NSArray<SignalAttachment *> *_Nonnull)attachments
messageText:(NSString *_Nullable)messageText
{ {
[ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread]; [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
[self tryToSendMessageWithBlock:^(SendCompletionBlock sendCompletion) { [self
tryToSendMessageWithBlock:^(SendCompletionBlock sendCompletion) {
OWSAssertIsOnMainThread(); OWSAssertIsOnMainThread();
__block TSOutgoingMessage *outgoingMessage = nil; __block TSOutgoingMessage *outgoingMessage = nil;
@ -274,6 +276,7 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion);
// TODO ALBUMS - send album via SAE // TODO ALBUMS - send album via SAE
outgoingMessage = [ThreadUtil sendMessageNonDurablyWithAttachments:attachments outgoingMessage = [ThreadUtil sendMessageNonDurablyWithAttachments:attachments
inThread:self.thread inThread:self.thread
messageBody:messageText
quotedReplyModel:nil quotedReplyModel:nil
messageSender:self.messageSender messageSender:self.messageSender
completion:^(NSError *_Nullable error) { completion:^(NSError *_Nullable error) {
@ -283,7 +286,7 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion);
// This is necessary to show progress. // This is necessary to show progress.
self.outgoingMessage = outgoingMessage; self.outgoingMessage = outgoingMessage;
} }
fromViewController:approvalViewController]; fromViewController:attachmentApproval];
} }
- (void)attachmentApproval:(AttachmentApprovalViewController *)attachmentApproval - (void)attachmentApproval:(AttachmentApprovalViewController *)attachmentApproval
@ -399,7 +402,7 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion);
[self.progressView autoPinWidthToSuperviewWithMargin:24]; [self.progressView autoPinWidthToSuperviewWithMargin:24];
[self.progressView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:progressAlert.view withOffset:4]; [self.progressView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:progressAlert.view withOffset:4];
#ifdef DEBUG #ifdef DEBUG
if (@available(iOS 12, *)) { if (@available(iOS 13, *)) {
// TODO: Congratulations! You survived to see another iOS release. // TODO: Congratulations! You survived to see another iOS release.
OWSFailDebug(@"Make sure the progress view still looks good, and increment the version canary."); OWSFailDebug(@"Make sure the progress view still looks good, and increment the version canary.");
} }

@ -190,6 +190,16 @@ public class SignalAttachment: NSObject {
static let kMaxFileSizeAudio = OWSMediaUtils.kMaxFileSizeAudio static let kMaxFileSizeAudio = OWSMediaUtils.kMaxFileSizeAudio
static let kMaxFileSizeGeneric = OWSMediaUtils.kMaxFileSizeGeneric static let kMaxFileSizeGeneric = OWSMediaUtils.kMaxFileSizeGeneric
// MARK:
@objc
public static let isMultiSendEnabled = true
@objc
public static var maxAttachmentsAllowed: Int {
return isMultiSendEnabled ? 32 : 1
}
// MARK: Constructor // MARK: Constructor
// This method should not be called directly; use the factory // This method should not be called directly; use the factory

@ -74,6 +74,7 @@ NS_ASSUME_NONNULL_BEGIN
// Used by SAE, otherwise we should use the durable `enqueue` counterpart // Used by SAE, otherwise we should use the durable `enqueue` counterpart
+ (TSOutgoingMessage *)sendMessageNonDurablyWithAttachments:(NSArray<SignalAttachment *> *)attachments + (TSOutgoingMessage *)sendMessageNonDurablyWithAttachments:(NSArray<SignalAttachment *> *)attachments
inThread:(TSThread *)thread inThread:(TSThread *)thread
messageBody:(nullable NSString *)messageBody
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel
messageSender:(OWSMessageSender *)messageSender messageSender:(OWSMessageSender *)messageSender
completion:(void (^_Nullable)(NSError *_Nullable error))completion; completion:(void (^_Nullable)(NSError *_Nullable error))completion;

@ -215,6 +215,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (TSOutgoingMessage *)sendMessageNonDurablyWithAttachments:(NSArray<SignalAttachment *> *)attachments + (TSOutgoingMessage *)sendMessageNonDurablyWithAttachments:(NSArray<SignalAttachment *> *)attachments
inThread:(TSThread *)thread inThread:(TSThread *)thread
messageBody:(nullable NSString *)messageBody
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel
messageSender:(OWSMessageSender *)messageSender messageSender:(OWSMessageSender *)messageSender
completion:(void (^_Nullable)(NSError *_Nullable error))completion completion:(void (^_Nullable)(NSError *_Nullable error))completion
@ -229,7 +230,6 @@ NS_ASSUME_NONNULL_BEGIN
uint32_t expiresInSeconds = (configuration.isEnabled ? configuration.durationSeconds : 0); uint32_t expiresInSeconds = (configuration.isEnabled ? configuration.durationSeconds : 0);
BOOL isVoiceMessage = (attachments.count == 1 && attachments.firstObject.isVoiceMessage); BOOL isVoiceMessage = (attachments.count == 1 && attachments.firstObject.isVoiceMessage);
NSString *_Nullable messageBody = (attachments.count == 1 ? attachments.firstObject.captionText : nil);
TSOutgoingMessage *message = TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp] [[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread inThread:thread

@ -966,14 +966,15 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
} }
private func buildAttachments() -> Promise<[SignalAttachment]> { 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 { guard let strongSelf = self else {
let error = ShareViewControllerError.assertionError(description: "expired") let error = ShareViewControllerError.assertionError(description: "expired")
return Promise(error: error) return Promise(error: error)
} }
var loadPromises = [Promise<SignalAttachment>]() var loadPromises = [Promise<SignalAttachment>]()
for itemProvider in itemProviders {
for itemProvider in itemProviders.prefix(SignalAttachment.maxAttachmentsAllowed) {
let loadPromise = strongSelf.loadItemProvider(itemProvider: itemProvider) let loadPromise = strongSelf.loadItemProvider(itemProvider: itemProvider)
.then({ (loadedItem) -> Promise<SignalAttachment> in .then({ (loadedItem) -> Promise<SignalAttachment> in
return strongSelf.buildAttachment(forLoadedItem: loadedItem) return strongSelf.buildAttachment(forLoadedItem: loadedItem)
@ -989,8 +990,6 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
} }
return signalAttachments return signalAttachments
} }
promise.retainUntilComplete()
return promise
} }
// Some host apps (e.g. iOS Photos.app) sometimes auto-converts some video formats (e.g. com.apple.quicktime-movie) // Some host apps (e.g. iOS Photos.app) sometimes auto-converts some video formats (e.g. com.apple.quicktime-movie)

Loading…
Cancel
Save