From 4d13c6bee5c1f0df53521f15c73b687dd7d12238 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Fri, 28 Aug 2020 11:10:59 +1000 Subject: [PATCH] Patch unread indicator bug --- .../ConversationViewController.m | 1 - .../ConversationView/ConversationViewModel.m | 12 +++++++-- SignalServiceKit/src/Contacts/TSThread.m | 26 +++++++++++++++++-- .../src/Messages/OWSMessageUtils.m | 25 ++++++++++++++++++ .../src/Messages/OWSReadReceiptManager.m | 5 +++- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 538b73f49..96f84c3ff 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -3607,7 +3607,6 @@ typedef enum : NSUInteger { // and won't update the UI state immediately. - (void)didScrollToBottom { - id _Nullable lastVisibleViewItem = [self.viewItems lastObject]; if (lastVisibleViewItem) { uint64_t lastVisibleSortId = lastVisibleViewItem.interaction.sortId; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewModel.m b/Signal/src/ViewControllers/ConversationView/ConversationViewModel.m index 9e699b2b3..693392413 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewModel.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewModel.m @@ -63,8 +63,16 @@ NS_ASSUME_NONNULL_BEGIN interactionIndexMap[viewItem.interaction.uniqueId] = @(i); [interactionIds addObject:viewItem.interaction.uniqueId]; - if (viewItem.unreadIndicator != nil) { - _unreadIndicatorIndex = @(i); + if (viewItem.unreadIndicator != nil && [viewItem.interaction conformsToProtocol:@protocol(OWSReadTracking)]) { + id interaction = (id)viewItem.interaction; + + // Under normal circumstances !interaction.read should always evaluate to true at this point, but + // there is a bug that can somehow cause it to be false leading to conversations permanently being + // stuck with "unread" messages. + + if (!interaction.read) { + _unreadIndicatorIndex = @(i); + } } } _interactionIndexMap = [interactionIndexMap copy]; diff --git a/SignalServiceKit/src/Contacts/TSThread.m b/SignalServiceKit/src/Contacts/TSThread.m index ec78d578c..eeb2a87f0 100644 --- a/SignalServiceKit/src/Contacts/TSThread.m +++ b/SignalServiceKit/src/Contacts/TSThread.m @@ -348,7 +348,12 @@ ConversationColorName const kConversationColorName_Default = ConversationColorNa OWSFailDebug(@"Unexpected object in unseen messages: %@", [object class]); return; } - [messages addObject:(id)object]; + id unread = (id)object; + if (unread.read) { + [LKLogger print:@"Found an already read message in the * unseen * messages list."]; + return; + } + [messages addObject:unread]; }]; return [messages copy]; @@ -356,7 +361,24 @@ ConversationColorName const kConversationColorName_Default = ConversationColorNa - (NSUInteger)unreadMessageCountWithTransaction:(YapDatabaseReadTransaction *)transaction { - return [[transaction ext:TSUnreadDatabaseViewExtensionName] numberOfItemsInGroup:self.uniqueId]; + __block NSUInteger count = 0; + + YapDatabaseViewTransaction *unreadMessages = [transaction ext:TSUnreadDatabaseViewExtensionName]; + [unreadMessages enumerateKeysAndObjectsInGroup:self.uniqueId + usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { + if (![object conformsToProtocol:@protocol(OWSReadTracking)]) { + OWSFailDebug(@"Unexpected object in unread messages: %@", [object class]); + return; + } + id unread = (id)object; + if (unread.read) { + [LKLogger print:@"Found an already read message in the * unread * messages list."]; + return; + } + count += 1; + }]; + + return count; } - (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction diff --git a/SignalServiceKit/src/Messages/OWSMessageUtils.m b/SignalServiceKit/src/Messages/OWSMessageUtils.m index 5b39aa3af..a3e5e54bc 100644 --- a/SignalServiceKit/src/Messages/OWSMessageUtils.m +++ b/SignalServiceKit/src/Messages/OWSMessageUtils.m @@ -18,6 +18,7 @@ #import "TSThread.h" #import "UIImage+OWS.h" #import +#import NS_ASSUME_NONNULL_BEGIN @@ -65,6 +66,30 @@ NS_ASSUME_NONNULL_BEGIN - (NSUInteger)unreadMessagesCount { + __block NSUInteger count = 0; + + [LKStorage readWithBlock:^(YapDatabaseReadTransaction *transaction) { + YapDatabaseViewTransaction *unreadMessages = [transaction ext:TSUnreadDatabaseViewExtensionName]; + NSArray *allGroups = [unreadMessages allGroups]; + for (NSString *groupID in allGroups) { + [unreadMessages enumerateKeysAndObjectsInGroup:groupID + usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { + if (![object conformsToProtocol:@protocol(OWSReadTracking)]) { + OWSFailDebug(@"Unexpected object in unread messages: %@", [object class]); + return; + } + id unread = (id)object; + if (unread.read) { + [LKLogger print:@"Found an already read message in the * unread * messages list."]; + return; + } + count += 1; + }]; + } + }]; + + return count; + __block NSUInteger numberOfItems; [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { numberOfItems = [[transaction ext:TSUnreadDatabaseViewExtensionName] numberOfItemsInAllGroups]; diff --git a/SignalServiceKit/src/Messages/OWSReadReceiptManager.m b/SignalServiceKit/src/Messages/OWSReadReceiptManager.m index c51fa0578..a5bdb80d5 100644 --- a/SignalServiceKit/src/Messages/OWSReadReceiptManager.m +++ b/SignalServiceKit/src/Messages/OWSReadReceiptManager.m @@ -491,7 +491,10 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE return; } - OWSAssertDebug(!possiblyRead.read); + // Under normal circumstances !possiblyRead.read should always evaluate to true at this point, but + // there is a bug that can somehow cause it to be false leading to conversations permanently being + // stuck with "unread" messages. + OWSAssertDebug(possiblyRead.expireStartedAt == 0); if (!possiblyRead.read) { [newlyReadList addObject:possiblyRead];