Merge branch 'charlesmchen/badUnreadIndicatorAnimation'

pull/1/head
Matthew Chen 7 years ago
commit 4ee4df631c

@ -4847,9 +4847,11 @@ 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;
BOOL hasPlacedUnreadIndicator = NO;
for (ConversationViewItem *viewItem in viewItems) {
BOOL canShowDate = NO;
switch (viewItem.interaction.interactionType) {
@ -4884,12 +4886,47 @@ typedef enum : NSUInteger {
viewItem.shouldShowDate = shouldShowDate;
previousViewItemTimestamp = viewItemTimestamp;
// When a conversation without unread messages receives an incoming message,
// we call ensureDynamicInteractions to ensure that the unread indicator (etc.)
// state is updated accordingly. However this is done in a separate transaction.
// We don't want to show the incoming message _without_ an unread indicator and
// then immediately re-render it _with_ an unread indicator.
//
// To avoid this, we use a temporary instance of OWSUnreadIndicator whenever
// we find an unread message that _should_ have an unread indicator, but no
// unread indicator exists yet on dynamicInteractions.
BOOL isItemUnread = ([viewItem.interaction conformsToProtocol:@protocol(OWSReadTracking)]
&& !((id<OWSReadTracking>)viewItem.interaction).wasRead);
if (isItemUnread && !unreadIndicator && !hasPlacedUnreadIndicator) {
unreadIndicator =
[[OWSUnreadIndicator alloc] initUnreadIndicatorWithTimestamp:viewItem.interaction.timestamp
hasMoreUnseenMessages:NO
missingUnseenSafetyNumberChangeCount:0
unreadIndicatorPosition:0
firstUnseenInteractionTimestamp:viewItem.interaction.timestamp];
}
// Place the unread indicator onto the first appropriate view item,
// if any.
if (unreadIndicator && viewItem.interaction.timestampForSorting >= unreadIndicator.timestamp) {
viewItem.unreadIndicator = unreadIndicator;
unreadIndicator = nil;
hasPlacedUnreadIndicator = YES;
} 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 +4937,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 +4958,14 @@ typedef enum : NSUInteger {
// ...and always show the "disappearing messages" animation.
shouldHideFooter
= ([timestampText isEqualToString:nextTimestampText] && receiptStatus == nextReceiptStatus
&& outgoingMessage.messageState != TSOutgoingMessageStateFailed && !nextViewItem.shouldShowDate
&& outgoingMessage.messageState != TSOutgoingMessageStateFailed && !nextViewItem.hasCellHeader
&& !isDisappearingMessage);
}
// clustering
if (previousViewItem == nil) {
isFirstInCluster = YES;
} else if (viewItem.shouldShowDate) {
} else if (viewItem.hasCellHeader) {
isFirstInCluster = YES;
} else {
isFirstInCluster = previousViewItem.interaction.interactionType != OWSInteractionType_OutgoingMessage;
@ -4945,7 +4973,7 @@ typedef enum : NSUInteger {
if (nextViewItem == nil) {
isLastInCluster = YES;
} else if (nextViewItem.shouldShowDate) {
} else if (nextViewItem.hasCellHeader) {
isLastInCluster = YES;
} else {
isLastInCluster = nextViewItem.interaction.interactionType != OWSInteractionType_OutgoingMessage;
@ -4969,7 +4997,7 @@ 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 &&
shouldHideFooter = ([timestampText isEqualToString:nextTimestampText] && !nextViewItem.hasCellHeader &&
[NSObject isNullableObject:nextIncomingSenderId equalTo:incomingSenderId]
&& !isDisappearingMessage);
}
@ -4977,7 +5005,7 @@ typedef enum : NSUInteger {
// clustering
if (previousViewItem == nil) {
isFirstInCluster = YES;
} else if (viewItem.shouldShowDate) {
} else if (viewItem.hasCellHeader) {
isFirstInCluster = YES;
} else if (previousViewItem.interaction.interactionType != OWSInteractionType_IncomingMessage) {
isFirstInCluster = YES;
@ -4990,7 +5018,7 @@ typedef enum : NSUInteger {
isLastInCluster = YES;
} else if (nextViewItem.interaction.interactionType != OWSInteractionType_IncomingMessage) {
isLastInCluster = YES;
} else if (nextViewItem.shouldShowDate) {
} else if (nextViewItem.hasCellHeader) {
isLastInCluster = YES;
} else {
TSIncomingMessage *nextIncomingMessage = (TSIncomingMessage *)nextViewItem.interaction;
@ -5010,7 +5038,7 @@ typedef enum : NSUInteger {
shouldShowSenderName
= (![NSObject isNullableObject:previousIncomingSenderId equalTo:incomingSenderId]
|| viewItem.shouldShowDate);
|| viewItem.hasCellHeader);
}
if (shouldShowSenderName) {
senderName = [self.contactsManager
@ -5027,7 +5055,7 @@ typedef enum : NSUInteger {
shouldShowSenderAvatar = YES;
if (nextViewItem && nextViewItem.interaction.interactionType == interactionType) {
shouldShowSenderAvatar = (![NSObject isNullableObject:nextIncomingSenderId equalTo:incomingSenderId]
|| nextViewItem.shouldShowDate);
|| nextViewItem.hasCellHeader);
}
}
}
@ -5038,11 +5066,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;

Loading…
Cancel
Save