Rework quoted attachments.

pull/1/head
Matthew Chen 6 years ago
parent 56dfdaf6e7
commit b0704074b9

@ -1,5 +1,5 @@
// //
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// //
#import "TSAttachmentStream.h" #import "TSAttachmentStream.h"
@ -776,6 +776,10 @@ typedef void (^OWSLoadedThumbnailSuccess)(OWSLoadedThumbnail *loadedThumbnail);
- (nullable TSAttachmentStream *)cloneAsThumbnail - (nullable TSAttachmentStream *)cloneAsThumbnail
{ {
if (!self.isValidVisualMedia) {
return nil;
}
NSData *_Nullable thumbnailData = self.thumbnailDataSmallSync; NSData *_Nullable thumbnailData = self.thumbnailDataSmallSync;
// Only some media types have thumbnails // Only some media types have thumbnails
if (!thumbnailData) { if (!thumbnailData) {

@ -1,5 +1,5 @@
// //
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// //
#import "TSQuotedMessage.h" #import "TSQuotedMessage.h"
@ -136,14 +136,15 @@ NS_ASSUME_NONNULL_BEGIN
TSQuotedMessageContentSource bodySource = TSQuotedMessageContentSourceUnknown; TSQuotedMessageContentSource bodySource = TSQuotedMessageContentSourceUnknown;
// Prefer to generate the text snippet locally if available. // Prefer to generate the text snippet locally if available.
TSMessage *_Nullable localRecord = (TSMessage *)[ TSMessage *_Nullable quotedMessage = [self findQuotedMessageWithTimestamp:timestamp
[TSInteraction interactionsWithTimestamp:quoteProto.id ofClass:TSMessage.class withTransaction:transaction] threadId:thread.uniqueId
firstObject]; authorId:authorId
transaction:transaction];
if (localRecord) { if (quotedMessage) {
bodySource = TSQuotedMessageContentSourceLocal; bodySource = TSQuotedMessageContentSourceLocal;
NSString *localText = [localRecord bodyTextWithTransaction:transaction]; NSString *localText = [quotedMessage bodyTextWithTransaction:transaction];
if (localText.length > 0) { if (localText.length > 0) {
body = localText; body = localText;
} }
@ -166,21 +167,21 @@ NS_ASSUME_NONNULL_BEGIN
sourceFilename:quotedAttachment.fileName]; sourceFilename:quotedAttachment.fileName];
// We prefer deriving any thumbnail locally rather than fetching one from the network. // We prefer deriving any thumbnail locally rather than fetching one from the network.
TSAttachmentStream *_Nullable thumbnailStream = TSAttachmentStream *_Nullable localThumbnail =
[self tryToDeriveLocalThumbnailWithAttachmentInfo:attachmentInfo [self tryToDeriveLocalThumbnailWithTimestamp:timestamp
timestamp:timestamp threadId:thread.uniqueId
threadId:thread.uniqueId authorId:authorId
authorId:authorId contentType:quotedAttachment.contentType
transaction:transaction]; transaction:transaction];
if (thumbnailStream) { if (localThumbnail) {
OWSLogDebug(@"Generated local thumbnail for quoted quoted message: %@:%lu", OWSLogDebug(@"Generated local thumbnail for quoted quoted message: %@:%lu",
thread.uniqueId, thread.uniqueId,
(unsigned long)timestamp); (unsigned long)timestamp);
[thumbnailStream saveWithTransaction:transaction]; [localThumbnail saveWithTransaction:transaction];
attachmentInfo.thumbnailAttachmentStreamId = thumbnailStream.uniqueId; attachmentInfo.thumbnailAttachmentStreamId = localThumbnail.uniqueId;
} else if (quotedAttachment.thumbnail) { } else if (quotedAttachment.thumbnail) {
OWSLogDebug(@"Saving reference for fetching remote thumbnail for quoted message: %@:%lu", OWSLogDebug(@"Saving reference for fetching remote thumbnail for quoted message: %@:%lu",
thread.uniqueId, thread.uniqueId,
@ -201,6 +202,9 @@ NS_ASSUME_NONNULL_BEGIN
} }
[attachmentInfos addObject:attachmentInfo]; [attachmentInfos addObject:attachmentInfo];
// For now, only support a single quoted attachment.
break;
} }
if (body.length == 0 && !hasAttachment) { if (body.length == 0 && !hasAttachment) {
@ -216,57 +220,76 @@ NS_ASSUME_NONNULL_BEGIN
receivedQuotedAttachmentInfos:attachmentInfos]; receivedQuotedAttachmentInfos:attachmentInfos];
} }
+ (nullable TSAttachmentStream *)tryToDeriveLocalThumbnailWithAttachmentInfo:(OWSAttachmentInfo *)attachmentInfo + (nullable TSAttachmentStream *)tryToDeriveLocalThumbnailWithTimestamp:(uint64_t)timestamp
timestamp:(uint64_t)timestamp threadId:(NSString *)threadId
threadId:(NSString *)threadId authorId:(NSString *)authorId
authorId:(NSString *)authorId contentType:(NSString *)contentType
transaction: transaction:(YapDatabaseReadWriteTransaction *)transaction
(YapDatabaseReadWriteTransaction *)transaction
{ {
if (![TSAttachmentStream hasThumbnailForMimeType:attachmentInfo.contentType]) { TSMessage *_Nullable quotedMessage =
[self findQuotedMessageWithTimestamp:timestamp threadId:threadId authorId:authorId transaction:transaction];
if (!quotedMessage) {
return nil; return nil;
} }
NSArray<TSMessage *> *quotedMessages = (NSArray<TSMessage *> *)[TSInteraction TSAttachment *_Nullable attachmentToQuote = nil;
interactionsWithTimestamp:timestamp if (quotedMessage.attachmentIds.count > 0) {
filter:^BOOL(TSInteraction *interaction) { attachmentToQuote = [quotedMessage attachmentsWithTransaction:transaction].firstObject;
if (![threadId isEqual:interaction.uniqueThreadId]) { } else if (quotedMessage.linkPreview && quotedMessage.linkPreview.imageAttachmentId.length > 0) {
return NO; attachmentToQuote =
} [TSAttachment fetchObjectWithUniqueID:quotedMessage.linkPreview.imageAttachmentId transaction:transaction];
}
if ([interaction isKindOfClass:[TSIncomingMessage class]]) { if (![attachmentToQuote isKindOfClass:[TSAttachmentStream class]]) {
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)interaction;
return [authorId isEqual:incomingMessage.authorId];
} else if ([interaction isKindOfClass:[TSOutgoingMessage class]]) {
return [authorId isEqual:[TSAccountManager localNumber]];
} else {
// ignore other interaction types
return NO;
}
}
withTransaction:transaction];
TSMessage *_Nullable quotedMessage = quotedMessages.firstObject;
if (!quotedMessage) {
return nil; return nil;
} }
if (![TSAttachmentStream hasThumbnailForMimeType:contentType]) {
// We quote _the first_ attachment, if any.
TSAttachment *_Nullable attachment = [quotedMessage attachmentsWithTransaction:transaction].firstObject;
if (![attachment isKindOfClass:[TSAttachmentStream class]]) {
return nil; return nil;
} }
TSAttachmentStream *sourceStream = (TSAttachmentStream *)attachment; TSAttachmentStream *sourceStream = (TSAttachmentStream *)attachmentToQuote;
return [sourceStream cloneAsThumbnail];
}
+ (nullable TSMessage *)findQuotedMessageWithTimestamp:(uint64_t)timestamp
threadId:(NSString *)threadId
authorId:(NSString *)authorId
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssertDebug(transaction);
TSAttachmentStream *_Nullable thumbnailStream = [sourceStream cloneAsThumbnail]; if (timestamp <= 0) {
if (!thumbnailStream) { OWSFailDebug(@"Invalid timestamp: %llu", timestamp);
return nil;
}
if (threadId.length <= 0) {
OWSFailDebug(@"Invalid thread.");
return nil;
}
if (authorId.length <= 0) {
OWSFailDebug(@"Invalid authorId: %@", authorId);
return nil; return nil;
} }
return thumbnailStream; for (TSMessage *message in
} [TSInteraction interactionsWithTimestamp:timestamp ofClass:TSMessage.class withTransaction:transaction]) {
if (![message.uniqueThreadId isEqualToString:threadId]) {
continue;
}
if ([message isKindOfClass:[TSIncomingMessage class]]) {
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)message;
if (![authorId isEqual:incomingMessage.authorId]) {
continue;
}
} else if ([message isKindOfClass:[TSOutgoingMessage class]]) {
if (![authorId isEqual:[TSAccountManager localNumber]]) {
continue;
}
}
return message;
}
OWSLogWarn(@"Could not find quoted message: %llu", timestamp);
return nil;
}
#pragma mark - Attachment (not necessarily with a thumbnail) #pragma mark - Attachment (not necessarily with a thumbnail)

