Render single media as albums.

This commit is contained in:
Matthew Chen 2018-11-08 13:20:14 -05:00
parent 1b49fa294f
commit cd224a1590
5 changed files with 135 additions and 217 deletions

View File

@ -433,6 +433,11 @@ private class MockConversationViewItem: NSObject, ConversationViewItem {
owsFailDebug("unexpected invocation")
return nil
}
func mediaAlbumHasFailedAttachment() -> Bool {
owsFailDebug("unexpected invocation")
return false
}
}
private class MockIncomingMessage: TSIncomingMessage {

View File

@ -187,14 +187,6 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
return (TSMessage *)self.viewItem.interaction;
}
- (CGSize)mediaSize
{
// This should always be valid for the appropriate cell types.
OWSAssertDebug(self.viewItem.mediaSize.width > 0 && self.viewItem.mediaSize.height > 0);
return self.viewItem.mediaSize;
}
- (BOOL)isQuotedReply
{
// This should always be valid for the appropriate cell types.
@ -232,10 +224,7 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
return YES;
case OWSMessageCellType_GenericAttachment:
case OWSMessageCellType_DownloadingAttachment:
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio:
case OWSMessageCellType_Video:
// Is there a caption?
return self.hasBodyText;
case OWSMessageCellType_ContactShare:
@ -305,12 +294,6 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
break;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Video:
OWSAssertDebug(self.viewItem.attachmentStream);
bodyMediaView = [self loadViewForMedia];
break;
case OWSMessageCellType_Audio:
OWSAssertDebug(self.viewItem.attachmentStream);
bodyMediaView = [self loadViewForAudio];
@ -595,10 +578,6 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
return NO;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Video:
return YES;
case OWSMessageCellType_Audio:
case OWSMessageCellType_GenericAttachment:
case OWSMessageCellType_DownloadingAttachment:
@ -796,38 +775,21 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
[albumView unloadMedia];
};
// Only apply "inner shadow" for single media, not albums.
if (albumView.itemViews.count == 1) {
UIView *itemView = albumView.itemViews.firstObject;
OWSBubbleShapeView *innerShadowView = [[OWSBubbleShapeView alloc]
initInnerShadowWithColor:(Theme.isDarkThemeEnabled ? UIColor.ows_whiteColor : UIColor.ows_blackColor)
radius:0.5f
opacity:0.15f];
[itemView addSubview:innerShadowView];
[self.bubbleView addPartnerView:innerShadowView];
[self.viewConstraints addObjectsFromArray:[innerShadowView ows_autoPinToSuperviewEdges]];
}
return albumView;
}
- (UIView *)loadViewForMedia
{
OWSAssertDebug(self.attachmentStream);
OWSAssertDebug([self.attachmentStream isVisualMedia]);
ConversationMediaView *mediaView =
[[ConversationMediaView alloc] initWithMediaCache:self.cellMediaCache
attachment:self.attachmentStream
isOutgoing:self.isOutgoing
maxMessageWidth:self.conversationStyle.maxMessageWidth];
self.loadCellContentBlock = ^{
[mediaView loadMedia];
};
self.unloadCellContentBlock = ^{
[mediaView unloadMedia];
};
[self addAttachmentUploadViewIfNecessary];
OWSBubbleShapeView *innerShadowView = [[OWSBubbleShapeView alloc]
initInnerShadowWithColor:(Theme.isDarkThemeEnabled ? UIColor.ows_whiteColor : UIColor.ows_blackColor)
radius:0.5f
opacity:0.15f];
[mediaView addSubview:innerShadowView];
[self.bubbleView addPartnerView:innerShadowView];
[self.viewConstraints addObjectsFromArray:[innerShadowView ows_autoPinToSuperviewEdges]];
return mediaView;
}
- (UIView *)loadViewForAudio
{
OWSAssertDebug(self.attachmentStream);
@ -990,43 +952,6 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
case OWSMessageCellType_OversizeTextMessage: {
return nil;
}
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Video: {
OWSAssertDebug(self.mediaSize.width > 0);
OWSAssertDebug(self.mediaSize.height > 0);
// TODO: Adjust this behavior.
CGFloat contentAspectRatio = self.mediaSize.width / self.mediaSize.height;
// Clamp the aspect ratio so that very thin/wide content is presented
// in a reasonable way.
const CGFloat minAspectRatio = 0.35f;
const CGFloat maxAspectRatio = 1 / minAspectRatio;
contentAspectRatio = MAX(minAspectRatio, MIN(maxAspectRatio, contentAspectRatio));
const CGFloat maxMediaWidth = maxMessageWidth;
const CGFloat maxMediaHeight = maxMessageWidth;
CGFloat mediaWidth = maxMediaHeight * contentAspectRatio;
CGFloat mediaHeight = maxMediaHeight;
if (mediaWidth > maxMediaWidth) {
mediaWidth = maxMediaWidth;
mediaHeight = maxMediaWidth / contentAspectRatio;
}
// We don't want to blow up small images unnecessarily.
const CGFloat kMinimumSize = 150.f;
CGFloat shortSrcDimension = MIN(self.mediaSize.width, self.mediaSize.height);
CGFloat shortDstDimension = MIN(mediaWidth, mediaHeight);
if (shortDstDimension > kMinimumSize && shortDstDimension > shortSrcDimension) {
CGFloat factor = kMinimumSize / shortDstDimension;
mediaWidth *= factor;
mediaHeight *= factor;
}
result = CGSizeRound(CGSizeMake(mediaWidth, mediaHeight));
break;
}
case OWSMessageCellType_Audio:
result = CGSizeMake(maxMessageWidth, OWSAudioMessageView.bubbleHeight);
break;
@ -1049,6 +974,42 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
case OWSMessageCellType_MediaAlbum:
result = [OWSMediaAlbumCellView layoutSizeForMaxMessageWidth:maxMessageWidth
items:self.viewItem.mediaAlbumItems];
if (self.viewItem.mediaAlbumItems.count == 1) {
// Honor the content aspect ratio for single media.
ConversationMediaAlbumItem *mediaAlbumItem = self.viewItem.mediaAlbumItems.firstObject;
if (mediaAlbumItem.attachmentStream && mediaAlbumItem.mediaSize.width > 0
&& mediaAlbumItem.mediaSize.height > 0) {
CGSize mediaSize = mediaAlbumItem.mediaSize;
CGFloat contentAspectRatio = mediaSize.width / mediaSize.height;
// Clamp the aspect ratio so that very thin/wide content is presented
// in a reasonable way.
const CGFloat minAspectRatio = 0.35f;
const CGFloat maxAspectRatio = 1 / minAspectRatio;
contentAspectRatio = MAX(minAspectRatio, MIN(maxAspectRatio, contentAspectRatio));
const CGFloat maxMediaWidth = maxMessageWidth;
const CGFloat maxMediaHeight = maxMessageWidth;
CGFloat mediaWidth = maxMediaHeight * contentAspectRatio;
CGFloat mediaHeight = maxMediaHeight;
if (mediaWidth > maxMediaWidth) {
mediaWidth = maxMediaWidth;
mediaHeight = maxMediaWidth / contentAspectRatio;
}
// We don't want to blow up small images unnecessarily.
const CGFloat kMinimumSize = 150.f;
CGFloat shortSrcDimension = MIN(mediaSize.width, mediaSize.height);
CGFloat shortDstDimension = MIN(mediaWidth, mediaHeight);
if (shortDstDimension > kMinimumSize && shortDstDimension > shortSrcDimension) {
CGFloat factor = kMinimumSize / shortDstDimension;
mediaWidth *= factor;
mediaHeight *= factor;
}
result = CGSizeRound(CGSizeMake(mediaWidth, mediaHeight));
}
}
break;
}
@ -1367,35 +1328,11 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
break;
case OWSMessageCellType_StillImage:
OWSAssertDebug(self.bodyMediaView);
OWSAssertDebug(self.viewItem.attachmentStream);
[self.delegate didTapImageViewItem:self.viewItem
attachmentStream:self.viewItem.attachmentStream
imageView:self.bodyMediaView];
break;
case OWSMessageCellType_AnimatedImage:
OWSAssertDebug(self.bodyMediaView);
OWSAssertDebug(self.viewItem.attachmentStream);
[self.delegate didTapImageViewItem:self.viewItem
attachmentStream:self.viewItem.attachmentStream
imageView:self.bodyMediaView];
break;
case OWSMessageCellType_Audio:
OWSAssertDebug(self.viewItem.attachmentStream);
[self.delegate didTapAudioViewItem:self.viewItem attachmentStream:self.viewItem.attachmentStream];
return;
case OWSMessageCellType_Video:
OWSAssertDebug(self.bodyMediaView);
OWSAssertDebug(self.viewItem.attachmentStream);
[self.delegate didTapVideoViewItem:self.viewItem
attachmentStream:self.viewItem.attachmentStream
imageView:self.bodyMediaView];
return;
case OWSMessageCellType_GenericAttachment:
OWSAssertDebug(self.viewItem.attachmentStream);
@ -1413,10 +1350,33 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
case OWSMessageCellType_ContactShare:
[self.delegate didTapContactShareViewItem:self.viewItem];
break;
case OWSMessageCellType_MediaAlbum:
case OWSMessageCellType_MediaAlbum: {
OWSAssertDebug(self.bodyMediaView);
OWSAssertDebug(self.viewItem.mediaAlbumItems.count > 0);
if (self.viewItem.mediaAlbumHasFailedAttachment) {
[self.delegate didTapFailedIncomingAttachment:self.viewItem];
return;
}
// TODO: We might be able to get rid of this.
if (self.viewItem.mediaAlbumItems.count == 1) {
ConversationMediaAlbumItem *mediaAlbumItem = self.viewItem.mediaAlbumItems.firstObject;
if (!mediaAlbumItem.attachmentStream.isValidVisualMedia) {
// Do nothing.
} else if (mediaAlbumItem.attachmentStream.isAnimated || mediaAlbumItem.attachmentStream.isImage) {
[self.delegate didTapImageViewItem:self.viewItem
attachmentStream:mediaAlbumItem.attachmentStream
imageView:self.bodyMediaView];
return;
} else if (mediaAlbumItem.attachmentStream.isVideo) {
[self.delegate didTapVideoViewItem:self.viewItem
attachmentStream:mediaAlbumItem.attachmentStream
imageView:self.bodyMediaView];
return;
}
}
// For now, use first valid attachment.
TSAttachmentStream *_Nullable attachmentStream = self.viewItem.firstValidAlbumAttachment;
if (!attachmentStream) {
@ -1428,6 +1388,7 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
attachmentStream:attachmentStream
imageView:self.bodyMediaView];
break;
}
}
}

