From 4fda1be3f551cb2346d54d5bf2839445febf790a Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 22 Jan 2019 15:01:16 -0500 Subject: [PATCH 1/3] Save and share all items in album --- .../ConversationView/ConversationViewItem.m | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m index 60b94a184..0251a9eb8 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m @@ -98,6 +98,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) @property (nonatomic, nullable) TSAttachmentStream *attachmentStream; @property (nonatomic, nullable) TSAttachmentPointer *attachmentPointer; @property (nonatomic, nullable) ContactShareViewModel *contactShare; +@property (nonatomic, nullable) NSArray *allMediaAlbumAttachments; @property (nonatomic, nullable) NSArray *mediaAlbumItems; @property (nonatomic, nullable) NSString *systemMessageText; @property (nonatomic, nullable) TSThread *incomingMessageAuthorThread; @@ -162,6 +163,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) self.displayableQuotedText = nil; self.quotedReply = nil; self.systemMessageText = nil; + self.allMediaAlbumAttachments = nil; self.mediaAlbumItems = nil; [self updateAuthorConversationColorNameWithTransaction:transaction]; @@ -601,6 +603,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) } } + self.allMediaAlbumAttachments = attachments; self.mediaAlbumItems = mediaAlbumItems; self.messageCellType = OWSMessageCellType_MediaAlbum; NSString *_Nullable albumTitle = [message bodyTextWithTransaction:transaction]; @@ -925,9 +928,13 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) // TODO: We need a "canShareMediaAction" method. OWSAssertDebug(self.mediaAlbumItems); NSMutableArray *attachmentStreams = [NSMutableArray new]; - for (ConversationMediaAlbumItem *mediaAlbumItem in self.mediaAlbumItems) { - if (mediaAlbumItem.attachmentStream && mediaAlbumItem.attachmentStream.isValidVisualMedia) { - [attachmentStreams addObject:mediaAlbumItem.attachmentStream]; + for (TSAttachment *attachment in self.allMediaAlbumAttachments) { + if (![attachment isKindOfClass:[TSAttachmentStream class]]) { + continue; + } + TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment; + if (attachmentStream.isValidVisualMedia) { + [attachmentStreams addObject:attachmentStream]; } } if (attachmentStreams.count < 1) { @@ -1022,15 +1029,16 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) case OWSMessageCellType_MediaAlbum: { // TODO: Use PHPhotoLibrary. ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; - for (ConversationMediaAlbumItem *mediaAlbumItem in self.mediaAlbumItems) { - if (!mediaAlbumItem.attachmentStream) { + for (TSAttachment *attachment in self.allMediaAlbumAttachments) { + if (![attachment isKindOfClass:[TSAttachmentStream class]]) { continue; } - if (!mediaAlbumItem.attachmentStream.isValidVisualMedia) { + TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment; + if (!attachmentStream.isValidVisualMedia) { continue; } - if (mediaAlbumItem.attachmentStream.isImage || mediaAlbumItem.attachmentStream.isAnimated) { - NSData *data = [NSData dataWithContentsOfURL:[mediaAlbumItem.attachmentStream originalMediaURL]]; + if (attachmentStream.isImage || attachmentStream.isAnimated) { + NSData *data = [NSData dataWithContentsOfURL:[attachmentStream originalMediaURL]]; if (!data) { OWSFailDebug(@"Could not load image data"); continue; @@ -1043,11 +1051,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) } }]; } - if (mediaAlbumItem.attachmentStream.isVideo) { - if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum( - mediaAlbumItem.attachmentStream.originalFilePath)) { - UISaveVideoAtPathToSavedPhotosAlbum( - mediaAlbumItem.attachmentStream.originalFilePath, self, nil, nil); + if (attachmentStream.isVideo) { + if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(attachmentStream.originalFilePath)) { + UISaveVideoAtPathToSavedPhotosAlbum(attachmentStream.originalFilePath, self, nil, nil); } } } From 8dc6ea0c084e507457a375e8d7fd4e64f9dd773b Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 22 Jan 2019 15:31:42 -0500 Subject: [PATCH 2/3] Revert "Save and share all items in album" This reverts commit 58ab3948e969fe09872e51061e2311535d9e0eb4. --- .../ConversationView/ConversationViewItem.m | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m index 0251a9eb8..60b94a184 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m @@ -98,7 +98,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) @property (nonatomic, nullable) TSAttachmentStream *attachmentStream; @property (nonatomic, nullable) TSAttachmentPointer *attachmentPointer; @property (nonatomic, nullable) ContactShareViewModel *contactShare; -@property (nonatomic, nullable) NSArray *allMediaAlbumAttachments; @property (nonatomic, nullable) NSArray *mediaAlbumItems; @property (nonatomic, nullable) NSString *systemMessageText; @property (nonatomic, nullable) TSThread *incomingMessageAuthorThread; @@ -163,7 +162,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) self.displayableQuotedText = nil; self.quotedReply = nil; self.systemMessageText = nil; - self.allMediaAlbumAttachments = nil; self.mediaAlbumItems = nil; [self updateAuthorConversationColorNameWithTransaction:transaction]; @@ -603,7 +601,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) } } - self.allMediaAlbumAttachments = attachments; self.mediaAlbumItems = mediaAlbumItems; self.messageCellType = OWSMessageCellType_MediaAlbum; NSString *_Nullable albumTitle = [message bodyTextWithTransaction:transaction]; @@ -928,13 +925,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) // TODO: We need a "canShareMediaAction" method. OWSAssertDebug(self.mediaAlbumItems); NSMutableArray *attachmentStreams = [NSMutableArray new]; - for (TSAttachment *attachment in self.allMediaAlbumAttachments) { - if (![attachment isKindOfClass:[TSAttachmentStream class]]) { - continue; - } - TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment; - if (attachmentStream.isValidVisualMedia) { - [attachmentStreams addObject:attachmentStream]; + for (ConversationMediaAlbumItem *mediaAlbumItem in self.mediaAlbumItems) { + if (mediaAlbumItem.attachmentStream && mediaAlbumItem.attachmentStream.isValidVisualMedia) { + [attachmentStreams addObject:mediaAlbumItem.attachmentStream]; } } if (attachmentStreams.count < 1) { @@ -1029,16 +1022,15 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) case OWSMessageCellType_MediaAlbum: { // TODO: Use PHPhotoLibrary. ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; - for (TSAttachment *attachment in self.allMediaAlbumAttachments) { - if (![attachment isKindOfClass:[TSAttachmentStream class]]) { + for (ConversationMediaAlbumItem *mediaAlbumItem in self.mediaAlbumItems) { + if (!mediaAlbumItem.attachmentStream) { continue; } - TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment; - if (!attachmentStream.isValidVisualMedia) { + if (!mediaAlbumItem.attachmentStream.isValidVisualMedia) { continue; } - if (attachmentStream.isImage || attachmentStream.isAnimated) { - NSData *data = [NSData dataWithContentsOfURL:[attachmentStream originalMediaURL]]; + if (mediaAlbumItem.attachmentStream.isImage || mediaAlbumItem.attachmentStream.isAnimated) { + NSData *data = [NSData dataWithContentsOfURL:[mediaAlbumItem.attachmentStream originalMediaURL]]; if (!data) { OWSFailDebug(@"Could not load image data"); continue; @@ -1051,9 +1043,11 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) } }]; } - if (attachmentStream.isVideo) { - if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(attachmentStream.originalFilePath)) { - UISaveVideoAtPathToSavedPhotosAlbum(attachmentStream.originalFilePath, self, nil, nil); + if (mediaAlbumItem.attachmentStream.isVideo) { + if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum( + mediaAlbumItem.attachmentStream.originalFilePath)) { + UISaveVideoAtPathToSavedPhotosAlbum( + mediaAlbumItem.attachmentStream.originalFilePath, self, nil, nil); } } } From 79000d5fbb790cf745656d8813041e8bd5b64515 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 22 Jan 2019 16:50:49 -0500 Subject: [PATCH 3/3] Save and share all items in album. --- .../ConversationView/ConversationViewItem.m | 79 +++++++++++-------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m index 60b94a184..92687819a 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m @@ -9,7 +9,6 @@ #import "OWSMessageHeaderView.h" #import "OWSSystemMessageCell.h" #import "Signal-Swift.h" -#import #import #import #import @@ -1020,39 +1019,57 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) break; } case OWSMessageCellType_MediaAlbum: { - // TODO: Use PHPhotoLibrary. - ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; - for (ConversationMediaAlbumItem *mediaAlbumItem in self.mediaAlbumItems) { - 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) { - OWSFailDebug(@"Could not load image data"); - continue; - } - [library writeImageDataToSavedPhotosAlbum:data - metadata:nil - completionBlock:^(NSURL *assetURL, NSError *error) { - if (error) { - OWSLogWarn(@"Error saving image to photo album: %@", error); - } - }]; - } - if (mediaAlbumItem.attachmentStream.isVideo) { - if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum( - mediaAlbumItem.attachmentStream.originalFilePath)) { - UISaveVideoAtPathToSavedPhotosAlbum( - mediaAlbumItem.attachmentStream.originalFilePath, self, nil, nil); - } + [self saveMediaAlbumItems]; + break; + } + } +} + +- (void)saveMediaAlbumItems +{ + // We need to do these writes serially to avoid "write busy" errors + // from too many concurrent asset saves. + [self saveMediaAlbumItems:[self.mediaAlbumItems mutableCopy]]; +} + +- (void)saveMediaAlbumItems:(NSMutableArray *)mediaAlbumItems +{ + if (mediaAlbumItems.count < 1) { + return; + } + ConversationMediaAlbumItem *mediaAlbumItem = mediaAlbumItems.firstObject; + [mediaAlbumItems removeObjectAtIndex:0]; + + if (!mediaAlbumItem.attachmentStream || !mediaAlbumItem.attachmentStream.isValidVisualMedia) { + // Skip this item. + } else if (mediaAlbumItem.attachmentStream.isImage || mediaAlbumItem.attachmentStream.isAnimated) { + [[PHPhotoLibrary sharedPhotoLibrary] + performChanges:^{ + [PHAssetChangeRequest + creationRequestForAssetFromImageAtFileURL:mediaAlbumItem.attachmentStream.originalMediaURL]; + } + completionHandler:^(BOOL success, NSError *error) { + if (error || !success) { + OWSFailDebug(@"Image save failed: %@", error); } + [self saveMediaAlbumItems:mediaAlbumItems]; + }]; + return; + } else if (mediaAlbumItem.attachmentStream.isVideo) { + [[PHPhotoLibrary sharedPhotoLibrary] + performChanges:^{ + [PHAssetChangeRequest + creationRequestForAssetFromVideoAtFileURL:mediaAlbumItem.attachmentStream.originalMediaURL]; } - } + completionHandler:^(BOOL success, NSError *error) { + if (error || !success) { + OWSFailDebug(@"Video save failed: %@", error); + } + [self saveMediaAlbumItems:mediaAlbumItems]; + }]; + return; } + return [self saveMediaAlbumItems:mediaAlbumItems]; } - (void)deleteAction