From 1b3f6c0ca6368c14ffe7b0f1a91aba85f37a40dd Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Tue, 1 Mar 2022 17:25:53 +1100 Subject: [PATCH] Minor tweaks to the message request banner on the HomeVC Fixed the unread message counting for message requests Updated the message request banner to indicate the number of message requests with an unread message Updated the message request banner to automatically disappear if the user has no unread message requests Renamed a variable for ReadReceipt management to make it a bit more self-documenting (it looked like it would trigger a read receipt to be sent regardless of the setting) --- .../ConversationMessageMapping.swift | 2 +- Session/Conversations/ConversationVC.swift | 7 ++-- Session/Home/HomeVC.swift | 27 +++++++++++++--- .../Messages/Signal/TSIncomingMessage.m | 8 ++--- .../Messages/Signal/TSInfoMessage.m | 4 +-- .../MessageReceiver+Handling.swift | 2 +- .../Read Tracking/OWSReadReceiptManager.h | 2 +- .../Read Tracking/OWSReadReceiptManager.m | 8 ++--- .../Read Tracking/OWSReadTracking.h | 2 +- SessionMessagingKit/Threads/TSThread.m | 2 +- .../Messaging/OWSMessageUtils.h | 1 + .../Messaging/OWSMessageUtils.m | 32 +++++++++++++++++++ 12 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Session/Conversations/ConversationMessageMapping.swift b/Session/Conversations/ConversationMessageMapping.swift index f48503948..7075edc57 100644 --- a/Session/Conversations/ConversationMessageMapping.swift +++ b/Session/Conversations/ConversationMessageMapping.swift @@ -229,7 +229,7 @@ public class ConversationMessageMapping: NSObject { let indexPtr: UnsafeMutablePointer = UnsafeMutablePointer.allocate(capacity: 1) let wasFound = view.getGroup(nil, index: indexPtr, forKey: uniqueId, inCollection: TSInteraction.collection()) guard wasFound else { - owsFailDebug("Could not find interaction.") + SNLog("Could not find interaction.") return nil } let index = indexPtr.pointee diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index 03d148f9a..ae14bfe0a 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -731,9 +731,12 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat } func markAllAsRead() { - guard !thread.isMessageRequest() else { return } guard let lastSortID = viewItems.last?.interaction.sortId else { return } - OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: lastSortID, thread: thread) + OWSReadReceiptManager.shared().markAsReadLocally( + beforeSortId: lastSortID, + thread: thread, + trySendReadReceipt: !thread.isMessageRequest() + ) SSKEnvironment.shared.disappearingMessagesJob.cleanupMessagesWhichFailedToStartExpiringFromNow() } diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index 3d3217e0f..fb307db18 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -6,6 +6,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv private var threads: YapDatabaseViewMappings! private var threadViewModelCache: [String:ThreadViewModel] = [:] // Thread ID to ThreadViewModel private var tableViewTopConstraint: NSLayoutConstraint! + private var unreadMessageRequestCount: UInt = 0 private var messageRequestCount: UInt { threads.numberOfItems(inGroup: TSMessageRequestGroup) @@ -196,7 +197,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv switch indexPath.section { case 0: let cell = tableView.dequeueReusableCell(withIdentifier: MessageRequestsCell.reuseIdentifier) as! MessageRequestsCell - cell.update(with: Int(messageRequestCount)) + cell.update(with: Int(unreadMessageRequestCount)) return cell default: @@ -263,6 +264,14 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv } } + // Update the number of unread message requests + unreadMessageRequestCount = OWSMessageUtils.sharedManager().unreadMessageRequestCount() + + // If there are no unread message requests then hide the message request banner + if unreadMessageRequestCount == 0 { + CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = true + } + return reload() } } @@ -286,11 +295,21 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv // If we need to unhide the message request row and then re-insert it if !messageRequestChanges.isEmpty { - if tableView.numberOfRows(inSection: 0) == 1 && Int(messageRequestCount) <= 0 { + // Update the number of unread message requests + unreadMessageRequestCount = OWSMessageUtils.sharedManager().unreadMessageRequestCount() + + // If there are no unread message requests then hide the message request banner + if unreadMessageRequestCount == 0 && tableView.numberOfRows(inSection: 0) == 1 { + CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = true tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) } - else if tableView.numberOfRows(inSection: 0) == 0 && Int(messageRequestCount) > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { - tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) + else { + if tableView.numberOfRows(inSection: 0) == 1 && Int(messageRequestCount) <= 0 { + tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) + } + else if tableView.numberOfRows(inSection: 0) == 0 && Int(messageRequestCount) > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { + tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) + } } } diff --git a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m index e80bf0bdb..a6578df0c 100644 --- a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m @@ -140,16 +140,16 @@ NS_ASSUME_NONNULL_BEGIN return YES; } -- (void)markAsReadNowWithSendReadReceipt:(BOOL)sendReadReceipt +- (void)markAsReadNowWithTrySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction; { [self markAsReadAtTimestamp:[NSDate millisecondTimestamp] - sendReadReceipt:sendReadReceipt + trySendReadReceipt:trySendReadReceipt transaction:transaction]; } - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - sendReadReceipt:(BOOL)sendReadReceipt + trySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction; { if (_read && readTimestamp >= self.expireStartedAt) { @@ -174,7 +174,7 @@ NS_ASSUME_NONNULL_BEGIN expirationStartedAt:readTimestamp transaction:transaction]; - if (sendReadReceipt) { + if (trySendReadReceipt) { [OWSReadReceiptManager.sharedManager messageWasReadLocally:self]; } } diff --git a/SessionMessagingKit/Messages/Signal/TSInfoMessage.m b/SessionMessagingKit/Messages/Signal/TSInfoMessage.m index 5785196a6..9d303a1bf 100644 --- a/SessionMessagingKit/Messages/Signal/TSInfoMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSInfoMessage.m @@ -134,7 +134,7 @@ NSUInteger TSInfoMessageSchemaVersion = 1; } - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - sendReadReceipt:(BOOL)sendReadReceipt + trySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction { if (_read) { @@ -144,7 +144,7 @@ NSUInteger TSInfoMessageSchemaVersion = 1; _read = YES; [self saveWithTransaction:transaction]; - // Ignore sendReadReceipt, it doesn't apply to info messages. + // Ignore trySendReadReceipt, it doesn't apply to info messages. } @end diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index de65ce5cf..ec7d226e6 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -390,7 +390,7 @@ extension MessageReceiver { if let tsOutgoingMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) as? TSOutgoingMessage, let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) { // Mark previous messages as read if there is a sync message - OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: tsOutgoingMessage.sortId, thread: thread) + OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: tsOutgoingMessage.sortId, thread: thread, trySendReadReceipt: true) } // Update the contact's approval status of the current user if needed (if we are getting messages from diff --git a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.h b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.h index d2c07812b..c2dfddec5 100644 --- a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.h +++ b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.h @@ -45,7 +45,7 @@ extern NSString *const kIncomingMessageMarkedAsReadNotification; // This method can be called from any thread. - (void)messageWasReadLocally:(TSIncomingMessage *)message; -- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread; +- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread trySendReadReceipt:(BOOL)trySendReadReceipt; #pragma mark - Settings diff --git a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m index 13a1b39c2..4517e2be4 100644 --- a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m +++ b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m @@ -180,13 +180,13 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE #pragma mark - Mark as Read Locally -- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread +- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread trySendReadReceipt:(BOOL)trySendReadReceipt { [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [self markAsReadBeforeSortId:sortId thread:thread readTimestamp:[NSDate millisecondTimestamp] - wasLocal:YES + trySendReadReceipt:trySendReadReceipt transaction:transaction]; }]; } @@ -254,7 +254,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE - (void)markAsReadBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread readTimestamp:(uint64_t)readTimestamp - wasLocal:(BOOL)wasLocal + trySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction { NSMutableArray> *newlyReadList = [NSMutableArray new]; @@ -285,7 +285,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE } for (id readItem in newlyReadList) { - [readItem markAsReadAtTimestamp:readTimestamp sendReadReceipt:wasLocal transaction:transaction]; + [readItem markAsReadAtTimestamp:readTimestamp trySendReadReceipt:trySendReadReceipt transaction:transaction]; } } diff --git a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadTracking.h b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadTracking.h index d8afaaa41..b08071959 100644 --- a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadTracking.h +++ b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadTracking.h @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN * Used both for *responding* to a remote read receipt and in response to the local user's activity. */ - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - sendReadReceipt:(BOOL)sendReadReceipt + trySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction; @end diff --git a/SessionMessagingKit/Threads/TSThread.m b/SessionMessagingKit/Threads/TSThread.m index 91484bba7..00049a305 100644 --- a/SessionMessagingKit/Threads/TSThread.m +++ b/SessionMessagingKit/Threads/TSThread.m @@ -309,7 +309,7 @@ BOOL IsNoteToSelfEnabled(void) - (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction { for (id message in [self unseenMessagesWithTransaction:transaction]) { - [message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] sendReadReceipt:YES transaction:transaction]; + [message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] trySendReadReceipt:YES transaction:transaction]; } } diff --git a/SignalUtilitiesKit/Messaging/OWSMessageUtils.h b/SignalUtilitiesKit/Messaging/OWSMessageUtils.h index ef693b8dc..3069360bf 100644 --- a/SignalUtilitiesKit/Messaging/OWSMessageUtils.h +++ b/SignalUtilitiesKit/Messaging/OWSMessageUtils.h @@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)sharedManager; - (NSUInteger)unreadMessagesCount; +- (NSUInteger)unreadMessageRequestCount; - (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread; - (void)updateApplicationBadgeCount; diff --git a/SignalUtilitiesKit/Messaging/OWSMessageUtils.m b/SignalUtilitiesKit/Messaging/OWSMessageUtils.m index fe8d0a4d1..b07a80bf8 100644 --- a/SignalUtilitiesKit/Messaging/OWSMessageUtils.m +++ b/SignalUtilitiesKit/Messaging/OWSMessageUtils.m @@ -112,6 +112,38 @@ NS_ASSUME_NONNULL_BEGIN return numberOfItems; } +- (NSUInteger)unreadMessageRequestCount { + __block NSUInteger count = 0; + + [LKStorage readWithBlock:^(YapDatabaseReadTransaction *transaction) { + YapDatabaseViewTransaction *unreadMessages = [transaction ext:TSUnreadDatabaseViewExtensionName]; + NSArray *allGroups = [unreadMessages allGroups]; + // FIXME: Confusingly, `allGroups` includes contact threads as well + for (NSString *groupID in allGroups) { + TSThread *thread = [TSThread fetchObjectWithUniqueID:groupID transaction:transaction]; + + // Only increase the count for message requests + if (!thread.isMessageRequest) { continue; } + + [unreadMessages enumerateKeysAndObjectsInGroup:groupID + usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { + if (![object conformsToProtocol:@protocol(OWSReadTracking)]) { + return; + } + id unread = (id)object; + if (unread.read) { + NSLog(@"Found an already read message in the * unread * messages list."); + return; + } + count += 1; + *stop = YES; + }]; + } + }]; + + return count; +} + - (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread { __block NSUInteger numberOfItems;