From 578f40d7919bf5ed87c775ba9348ae410a2a5904 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 29 Mar 2018 11:25:19 -0400 Subject: [PATCH] Bubble collapse. --- .../ConversationView/Cells/OWSMessageCell.m | 36 +++---- .../ConversationView/ConversationViewItem.h | 4 +- .../ConversationView/ConversationViewItem.m | 99 ++++++++++--------- .../MessageDetailViewController.swift | 4 +- 4 files changed, 72 insertions(+), 71 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m index 260d1d7dc..55c79529e 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m @@ -155,7 +155,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) OWSAssert(DisplayableText.kMaxJumbomojiCount == 5); CGFloat basePointSize = [UIFont ows_dynamicTypeBodyFont].pointSize; - switch (self.displayableText.jumbomojiCount) { + switch (self.displayableBodyText.jumbomojiCount) { case 0: break; case 1: @@ -167,7 +167,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) case 5: return [UIFont ows_regularFontWithSize:basePointSize + 6.f]; default: - OWSFail(@"%@ Unexpected jumbomoji count: %zd", self.logTag, self.displayableText.jumbomojiCount); + OWSFail(@"%@ Unexpected jumbomoji count: %zd", self.logTag, self.displayableBodyText.jumbomojiCount); break; } @@ -211,20 +211,20 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) return self.viewItem.messageCellType; } -- (BOOL)hasText +- (BOOL)hasBodyText { // This should always be valid for the appropriate cell types. OWSAssert(self.viewItem); - return self.viewItem.hasText; + return self.viewItem.hasBodyText; } -- (nullable DisplayableText *)displayableText +- (nullable DisplayableText *)displayableBodyText { // This should always be valid for the appropriate cell types. - OWSAssert(self.viewItem.displayableText); + OWSAssert(self.viewItem.displayableBodyText); - return self.viewItem.displayableText; + return self.viewItem.displayableBodyText; } - (nullable TSAttachmentStream *)attachmentStream @@ -271,7 +271,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) case OWSMessageCellType_AnimatedImage: case OWSMessageCellType_Audio: case OWSMessageCellType_Video: - return self.hasText; + return self.hasBodyText; } } @@ -289,7 +289,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) case OWSMessageCellType_Audio: case OWSMessageCellType_Video: // Is there a caption? - return self.hasText; + return self.hasBodyText; } } @@ -448,7 +448,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) OWSMessageTextView *_Nullable bodyTextView = nil; // We render malformed messages as "empty text" messages, // so create a text view if there is no body media view. - if (self.hasText || !bodyMediaView) { + if (self.hasBodyText || !bodyMediaView) { bodyTextView = [self createBodyTextViewIfNecessary]; } if (bodyTextView) { @@ -754,7 +754,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) shouldIgnoreEvents = outgoingMessage.messageState != TSOutgoingMessageStateSentToService; } [self.class loadForTextDisplay:self.bodyTextViewCached - text:self.displayableText.displayText + text:self.displayableBodyText.displayText textColor:self.textColor font:self.textMessageFont shouldIgnoreEvents:shouldIgnoreEvents]; @@ -783,10 +783,10 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) - (nullable UIView *)createTapForMoreLabelIfNecessary { - if (!self.hasText) { + if (!self.hasBodyText) { return nil; } - if (!self.displayableText.isTextTruncated) { + if (!self.displayableBodyText.isTextTruncated) { return nil; } @@ -1050,7 +1050,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) // Size of "message body" text, not quoted reply text. - (CGSize)bodyTextSizeForContentWidth:(int)contentWidth includeMargins:(BOOL)includeMargins { - if (!self.hasText) { + if (!self.hasBodyText) { return CGSizeZero; } @@ -1061,7 +1061,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) const int maxMessageWidth = [self maxMessageWidthForContentWidth:contentWidth]; const int maxTextWidth = (int)floor(maxMessageWidth - (leftMargin + rightMargin)); - self.bodyTextViewCached.text = self.displayableText.displayText; + self.bodyTextViewCached.text = self.displayableBodyText.displayText; // Honor dynamic type in the message bodies. self.bodyTextViewCached.font = [self textMessageFont]; CGSize textSize = CGSizeCeil([self.bodyTextViewCached sizeThatFits:CGSizeMake(maxTextWidth, CGFLOAT_MAX)]); @@ -1142,7 +1142,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) cellSize.height += self.dateHeaderHeight; cellSize.height += self.footerHeight; - if (self.hasText && self.displayableText.isTextTruncated) { + if (self.hasBodyText && self.displayableBodyText.isTextTruncated) { cellSize.height += self.tapForMoreHeight; } @@ -1344,7 +1344,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) } } - if (self.hasText && self.displayableText.isTextTruncated) { + if (self.hasBodyText && self.displayableBodyText.isTextTruncated) { [self.delegate didTapTruncatedTextMessage:self.viewItem]; return; } @@ -1375,7 +1375,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) break; case OWSMessageCellType_TextMessage: case OWSMessageCellType_OversizeTextMessage: - if (self.displayableText.isTextTruncated) { + if (self.displayableBodyText.isTextTruncated) { [self.delegate didTapTruncatedTextMessage:self.viewItem]; return; } diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h index 8f7e345c8..1777bf38d 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h @@ -43,7 +43,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType); @property (nonatomic, readonly) TSInteraction *interaction; @property (nonatomic, readonly) BOOL isGroupThread; -@property (nonatomic, readonly) BOOL hasText; +@property (nonatomic, readonly) BOOL hasBodyText; @property (nonatomic) BOOL shouldShowDate; @property (nonatomic) BOOL shouldHideRecipientStatus; @@ -79,7 +79,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType); // These methods only apply to text & attachment messages. - (OWSMessageCellType)messageCellType; -- (nullable DisplayableText *)displayableText; +- (nullable DisplayableText *)displayableBodyText; - (nullable TSAttachmentStream *)attachmentStream; - (nullable TSAttachmentPointer *)attachmentPointer; - (CGSize)mediaSize; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m index a26eac86f..0c6de073d 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m @@ -56,12 +56,12 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) @property (nonatomic) BOOL hasViewState; @property (nonatomic) OWSMessageCellType messageCellType; // TODO: Rename to displayableBodyText. -@property (nonatomic, nullable) DisplayableText *displayableText; +@property (nonatomic, nullable) DisplayableText *displayableBodyText; @property (nonatomic, nullable) TSAttachmentStream *attachmentStream; @property (nonatomic, nullable) TSAttachmentPointer *attachmentPointer; @property (nonatomic) CGSize mediaSize; // TODO: Remove in favor of displayableBodyText nil test. -//@property (nonatomic) BOOL hasText; +//@property (nonatomic) BOOL hasBodyText; @end @@ -97,7 +97,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) self.hasViewState = NO; self.messageCellType = OWSMessageCellType_Unknown; - self.displayableText = nil; + self.displayableBodyText = nil; self.attachmentStream = nil; self.attachmentPointer = nil; self.mediaSize = CGSizeZero; @@ -107,9 +107,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) [self ensureViewState:transaction]; } -- (BOOL)hasText +- (BOOL)hasBodyText { - return _displayableText != nil; + return _displayableBodyText != nil; } - (void)setShouldShowDate:(BOOL)shouldShowDate @@ -271,7 +271,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) // TODO: Now that we're caching the displayable text on the view items, // I don't think we need this cache any more. -- (NSCache *)displayableTextCache +- (NSCache *)displayableBodyTextCache { static NSCache *cache = nil; static dispatch_once_t onceToken; @@ -283,44 +283,45 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) return cache; } -- (DisplayableText *)displayableTextForText:(NSString *)text interactionId:(NSString *)interactionId +- (DisplayableText *)displayableBodyTextForText:(NSString *)text interactionId:(NSString *)interactionId { OWSAssert(text); OWSAssert(interactionId.length > 0); - return [self displayableTextForInteractionId:interactionId - textBlock:^{ - return text; - }]; + return [self displayableBodyTextForInteractionId:interactionId + textBlock:^{ + return text; + }]; } -- (DisplayableText *)displayableTextForOversizeTextAttachment:(TSAttachmentStream *)attachmentStream - interactionId:(NSString *)interactionId +- (DisplayableText *)displayableBodyTextForOversizeTextAttachment:(TSAttachmentStream *)attachmentStream + interactionId:(NSString *)interactionId { OWSAssert(attachmentStream); OWSAssert(interactionId.length > 0); - return [self displayableTextForInteractionId:interactionId - textBlock:^{ - NSData *textData = [NSData dataWithContentsOfURL:attachmentStream.mediaURL]; - NSString *text = - [[NSString alloc] initWithData:textData encoding:NSUTF8StringEncoding]; - return text; - }]; + return + [self displayableBodyTextForInteractionId:interactionId + textBlock:^{ + NSData *textData = [NSData dataWithContentsOfURL:attachmentStream.mediaURL]; + NSString *text = + [[NSString alloc] initWithData:textData encoding:NSUTF8StringEncoding]; + return text; + }]; } -- (DisplayableText *)displayableTextForInteractionId:(NSString *)interactionId - textBlock:(NSString * (^_Nonnull)(void))textBlock +- (DisplayableText *)displayableBodyTextForInteractionId:(NSString *)interactionId + textBlock:(NSString * (^_Nonnull)(void))textBlock { OWSAssert(interactionId.length > 0); - DisplayableText *_Nullable displayableText = [[self displayableTextCache] objectForKey:interactionId]; - if (!displayableText) { + DisplayableText *_Nullable displayableBodyText = [[self displayableBodyTextCache] objectForKey:interactionId]; + if (!displayableBodyText) { NSString *text = textBlock(); - displayableText = [DisplayableText displayableText:text]; - [[self displayableTextCache] setObject:displayableText forKey:interactionId]; + displayableBodyText = [DisplayableText displayableText:text]; + [[self displayableBodyTextCache] setObject:displayableBodyText forKey:interactionId]; } - return displayableText; + return displayableBodyText; } - (nullable TSAttachment *)firstAttachmentIfAnyOfMessage:(TSMessage *)message @@ -360,9 +361,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) if ([attachment.contentType isEqualToString:OWSMimeTypeOversizeTextMessage]) { self.messageCellType = OWSMessageCellType_OversizeTextMessage; - self.displayableText = [self displayableTextForOversizeTextAttachment:self.attachmentStream - interactionId:message.uniqueId]; - // self.hasText = YES; + self.displayableBodyText = [self displayableBodyTextForOversizeTextAttachment:self.attachmentStream + interactionId:message.uniqueId]; + // self.hasBodyText = YES; } else if ([self.attachmentStream isAnimated] || [self.attachmentStream isImage] || [self.attachmentStream isVideo]) { if ([self.attachmentStream isAnimated]) { @@ -407,19 +408,19 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) // Ignore message body for oversize text attachments. if (message.body.length > 0) { - if (self.hasText) { + if (self.hasBodyText) { OWSFail(@"%@ oversize text message has unexpected caption.", self.logTag); } - // self.hasText = YES; + // self.hasBodyText = YES; // If we haven't already assigned an attachment type at this point, message.body isn't a caption, // it's a stand-alone text message. if (self.messageCellType == OWSMessageCellType_Unknown) { OWSAssert(message.attachmentIds.count == 0); self.messageCellType = OWSMessageCellType_TextMessage; } - self.displayableText = [self displayableTextForText:message.body interactionId:message.uniqueId]; - OWSAssert(self.displayableText); + self.displayableBodyText = [self displayableBodyTextForText:message.body interactionId:message.uniqueId]; + OWSAssert(self.displayableBodyText); } if (self.messageCellType == OWSMessageCellType_Unknown) { @@ -427,8 +428,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) // are rendered like empty text messages, but without any interactivity. DDLogWarn(@"%@ Treating unknown message as empty text message: %@", self.logTag, message.description); self.messageCellType = OWSMessageCellType_TextMessage; - // self.hasText = YES; - self.displayableText = [[DisplayableText alloc] initWithFullText:@"" displayText:@"" isTextTruncated:NO]; + // self.hasBodyText = YES; + self.displayableBodyText = [[DisplayableText alloc] initWithFullText:@"" displayText:@"" isTextTruncated:NO]; } } @@ -439,16 +440,16 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) return _messageCellType; } -- (nullable DisplayableText *)displayableText +- (nullable DisplayableText *)displayableBodyText { OWSAssertIsOnMainThread(); OWSAssert(self.hasViewState); - OWSAssert(_displayableText); - OWSAssert(_displayableText.displayText); - OWSAssert(_displayableText.fullText); + OWSAssert(_displayableBodyText); + OWSAssert(_displayableBodyText.displayText); + OWSAssert(_displayableBodyText.fullText); - return _displayableText; + return _displayableBodyText; } - (nullable TSAttachmentStream *)attachmentStream @@ -551,13 +552,13 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) - (BOOL)canPerformAction:(SEL)action { if (action == self.copyTextActionSelector) { - return [self hasTextActionContent]; + return [self hasBodyTextActionContent]; } else if (action == self.copyMediaActionSelector) { return [self hasMediaActionContent]; } else if (action == self.saveMediaActionSelector) { return [self canSaveMedia]; } else if (action == self.shareTextActionSelector) { - return [self hasTextActionContent]; + return [self hasBodyTextActionContent]; } else if (action == self.shareMediaActionSelector) { return [self hasMediaActionContent]; } else if (action == self.deleteActionSelector) { @@ -579,8 +580,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) case OWSMessageCellType_Audio: case OWSMessageCellType_Video: case OWSMessageCellType_GenericAttachment: { - OWSAssert(self.displayableText); - [UIPasteboard.generalPasteboard setString:self.displayableText.fullText]; + OWSAssert(self.displayableBodyText); + [UIPasteboard.generalPasteboard setString:self.displayableBodyText.fullText]; break; } case OWSMessageCellType_DownloadingAttachment: { @@ -638,8 +639,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) case OWSMessageCellType_Audio: case OWSMessageCellType_Video: case OWSMessageCellType_GenericAttachment: { - OWSAssert(self.displayableText); - [AttachmentSharing showShareUIForText:self.displayableText.fullText]; + OWSAssert(self.displayableBodyText); + [AttachmentSharing showShareUIForText:self.displayableBodyText.fullText]; break; } case OWSMessageCellType_DownloadingAttachment: { @@ -746,9 +747,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) [self.interaction remove]; } -- (BOOL)hasTextActionContent +- (BOOL)hasBodyTextActionContent { - return self.hasText && self.displayableText.fullText.length > 0; + return self.hasBodyText && self.displayableBodyText.fullText.length > 0; } - (BOOL)hasMediaActionContent diff --git a/Signal/src/ViewControllers/MessageDetailViewController.swift b/Signal/src/ViewControllers/MessageDetailViewController.swift index 1f9e964cb..f657d9af6 100644 --- a/Signal/src/ViewControllers/MessageDetailViewController.swift +++ b/Signal/src/ViewControllers/MessageDetailViewController.swift @@ -307,10 +307,10 @@ class MessageDetailViewController: OWSViewController, UIScrollViewDelegate, Medi } private func displayableTextIfText() -> String? { - guard viewItem.hasText else { + guard viewItem.hasBodyText else { return nil } - guard let displayableText = viewItem.displayableText() else { + guard let displayableText = viewItem.displayableBodyText() else { return nil } let messageBody = displayableText.fullText