diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m index 50d0b0830..76bbf744a 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m @@ -143,7 +143,7 @@ NS_ASSUME_NONNULL_BEGIN [self.messageBubbleView configureViews]; [self.messageBubbleView loadContent]; - if (self.viewItem.hasCellHeader) { + if (self.viewItem.hasDateOrUnreadBreak) { CGFloat headerHeight = [self.headerView measureWithConversationViewItem:self.viewItem conversationStyle:self.conversationStyle] .height; @@ -342,7 +342,7 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert(cellSize.width > 0 && cellSize.height > 0); - if (self.viewItem.hasCellHeader) { + if (self.viewItem.hasDateOrUnreadBreak) { cellSize.height += [self.headerView measureWithConversationViewItem:self.viewItem conversationStyle:self.conversationStyle] .height; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index a568443c1..9b7858258 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -4847,9 +4847,10 @@ typedef enum : NSUInteger { } }]; - // Update the "shouldShowDate" property of the view items. + // Update the "break" properties (shouldShowDate and unreadIndicator) of the view items. BOOL shouldShowDateOnNextViewItem = YES; uint64_t previousViewItemTimestamp = 0; + OWSUnreadIndicator *_Nullable unreadIndicator = self.dynamicInteractions.unreadIndicator; for (ConversationViewItem *viewItem in viewItems) { BOOL canShowDate = NO; switch (viewItem.interaction.interactionType) { @@ -4884,12 +4885,25 @@ typedef enum : NSUInteger { viewItem.shouldShowDate = shouldShowDate; previousViewItemTimestamp = viewItemTimestamp; + + // Place the unread indicator onto the first appropriate view item, + // if any. + if (unreadIndicator && viewItem.interaction.timestampForSorting >= unreadIndicator.timestamp) { + viewItem.unreadIndicator = unreadIndicator; + unreadIndicator = nil; + } else { + viewItem.unreadIndicator = nil; + } + } + if (unreadIndicator) { + // This isn't necessarily a bug - all of the interactions after the + // unread indicator may have disappeared or been deleted. + DDLogWarn(@"%@ Couldn't find an interaction to hang the unread indicator on.", self.logTag); } // Update the properties of the view items. // - // NOTE: This logic uses shouldShowDate which is set in the previous pass. - OWSUnreadIndicator *_Nullable unreadIndicator = self.dynamicInteractions.unreadIndicator; + // NOTE: This logic uses the break properties which are set in the previous pass. for (NSUInteger i = 0; i < viewItems.count; i++) { ConversationViewItem *viewItem = viewItems[i]; ConversationViewItem *_Nullable previousViewItem = (i > 0 ? viewItems[i - 1] : nil); @@ -4900,15 +4914,6 @@ typedef enum : NSUInteger { BOOL isLastInCluster = YES; NSAttributedString *_Nullable senderName = nil; - // Place the unread indicator onto the first appropriate view item, - // if any. - if (unreadIndicator && viewItem.interaction.timestampForSorting >= unreadIndicator.timestamp) { - viewItem.unreadIndicator = unreadIndicator; - unreadIndicator = nil; - } else { - viewItem.unreadIndicator = nil; - } - OWSInteractionType interactionType = viewItem.interaction.interactionType; NSString *timestampText = [DateUtil formatTimestampShort:viewItem.interaction.timestamp]; @@ -4930,14 +4935,14 @@ typedef enum : NSUInteger { // ...and always show the "disappearing messages" animation. shouldHideFooter = ([timestampText isEqualToString:nextTimestampText] && receiptStatus == nextReceiptStatus - && outgoingMessage.messageState != TSOutgoingMessageStateFailed && !nextViewItem.shouldShowDate - && !isDisappearingMessage); + && outgoingMessage.messageState != TSOutgoingMessageStateFailed + && !nextViewItem.hasDateOrUnreadBreak && !isDisappearingMessage); } // clustering if (previousViewItem == nil) { isFirstInCluster = YES; - } else if (viewItem.shouldShowDate) { + } else if (viewItem.hasDateOrUnreadBreak) { isFirstInCluster = YES; } else { isFirstInCluster = previousViewItem.interaction.interactionType != OWSInteractionType_OutgoingMessage; @@ -4945,7 +4950,7 @@ typedef enum : NSUInteger { if (nextViewItem == nil) { isLastInCluster = YES; - } else if (nextViewItem.shouldShowDate) { + } else if (nextViewItem.hasDateOrUnreadBreak) { isLastInCluster = YES; } else { isLastInCluster = nextViewItem.interaction.interactionType != OWSInteractionType_OutgoingMessage; @@ -4969,15 +4974,16 @@ typedef enum : NSUInteger { // We can skip the "incoming message status" footer in a cluster if the next message // has the same footer and no "date break" separates us. // ...but always show the "disappearing messages" animation. - shouldHideFooter = ([timestampText isEqualToString:nextTimestampText] && !nextViewItem.shouldShowDate && - [NSObject isNullableObject:nextIncomingSenderId equalTo:incomingSenderId] - && !isDisappearingMessage); + shouldHideFooter + = ([timestampText isEqualToString:nextTimestampText] && !nextViewItem.hasDateOrUnreadBreak && + [NSObject isNullableObject:nextIncomingSenderId equalTo:incomingSenderId] + && !isDisappearingMessage); } // clustering if (previousViewItem == nil) { isFirstInCluster = YES; - } else if (viewItem.shouldShowDate) { + } else if (viewItem.hasDateOrUnreadBreak) { isFirstInCluster = YES; } else if (previousViewItem.interaction.interactionType != OWSInteractionType_IncomingMessage) { isFirstInCluster = YES; @@ -4990,7 +4996,7 @@ typedef enum : NSUInteger { isLastInCluster = YES; } else if (nextViewItem.interaction.interactionType != OWSInteractionType_IncomingMessage) { isLastInCluster = YES; - } else if (nextViewItem.shouldShowDate) { + } else if (nextViewItem.hasDateOrUnreadBreak) { isLastInCluster = YES; } else { TSIncomingMessage *nextIncomingMessage = (TSIncomingMessage *)nextViewItem.interaction; @@ -5010,7 +5016,7 @@ typedef enum : NSUInteger { shouldShowSenderName = (![NSObject isNullableObject:previousIncomingSenderId equalTo:incomingSenderId] - || viewItem.shouldShowDate); + || viewItem.hasDateOrUnreadBreak); } if (shouldShowSenderName) { senderName = [self.contactsManager @@ -5027,7 +5033,7 @@ typedef enum : NSUInteger { shouldShowSenderAvatar = YES; if (nextViewItem && nextViewItem.interaction.interactionType == interactionType) { shouldShowSenderAvatar = (![NSObject isNullableObject:nextIncomingSenderId equalTo:incomingSenderId] - || nextViewItem.shouldShowDate); + || nextViewItem.hasDateOrUnreadBreak); } } } @@ -5038,11 +5044,6 @@ typedef enum : NSUInteger { viewItem.shouldHideFooter = shouldHideFooter; viewItem.senderName = senderName; } - if (unreadIndicator) { - // This isn't necessarily a bug - all of the interactions after the - // unread indicator may have disappeared or been deleted. - DDLogWarn(@"%@ Couldn't find an interaction to hang the unread indicator on.", self.logTag); - } self.viewItems = viewItems; self.viewItemCache = viewItemCache; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h index 94c2b0fc8..80c5dee70 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h @@ -54,7 +54,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType); @property (nonatomic, readonly) BOOL isQuotedReply; @property (nonatomic, readonly) BOOL hasQuotedAttachment; @property (nonatomic, readonly) BOOL hasQuotedText; -@property (nonatomic, readonly) BOOL hasCellHeader; +@property (nonatomic, readonly) BOOL hasDateOrUnreadBreak; @property (nonatomic, readonly) BOOL isExpiringMessage; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m index edb6b0fc9..ec2ac7515 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m @@ -150,7 +150,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) return message.isExpiringMessage; } -- (BOOL)hasCellHeader +- (BOOL)hasDateOrUnreadBreak { return self.shouldShowDate || self.unreadIndicator; } @@ -277,7 +277,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) { OWSAssert(previousLayoutItem); - if (self.hasCellHeader) { + if (self.hasDateOrUnreadBreak) { return OWSMessageHeaderViewDateHeaderVMargin; }