mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
Merge pull request #7536 from hayaksi1/fix/3434-mention-suggestion-ranking
Rank the mention suggestions by how well they match what was typed
This commit is contained in:
+14
-1
@@ -115,9 +115,10 @@ class SuggestionsProcessor(
|
||||
.filterUpTo(MAX_BATCH_ITEMS) { member ->
|
||||
isJoinedMemberAndNotSelf(member) && memberMatchesQuery(member, query)
|
||||
}
|
||||
.sortedBy { member -> matchRank(member, query) }
|
||||
.map(ResolvedSuggestion::Member)
|
||||
|
||||
if ("room".contains(query) && canSendRoomMention) {
|
||||
if ("room".startsWith(query, ignoreCase = true) && canSendRoomMention) {
|
||||
listOf(ResolvedSuggestion.AtRoom) + matchingMembers
|
||||
} else {
|
||||
matchingMembers
|
||||
@@ -125,6 +126,18 @@ class SuggestionsProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Members whose display name starts with the query come first, then members whose user id
|
||||
* localpart starts with it, then the remaining matches on any other part of the name or id.
|
||||
*/
|
||||
private fun matchRank(member: RoomMember, query: String): Int {
|
||||
return when {
|
||||
member.displayName?.startsWith(query, ignoreCase = true) == true -> 0
|
||||
member.userId.extractedDisplayName.startsWith(query, ignoreCase = true) -> 1
|
||||
else -> 2
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
// We don't want to retrieve thousands of members
|
||||
private const val MAX_BATCH_ITEMS = 100
|
||||
|
||||
+42
@@ -383,6 +383,48 @@ class SuggestionsProcessorTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `processing Mention suggestion returns the members matching the start of the query first`() = runTest {
|
||||
val matchingOnAnyPart = aRoomMember(userId = UserId("@carol:server.org"), displayName = "Not Alice")
|
||||
val matchingOnUserIdStart = aRoomMember(userId = UserId("@alicia:server.org"), displayName = null)
|
||||
val matchingOnDisplayNameStart = aRoomMember(userId = UserId("@zoe:server.org"), displayName = "Alice")
|
||||
val result = suggestionsProcessor.process(
|
||||
suggestion = aMentionSuggestion("ali"),
|
||||
roomMembersState = RoomMembersState.Ready(
|
||||
persistentListOf(matchingOnAnyPart, matchingOnUserIdStart, matchingOnDisplayNameStart)
|
||||
),
|
||||
roomAliasSuggestions = emptyList(),
|
||||
currentUserId = A_USER_ID_2,
|
||||
canSendRoomMention = { false },
|
||||
isInThread = false,
|
||||
)
|
||||
assertThat(result).isEqualTo(
|
||||
listOf(
|
||||
ResolvedSuggestion.Member(matchingOnDisplayNameStart),
|
||||
ResolvedSuggestion.Member(matchingOnUserIdStart),
|
||||
ResolvedSuggestion.Member(matchingOnAnyPart),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `processing Mention suggestion returns room ignoring the case of the query`() = runTest {
|
||||
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "alice")
|
||||
val result = suggestionsProcessor.process(
|
||||
suggestion = aMentionSuggestion("RO"),
|
||||
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
|
||||
roomAliasSuggestions = emptyList(),
|
||||
currentUserId = A_USER_ID_2,
|
||||
canSendRoomMention = { true },
|
||||
isInThread = false,
|
||||
)
|
||||
assertThat(result).isEqualTo(
|
||||
listOf(
|
||||
ResolvedSuggestion.AtRoom,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `processing Mention suggestion with return matching display name but not room if not allowed`() = runTest {
|
||||
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro")
|
||||
|
||||
Reference in New Issue
Block a user