From 41ba692a03ec1d324e2f3c3c91dc7eaa5247b1d1 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Thu, 25 May 2023 09:14:01 +1000 Subject: [PATCH] Fixed an issue where you couldn't search for hidden contacts --- .../SessionThreadViewModel.swift | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift b/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift index 8d83302f7..d7d134ad0 100644 --- a/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift +++ b/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift @@ -1256,12 +1256,18 @@ public extension SessionThreadViewModel { /// - Closed group member name /// - Open group name /// - "Note to self" text match + /// - Hidden contact nickname + /// - Hidden contact name + /// + /// **Note 2:** Since the "Hidden Contact" records don't have associated threads the `rowId` value in the + /// returned results will always be `-1` for those results static func contactsAndGroupsQuery(userPublicKey: String, pattern: FTS5Pattern, searchTerm: String) -> AdaptedFetchRequest> { let thread: TypedTableAlias = TypedTableAlias() let closedGroup: TypedTableAlias = TypedTableAlias() let groupMember: TypedTableAlias = TypedTableAlias() let openGroup: TypedTableAlias = TypedTableAlias() let profile: TypedTableAlias = TypedTableAlias() + let contact: TypedTableAlias = TypedTableAlias() let profileIdColumnLiteral: SQL = SQL(stringLiteral: Profile.Columns.id.name) let profileNicknameColumnLiteral: SQL = SQL(stringLiteral: Profile.Columns.nickname.name) let profileNameColumnLiteral: SQL = SQL(stringLiteral: Profile.Columns.name.name) @@ -1572,6 +1578,83 @@ public extension SessionThreadViewModel { WHERE \(SQL("\(thread[.id]) = \(userPublicKey)")) """ + // MARK: --Contacts without threads + let hiddenContactQuery: SQL = """ + SELECT + IFNULL(\(Column.rank), 100) AS \(Column.rank), + + -1 AS \(ViewModel.rowIdKey), + \(contact[.id]) AS \(ViewModel.threadIdKey), + \(SQL("\(SessionThread.Variant.contact)")) AS \(ViewModel.threadVariantKey), + 0 AS \(ViewModel.threadCreationDateTimestampKey), + \(groupMemberInfoLiteral).\(ViewModel.threadMemberNamesKey), + + false AS \(ViewModel.threadIsNoteToSelfKey), + -1 AS \(ViewModel.threadPinnedPriorityKey), + + \(ViewModel.contactProfileKey).*, + \(ViewModel.closedGroupProfileFrontKey).*, + \(ViewModel.closedGroupProfileBackKey).*, + \(ViewModel.closedGroupProfileBackFallbackKey).*, + \(closedGroup[.name]) AS \(ViewModel.closedGroupNameKey), + \(openGroup[.name]) AS \(ViewModel.openGroupNameKey), + \(openGroup[.imageData]) AS \(ViewModel.openGroupProfilePictureDataKey), + + \(SQL("\(userPublicKey)")) AS \(ViewModel.currentUserPublicKeyKey) + + FROM \(Contact.self) + """ + let hiddenContactQueryCommonJoins: SQL = """ + JOIN \(Profile.self) AS \(ViewModel.contactProfileKey) ON \(ViewModel.contactProfileKey).\(profileIdColumnLiteral) = \(contact[.id]) + LEFT JOIN \(SessionThread.self) ON \(thread[.id]) = \(contact[.id]) + LEFT JOIN \(Profile.self) AS \(ViewModel.closedGroupProfileFrontKey) ON false + LEFT JOIN \(Profile.self) AS \(ViewModel.closedGroupProfileBackKey) ON false + LEFT JOIN \(Profile.self) AS \(ViewModel.closedGroupProfileBackFallbackKey) ON false + LEFT JOIN \(ClosedGroup.self) ON false + LEFT JOIN \(OpenGroup.self) ON false + LEFT JOIN ( + SELECT + \(groupMember[.groupId]), + '' AS \(ViewModel.threadMemberNamesKey) + FROM \(GroupMember.self) + ) AS \(groupMemberInfoLiteral) ON false + + WHERE \(thread[.id]) IS NULL + GROUP BY \(contact[.id]) + """ + + // Hidden contact by nickname + sqlQuery += """ + + UNION ALL + + """ + sqlQuery += hiddenContactQuery + sqlQuery += """ + + JOIN \(profileFullTextSearch) ON ( + \(profileFullTextSearch).rowid = \(ViewModel.contactProfileKey).rowid AND + \(profileFullTextSearch).\(profileNicknameColumnLiteral) MATCH \(pattern) + ) + """ + sqlQuery += hiddenContactQueryCommonJoins + + // Hidden contact by name + sqlQuery += """ + + UNION ALL + + """ + sqlQuery += hiddenContactQuery + sqlQuery += """ + + JOIN \(profileFullTextSearch) ON ( + \(profileFullTextSearch).rowid = \(ViewModel.contactProfileKey).rowid AND + \(profileFullTextSearch).\(profileNameColumnLiteral) MATCH \(pattern) + ) + """ + sqlQuery += hiddenContactQueryCommonJoins + // Group everything by 'threadId' (the same thread can be found in multiple queries due // to seaerching both nickname and name), then order everything by 'rank' (relevance) // first, 'Note to Self' second (want it to appear at the bottom of threads unless it