@ -1443,13 +1443,13 @@ NS_ASSUME_NONNULL_BEGIN
[otherAttachmentIds removeObjectsInArray:incomingMessage.attachmentIds]; [otherAttachmentIds removeObjectsInArray:incomingMessage.attachmentIds];
} }
for (NSString *attachmentId in otherAttachmentIds) { for (NSString *attachmentId in otherAttachmentIds) {
TSAttachmentPointer *_Nullable attachmentPointer = TSAttachment *_Nullable attachment =
[TSAttachmentPointer fetchObjectWithUniqueID:attachmentId transaction:transaction]; [TSAttachment fetchObjectWithUniqueID:attachmentId transaction:transaction];
if (![attachment isKindOfClass:[TSAttachmentPointer class]]) {
if (![attachmentPointer isKindOfClass:[TSAttachmentPointer class]]) { OWSLogInfo(@"Skipping attachment stream.");
OWSFailDebug(@"Missing attachment pointer.");
continue; continue;
} }
TSAttachmentPointer *_Nullable attachmentPointer = (TSAttachmentPointer *)attachment;
OWSLogDebug(@"Downloading attachment for message: %lu", (unsigned long)incomingMessage.timestamp); OWSLogDebug(@"Downloading attachment for message: %lu", (unsigned long)incomingMessage.timestamp);

Loading…
Cancel
Save