View File

@ -11,10 +11,7 @@ typedef NS_ENUM(NSInteger, OWSMessageCellType) {
OWSMessageCellType_Unknown,
OWSMessageCellType_TextMessage,
OWSMessageCellType_OversizeTextMessage,
OWSMessageCellType_StillImage,
OWSMessageCellType_AnimatedImage,
OWSMessageCellType_Audio,
OWSMessageCellType_Video,
OWSMessageCellType_GenericAttachment,
OWSMessageCellType_DownloadingAttachment,
OWSMessageCellType_ContactShare,
@ -108,7 +105,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
@property (nonatomic, readonly, nullable) DisplayableText *displayableBodyText;
@property (nonatomic, readonly, nullable) TSAttachmentStream *attachmentStream;
@property (nonatomic, readonly, nullable) TSAttachmentPointer *attachmentPointer;
@property (nonatomic, readonly) CGSize mediaSize;
@property (nonatomic, readonly, nullable) NSArray<ConversationMediaAlbumItem *> *mediaAlbumItems;
@property (nonatomic, readonly, nullable) DisplayableText *displayableQuotedText;
@ -146,6 +142,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
- (nullable TSAttachmentStream *)firstValidAlbumAttachment;
- (BOOL)mediaAlbumHasFailedAttachment;
@end
#pragma mark -

View File

@ -25,14 +25,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
return @"OWSMessageCellType_TextMessage";
case OWSMessageCellType_OversizeTextMessage:
return @"OWSMessageCellType_OversizeTextMessage";
case OWSMessageCellType_StillImage:
return @"OWSMessageCellType_StillImage";
case OWSMessageCellType_AnimatedImage:
return @"OWSMessageCellType_AnimatedImage";
case OWSMessageCellType_Audio:
return @"OWSMessageCellType_Audio";
case OWSMessageCellType_Video:
return @"OWSMessageCellType_Video";
case OWSMessageCellType_GenericAttachment:
return @"OWSMessageCellType_GenericAttachment";
case OWSMessageCellType_DownloadingAttachment:
@ -94,7 +88,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
@property (nonatomic, nullable) TSAttachmentStream *attachmentStream;
@property (nonatomic, nullable) TSAttachmentPointer *attachmentPointer;
@property (nonatomic, nullable) ContactShareViewModel *contactShare;
@property (nonatomic) CGSize mediaSize;
@property (nonatomic, nullable) NSArray<ConversationMediaAlbumItem *> *mediaAlbumItems;
@property (nonatomic, nullable) NSString *systemMessageText;
@property (nonatomic, nullable) TSThread *incomingMessageAuthorThread;
@ -156,7 +149,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
self.displayableBodyText = nil;
self.attachmentStream = nil;
self.attachmentPointer = nil;
self.mediaSize = CGSizeZero;
self.displayableQuotedText = nil;
self.quotedReply = nil;
self.systemMessageText = nil;
@ -573,9 +565,24 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
if ([message isMediaAlbumWithTransaction:transaction]) {
OWSAssertDebug(attachments.count > 0);
NSArray<ConversationMediaAlbumItem *> *mediaAlbumItems = [self mediaAlbumItemsForAttachments:attachments];
if (mediaAlbumItems.count == 1) {
ConversationMediaAlbumItem *mediaAlbumItem = mediaAlbumItems.firstObject;
if (mediaAlbumItem.attachmentStream && !mediaAlbumItem.attachmentStream.isValidVisualMedia) {
OWSLogWarn(@"Treating invalid media as generic attachment.");
self.messageCellType = OWSMessageCellType_GenericAttachment;
return;
}
}
self.mediaAlbumItems = mediaAlbumItems;
self.messageCellType = OWSMessageCellType_MediaAlbum;
NSString *_Nullable albumTitle = [message bodyTextWithTransaction:transaction];
if (!albumTitle && mediaAlbumItems.count == 1) {
// If the album contains only one option, use its caption as the
// the album title.
albumTitle = mediaAlbumItems.firstObject.caption;
}
if (albumTitle) {
self.displayableBodyText = [self displayableBodyTextForText:albumTitle interactionId:message.uniqueId];
}
@ -593,41 +600,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
self.messageCellType = OWSMessageCellType_OversizeTextMessage;
self.displayableBodyText = [self displayableBodyTextForOversizeTextAttachment:self.attachmentStream
interactionId:message.uniqueId];
} else if ([self.attachmentStream isAnimated] || [self.attachmentStream isImage] ||
[self.attachmentStream isVideo]) {
if ([self.attachmentStream isAnimated]) {
if (![self.attachmentStream isValidImage]) {
OWSLogWarn(@"Treating invalid image as generic attachment.");
self.messageCellType = OWSMessageCellType_GenericAttachment;
return;
}
self.messageCellType = OWSMessageCellType_AnimatedImage;
} else if ([self.attachmentStream isImage]) {
if (![self.attachmentStream isValidImage]) {
OWSLogWarn(@"Treating invalid image as generic attachment.");
self.messageCellType = OWSMessageCellType_GenericAttachment;
return;
}
self.messageCellType = OWSMessageCellType_StillImage;
} else if ([self.attachmentStream isVideo]) {
if (![self.attachmentStream isValidVideo]) {
OWSLogWarn(@"Treating invalid video as generic attachment.");
self.messageCellType = OWSMessageCellType_GenericAttachment;
return;
}
self.messageCellType = OWSMessageCellType_Video;
} else {
OWSFailDebug(@"unexpected attachment type.");
self.messageCellType = OWSMessageCellType_GenericAttachment;
return;
}
self.mediaSize = [self.attachmentStream imageSize];
if (self.mediaSize.width <= 0 || self.mediaSize.height <= 0) {
self.messageCellType = OWSMessageCellType_GenericAttachment;
}
} else if ([self.attachmentStream isAudio]) {
CGFloat audioDurationSeconds = [self.attachmentStream audioDurationSeconds];
if (audioDurationSeconds > 0) {
@ -825,14 +797,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
return _attachmentPointer;
}
- (CGSize)mediaSize
{
OWSAssertIsOnMainThread();
OWSAssertDebug(self.hasViewState);
return _mediaSize;
}
- (nullable DisplayableText *)displayableQuotedText
{
OWSAssertIsOnMainThread();
@ -850,10 +814,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
switch (self.messageCellType) {
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio:
case OWSMessageCellType_Video:
case OWSMessageCellType_MediaAlbum:
case OWSMessageCellType_GenericAttachment: {
OWSAssertDebug(self.displayableBodyText);
@ -886,10 +847,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
OWSFailDebug(@"No media to copy");
break;
}
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio:
case OWSMessageCellType_Video:
case OWSMessageCellType_GenericAttachment: {
[self copyAttachmentToPasteboard:self.attachmentStream];
break;
@ -899,6 +857,14 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
break;
}
case OWSMessageCellType_MediaAlbum: {
if (self.mediaAlbumItems.count == 1) {
ConversationMediaAlbumItem *mediaAlbumItem = self.mediaAlbumItems.firstObject;
if (mediaAlbumItem.attachmentStream && mediaAlbumItem.attachmentStream.isValidVisualMedia) {
[self copyAttachmentToPasteboard:mediaAlbumItem.attachmentStream];
return;
}
}
OWSFailDebug(@"Can't copy media album");
break;
}
@ -931,10 +897,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
case OWSMessageCellType_ContactShare:
OWSFailDebug(@"No media to share.");
break;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio:
case OWSMessageCellType_Video:
case OWSMessageCellType_GenericAttachment:
[AttachmentSharing showShareUIForAttachment:self.attachmentStream];
break;
@ -947,7 +910,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
OWSAssertDebug(self.mediaAlbumItems);
NSMutableArray<TSAttachmentStream *> *attachmentStreams = [NSMutableArray new];
for (ConversationMediaAlbumItem *mediaAlbumItem in self.mediaAlbumItems) {
if (mediaAlbumItem.attachmentStream) {
if (mediaAlbumItem.attachmentStream && mediaAlbumItem.attachmentStream.isValidVisualMedia) {
[attachmentStreams addObject:mediaAlbumItem.attachmentStream];
}
}
@ -969,17 +932,19 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_ContactShare:
return NO;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
return YES;
case OWSMessageCellType_Audio:
return NO;
case OWSMessageCellType_Video:
return UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(self.attachmentStream.originalFilePath);
case OWSMessageCellType_GenericAttachment:
case OWSMessageCellType_DownloadingAttachment:
case OWSMessageCellType_MediaAlbum:
case OWSMessageCellType_MediaAlbum: {
if (self.mediaAlbumItems.count == 1) {
ConversationMediaAlbumItem *mediaAlbumItem = self.mediaAlbumItems.firstObject;
if (mediaAlbumItem.attachmentStream && mediaAlbumItem.attachmentStream.isValidVisualMedia) {
return YES;
}
}
return NO;
}
}
}
@ -991,13 +956,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_ContactShare:
return NO;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
return YES;
case OWSMessageCellType_Audio:
return NO;
case OWSMessageCellType_Video:
return UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(self.attachmentStream.originalFilePath);
case OWSMessageCellType_GenericAttachment:
case OWSMessageCellType_DownloadingAttachment:
return NO;
@ -1006,6 +966,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
if (!mediaAlbumItem.attachmentStream) {
continue;
}
if (!mediaAlbumItem.attachmentStream.isValidVisualMedia) {
continue;
}
if (mediaAlbumItem.attachmentStream.isImage || mediaAlbumItem.attachmentStream.isAnimated) {
return YES;
}
@ -1030,33 +993,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
case OWSMessageCellType_ContactShare:
OWSFailDebug(@"Cannot save text data.");
break;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage: {
NSData *data = [NSData dataWithContentsOfURL:[self.attachmentStream originalMediaURL]];
if (!data) {
OWSFailDebug(@"Could not load image data");
return;
}
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeImageDataToSavedPhotosAlbum:data
metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
OWSLogWarn(@"Error Saving image to photo album: %@", error);
}
}];
break;
}
case OWSMessageCellType_Audio:
OWSFailDebug(@"Cannot save media data.");
break;
case OWSMessageCellType_Video:
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(self.attachmentStream.originalFilePath)) {
UISaveVideoAtPathToSavedPhotosAlbum(self.attachmentStream.originalFilePath, self, nil, nil);
} else {
OWSFailDebug(@"Could not save incompatible video data.");
}
break;
case OWSMessageCellType_GenericAttachment:
OWSFailDebug(@"Cannot save media data.");
break;
@ -1071,6 +1010,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
if (!mediaAlbumItem.attachmentStream) {
continue;
}
if (!mediaAlbumItem.attachmentStream.isValidVisualMedia) {
continue;
}
if (mediaAlbumItem.attachmentStream.isImage || mediaAlbumItem.attachmentStream.isAnimated) {
NSData *data = [NSData dataWithContentsOfURL:[mediaAlbumItem.attachmentStream originalMediaURL]];
if (!data) {
@ -1115,21 +1057,33 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_ContactShare:
return NO;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio:
case OWSMessageCellType_Video:
case OWSMessageCellType_GenericAttachment:
return self.attachmentStream != nil;
case OWSMessageCellType_DownloadingAttachment: {
return NO;
}
case OWSMessageCellType_MediaAlbum:
// TODO: I suspect we need separate "can save media", "can share media", etc. methods.
return self.firstValidAlbumAttachment != nil;
}
}
- (BOOL)mediaAlbumHasFailedAttachment
{
OWSAssertDebug(self.messageCellType == OWSMessageCellType_MediaAlbum);
OWSAssertDebug(self.mediaAlbumItems.count > 0);
for (ConversationMediaAlbumItem *mediaAlbumItem in self.mediaAlbumItems) {
if ([mediaAlbumItem.attachment isKindOfClass:[TSAttachmentPointer class]]) {
TSAttachmentPointer *attachmentPointer = (TSAttachmentPointer *)mediaAlbumItem.attachment;
if (attachmentPointer.state == TSAttachmentPointerStateFailed) {
return YES;
}
}
}
return NO;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -225,7 +225,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
- (BOOL)isMediaAlbumWithTransaction:(YapDatabaseReadTransaction *)transaction
{
NSArray<TSAttachment *> *attachments = [self attachmentsWithTransaction:transaction];
if (attachments.count < 2) {
if (attachments.count < 1) {
return NO;
}
for (TSAttachment *attachment in attachments) {