diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index fa87ee856..f724e0516 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -679,7 +679,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 */; }; @@ -1757,7 +1757,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 = ""; }; @@ -2359,7 +2359,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 */, @@ -4671,6 +4671,7 @@ files = ( C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */, 7B1D74AC27BDE7510030B423 /* Promise+Timeout.swift in Sources */, + C3AABDDF2553ECF00042FF4C /* Array+Utilities.swift in Sources */, C32C5A47256DB8F0003C73A2 /* ECKeyPair+Hexadecimal.swift in Sources */, C3D9E41525676C320040E4F3 /* Storage.swift in Sources */, 7B1D74B027C365960030B423 /* Timer+MainThread.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/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 09c87aecb..203ed4c2f 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 @@ -296,7 +290,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]) 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) + } +}