From e243fb88176a1c31e6dac2b8e6723d55f49a996b Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Wed, 2 Mar 2022 11:31:33 +1100 Subject: [PATCH 1/4] fix unread message request count issues --- Session/Home/HomeVC.swift | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index bea05f1f0..cefd0cb34 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -6,10 +6,8 @@ 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) + private var unreadMessageRequestCount: UInt { + OWSMessageUtils.sharedManager().unreadMessageRequestCount() } private var threadCount: UInt { @@ -182,7 +180,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch section { case 0: - if messageRequestCount > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { + if unreadMessageRequestCount > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { return 1 } @@ -264,9 +262,6 @@ 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 @@ -295,8 +290,6 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv // If we need to unhide the message request row and then re-insert it if !messageRequestChanges.isEmpty { - // 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 { @@ -304,10 +297,10 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) } else { - if tableView.numberOfRows(inSection: 0) == 1 && Int(messageRequestCount) <= 0 { + if tableView.numberOfRows(inSection: 0) == 1 && Int(unreadMessageRequestCount) <= 0 { tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) } - else if tableView.numberOfRows(inSection: 0) == 0 && Int(messageRequestCount) > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { + else if tableView.numberOfRows(inSection: 0) == 0 && Int(unreadMessageRequestCount) > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) } } From 22921a6b5a99a13a9d8a673b10395be65e495209 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Thu, 3 Mar 2022 10:37:50 +1100 Subject: [PATCH 2/4] Fixed a crash due to not passing the transaction when accessing the database --- SignalUtilitiesKit/Messaging/OWSMessageUtils.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SignalUtilitiesKit/Messaging/OWSMessageUtils.m b/SignalUtilitiesKit/Messaging/OWSMessageUtils.m index b07a80bf8..f8a932fa6 100644 --- a/SignalUtilitiesKit/Messaging/OWSMessageUtils.m +++ b/SignalUtilitiesKit/Messaging/OWSMessageUtils.m @@ -123,7 +123,7 @@ NS_ASSUME_NONNULL_BEGIN TSThread *thread = [TSThread fetchObjectWithUniqueID:groupID transaction:transaction]; // Only increase the count for message requests - if (!thread.isMessageRequest) { continue; } + if (![thread isMessageRequestUsingTransaction:transaction]) { continue; } [unreadMessages enumerateKeysAndObjectsInGroup:groupID usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { From decb946bf30e4e94688993b05563a220e44f8d2c Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Fri, 4 Mar 2022 17:17:58 +1100 Subject: [PATCH 3/4] Fixed an unrecognised selector crash hidden by the conversion of Objective-C to Swift --- SessionMessagingKit/Messages/Signal/TSIncomingMessage.h | 2 +- .../Sending & Receiving/MessageReceiver+Handling.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.h b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.h index b4a0edb0e..c965ff51b 100644 --- a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.h +++ b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.h @@ -85,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) NSString *authorId; // convenience method for expiring a message which was just read -- (void)markAsReadNowWithSendReadReceipt:(BOOL)sendReadReceipt +- (void)markAsReadNowWithTrySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction; - (void)setNotificationIdentifier:(NSString * _Nullable)notificationIdentifier diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index ec7d226e6..5df789c88 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -296,7 +296,7 @@ extension MessageReceiver { } if let messageToDelete = localMessage { if let incomingMessage = messageToDelete as? TSIncomingMessage { - incomingMessage.markAsReadNow(withSendReadReceipt: false, transaction: transaction) + incomingMessage.markAsReadNow(withTrySendReadReceipt: false, transaction: transaction) if let notificationIdentifier = incomingMessage.notificationIdentifier, !notificationIdentifier.isEmpty { UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [notificationIdentifier]) UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [notificationIdentifier]) From af543b980bef0b822d33c734729fc56e2e3f33d3 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Mon, 7 Mar 2022 10:22:46 +1100 Subject: [PATCH 4/4] Made a couple of changes to how the ConfigurationMessage is generated and handled Stopped configuration messages from automatically creating threads for sync'ed contacts (now they will only be created if there are messages) Updated the ConfigurationMessage to stop truncating the list of contacts but filter the full set (also update the logic to include previously approved contacts) --- Session.xcodeproj/project.pbxproj | 8 +- Session/Utilities/ContactUtilities.swift | 1 + .../ConfigurationMessage+Convenience.swift | 79 ++++++++++--------- .../MessageReceiver+Handling.swift | 6 -- ...escription.swift => Array+Utilities.swift} | 6 ++ 5 files changed, 51 insertions(+), 49 deletions(-) rename SessionUtilitiesKit/General/{Array+Description.swift => Array+Utilities.swift} (61%) diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index d66006e48..f9a470e50 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -675,7 +675,7 @@ C3A7219A2558C1660043A11F /* AnyPromise+Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3A721992558C1660043A11F /* AnyPromise+Conversion.swift */; }; C3A7225E2558C38D0043A11F /* Promise+Retaining.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3A7225D2558C38D0043A11F /* Promise+Retaining.swift */; }; C3A76A8D25DB83F90074CB90 /* PermissionMissingModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3A76A8C25DB83F90074CB90 /* PermissionMissingModal.swift */; }; - C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D12553860800C340D1 /* Array+Description.swift */; }; + C3AABDDF2553ECF00042FF4C /* Array+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D12553860800C340D1 /* Array+Utilities.swift */; }; C3AAFFF225AE99710089E6DD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFF125AE99710089E6DD /* AppDelegate.swift */; }; C3ADC66126426688005F1414 /* ShareVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3ADC66026426688005F1414 /* ShareVC.swift */; }; C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE0752554CDA60050F1E3 /* Configuration.swift */; }; @@ -1749,7 +1749,7 @@ C3C2A5CE2553860700C340D1 /* Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = ""; }; C3C2A5CF2553860700C340D1 /* Promise+Hashing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Promise+Hashing.swift"; sourceTree = ""; }; C3C2A5D02553860800C340D1 /* Promise+Threading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Promise+Threading.swift"; sourceTree = ""; }; - C3C2A5D12553860800C340D1 /* Array+Description.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Description.swift"; sourceTree = ""; }; + C3C2A5D12553860800C340D1 /* Array+Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Utilities.swift"; sourceTree = ""; }; C3C2A5D22553860900C340D1 /* String+Trimming.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Trimming.swift"; sourceTree = ""; }; C3C2A5D32553860900C340D1 /* Promise+Delaying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Promise+Delaying.swift"; sourceTree = ""; }; C3C2A5D42553860A00C340D1 /* Threading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Threading.swift; sourceTree = ""; }; @@ -2349,7 +2349,7 @@ children = ( C33FDB8A255A581200E217F9 /* AppContext.h */, C33FDB85255A581100E217F9 /* AppContext.m */, - C3C2A5D12553860800C340D1 /* Array+Description.swift */, + C3C2A5D12553860800C340D1 /* Array+Utilities.swift */, C33FDAA8255A57FF00E217F9 /* BuildConfiguration.swift */, B8F5F58225EC94A6003BF8D4 /* Collection+Subscripting.swift */, B8AE75A325A6C6A6001A84D2 /* Data+Trimming.swift */, @@ -4655,7 +4655,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */, + C3AABDDF2553ECF00042FF4C /* Array+Utilities.swift in Sources */, C32C5A47256DB8F0003C73A2 /* ECKeyPair+Hexadecimal.swift in Sources */, C3D9E41525676C320040E4F3 /* Storage.swift in Sources */, C32C5D83256DD5B6003C73A2 /* SSKKeychainStorage.swift in Sources */, diff --git a/Session/Utilities/ContactUtilities.swift b/Session/Utilities/ContactUtilities.swift index 2ecaa2641..a1ef5db88 100644 --- a/Session/Utilities/ContactUtilities.swift +++ b/Session/Utilities/ContactUtilities.swift @@ -5,6 +5,7 @@ enum ContactUtilities { // Collect all contacts var result: [String] = [] Storage.read { transaction in + // FIXME: If a user deletes a contact thread they will no longer appear in this list (ie. won't be an option for closed group conversations) TSContactThread.enumerateCollectionObjects(with: transaction) { object, _ in guard let thread: TSContactThread = object as? TSContactThread, diff --git a/SessionMessagingKit/Messages/Control Messages/ConfigurationMessage+Convenience.swift b/SessionMessagingKit/Messages/Control Messages/ConfigurationMessage+Convenience.swift index 6575575da..e4312c232 100644 --- a/SessionMessagingKit/Messages/Control Messages/ConfigurationMessage+Convenience.swift +++ b/SessionMessagingKit/Messages/Control Messages/ConfigurationMessage+Convenience.swift @@ -1,3 +1,4 @@ +import SessionUtilitiesKit extension ConfigurationMessage { @@ -10,8 +11,7 @@ extension ConfigurationMessage { let profileKey = user.profileEncryptionKey?.keyData var closedGroups: Set = [] var openGroups: Set = [] - var contacts: Set = [] - var contactCount = 0 + var contacts: Set = [] let populateDataClosure: (YapDatabaseReadTransaction) -> () = { transaction in TSGroupThread.enumerateCollectionObjects(with: transaction) { object, _ in @@ -48,47 +48,48 @@ extension ConfigurationMessage { } let currentUserPublicKey: String = getUserHexEncodedPublicKey() - var truncatedContacts = storage.getAllContacts(with: transaction) - if truncatedContacts.count > 200 { - truncatedContacts = Set(Array(truncatedContacts)[0..<200]) - } - - truncatedContacts.forEach { contact in - let publicKey = contact.sessionID - let threadID = TSContactThread.threadID(fromContactSessionID: publicKey) - - // Want to sync contacts for visible threads and blocked contacts between devices - guard - publicKey != currentUserPublicKey && ( - TSContactThread.fetch(uniqueId: threadID, transaction: transaction)?.shouldBeVisible == true || - SSKEnvironment.shared.blockingManager.isRecipientIdBlocked(publicKey) + contacts = storage.getAllContacts(with: transaction) + .filter { contact -> Bool in + let threadID = TSContactThread.threadID(fromContactSessionID: contact.sessionID) + + return ( + // Skip the current user + contact.sessionID != currentUserPublicKey && ( + + // Include already approved contacts + contact.isApproved || + contact.didApproveMe || + + // Sync blocked contacts + SSKEnvironment.shared.blockingManager.isRecipientIdBlocked(contact.sessionID) || + + // Contacts which have visible threads (sanity check - should be included as already approved) + TSContactThread.fetch(uniqueId: threadID, transaction: transaction)?.shouldBeVisible == true + ) ) - else { - return } - - // Can just default the 'hasX' values to true as they will be set to this - // when converting to proto anyway - let profilePictureURL = contact.profilePictureURL - let profileKey = contact.profileEncryptionKey?.keyData - let contact = ConfigurationMessage.Contact( - publicKey: publicKey, - displayName: (contact.name ?? publicKey), - profilePictureURL: profilePictureURL, - profileKey: profileKey, - hasIsApproved: true, - isApproved: contact.isApproved, - hasIsBlocked: true, - isBlocked: contact.isBlocked, - hasDidApproveMe: true, - didApproveMe: contact.didApproveMe - ) - - contacts.insert(contact) - contactCount += 1 + .map { contact -> ConfigurationMessage.Contact in + // Can just default the 'hasX' values to true as they will be set to this + // when converting to proto anyway + let profilePictureURL = contact.profilePictureURL + let profileKey = contact.profileEncryptionKey?.keyData + + return ConfigurationMessage.Contact( + publicKey: contact.sessionID, + displayName: (contact.name ?? contact.sessionID), + profilePictureURL: profilePictureURL, + profileKey: profileKey, + hasIsApproved: true, + isApproved: contact.isApproved, + hasIsBlocked: true, + isBlocked: contact.isBlocked, + hasDidApproveMe: true, + didApproveMe: contact.didApproveMe + ) + } + .asSet() } - } // If we are provided with a transaction then read the data based on the state of the database // from within the transaction rather than the state in disk diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index 5df789c88..021af0748 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -238,12 +238,6 @@ extension MessageReceiver { thread.remove(with: transaction) } } - else { - // Otherwise create and save the thread - let thread = TSContactThread.getOrCreateThread(withContactSessionID: sessionID, transaction: transaction) - thread.shouldBeVisible = true - thread.save(with: transaction) - } } // FIXME: 'OWSBlockingManager' manages it's own dbConnection and transactions so we have to dispatch this to prevent deadlocks diff --git a/SessionUtilitiesKit/General/Array+Description.swift b/SessionUtilitiesKit/General/Array+Utilities.swift similarity index 61% rename from SessionUtilitiesKit/General/Array+Description.swift rename to SessionUtilitiesKit/General/Array+Utilities.swift index 6ac99240a..0b4d8b7fd 100644 --- a/SessionUtilitiesKit/General/Array+Description.swift +++ b/SessionUtilitiesKit/General/Array+Utilities.swift @@ -5,3 +5,9 @@ public extension Array where Element : CustomStringConvertible { return "[ " + map { $0.description }.joined(separator: ", ") + " ]" } } + +public extension Array where Element: Hashable { + func asSet() -> Set { + return Set(self) + } +}