Browse Source

Don't show own user in search results

Anywhere we do a global search (starting a DM, creating a room,
inviting a user to a room) should filter out the local user.
pull/797/head
Chris Smith 1 year ago
parent
commit
3e087c06da
  1. 20
      libraries/usersearch/impl/src/main/kotlin/io/element/android/libraries/usersearch/impl/MatrixUserRepository.kt
  2. 64
      libraries/usersearch/impl/src/test/kotlin/io/element/android/libraries/usersearch/impl/MatrixUserRepositoryTest.kt

20
libraries/usersearch/impl/src/main/kotlin/io/element/android/libraries/usersearch/impl/MatrixUserRepository.kt

@ -18,6 +18,7 @@ package io.element.android.libraries.usersearch.impl
import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.MatrixPatterns import io.element.android.libraries.matrix.api.core.MatrixPatterns
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
@ -31,13 +32,16 @@ import javax.inject.Inject
@ContributesBinding(SessionScope::class) @ContributesBinding(SessionScope::class)
class MatrixUserRepository @Inject constructor( class MatrixUserRepository @Inject constructor(
client: MatrixClient,
private val dataSource: UserListDataSource private val dataSource: UserListDataSource
) : UserRepository { ) : UserRepository {
private val sessionId = client.sessionId
override suspend fun search(query: String): Flow<List<UserSearchResult>> = flow { override suspend fun search(query: String): Flow<List<UserSearchResult>> = flow {
// Manually add a fake result with the matrixId, if any // Manually add a fake result with the matrixId, if provided and not the local user
val isUserId = MatrixPatterns.isUserId(query) val isAnotherUsersId = query != sessionId.value && MatrixPatterns.isUserId(query)
if (isUserId) { if (isAnotherUsersId) {
emit(listOf(UserSearchResult(MatrixUser(UserId(query))))) emit(listOf(UserSearchResult(MatrixUser(UserId(query)))))
} }
@ -45,10 +49,14 @@ class MatrixUserRepository @Inject constructor(
// Debounce // Debounce
delay(DEBOUNCE_TIME_MILLIS) delay(DEBOUNCE_TIME_MILLIS)
val results = dataSource.search(query, MAXIMUM_SEARCH_RESULTS).map { UserSearchResult(it) }.toMutableList() val results = dataSource
.search(query, MAXIMUM_SEARCH_RESULTS)
.filter { it.userId != sessionId }
.map { UserSearchResult(it) }
.toMutableList()
// If the query is a user ID and the result doesn't contain that user ID, query the profile information explicitly // If the query is another user's MXID and the result doesn't contain that user ID, query the profile information explicitly
if (isUserId && results.none { it.matrixUser.userId.value == query }) { if (isAnotherUsersId && results.none { it.matrixUser.userId.value == query }) {
results.add( results.add(
0, 0,
dataSource.getProfile(UserId(query)) dataSource.getProfile(UserId(query))

64
libraries/usersearch/impl/src/test/kotlin/io/element/android/libraries/usersearch/impl/MatrixUserRepositoryTest.kt

@ -18,22 +18,26 @@ package io.element.android.libraries.usersearch.impl
import app.cash.turbine.test import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.components.aMatrixUserList
import io.element.android.libraries.usersearch.api.UserSearchResult import io.element.android.libraries.usersearch.api.UserSearchResult
import io.element.android.libraries.usersearch.test.FakeUserListDataSource import io.element.android.libraries.usersearch.test.FakeUserListDataSource
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
private val SESSION_ID = SessionId("@current-user:example.com")
internal class MatrixUserRepositoryTest { internal class MatrixUserRepositoryTest {
@Test @Test
fun `search - emits nothing if the search query is too short`() = runTest { fun `search - emits nothing if the search query is too short`() = runTest {
val dataSource = FakeUserListDataSource() val dataSource = FakeUserListDataSource()
val repository = MatrixUserRepository(dataSource) val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search("x") val result = repository.search("x")
@ -45,7 +49,7 @@ internal class MatrixUserRepositoryTest {
@Test @Test
fun `search - returns empty list if no results are found`() = runTest { fun `search - returns empty list if no results are found`() = runTest {
val dataSource = FakeUserListDataSource() val dataSource = FakeUserListDataSource()
val repository = MatrixUserRepository(dataSource) val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search("some query") val result = repository.search("some query")
@ -59,7 +63,7 @@ internal class MatrixUserRepositoryTest {
fun `search - returns users if results are found`() = runTest { fun `search - returns users if results are found`() = runTest {
val dataSource = FakeUserListDataSource() val dataSource = FakeUserListDataSource()
dataSource.givenSearchResult(aMatrixUserList()) dataSource.givenSearchResult(aMatrixUserList())
val repository = MatrixUserRepository(dataSource) val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search("some query") val result = repository.search("some query")
@ -72,7 +76,7 @@ internal class MatrixUserRepositoryTest {
@Test @Test
fun `search - immediately returns placeholder if search is mxid`() = runTest { fun `search - immediately returns placeholder if search is mxid`() = runTest {
val dataSource = FakeUserListDataSource() val dataSource = FakeUserListDataSource()
val repository = MatrixUserRepository(dataSource) val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search(A_USER_ID.value) val result = repository.search(A_USER_ID.value)
@ -83,12 +87,40 @@ internal class MatrixUserRepositoryTest {
} }
} }
@Test
fun `search - doesn't return placeholder if search is the local user's mxid`() = runTest {
val dataSource = FakeUserListDataSource()
val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search(SESSION_ID.value)
result.test {
assertThat(awaitItem()).isEmpty()
awaitComplete()
}
}
@Test
fun `search - filters out results with the local user's mxid`() = runTest {
val searchResults = aMatrixUserList() + MatrixUser(userId = SESSION_ID, displayName = A_USER_NAME)
val dataSource = FakeUserListDataSource()
dataSource.givenSearchResult(searchResults)
val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search("some text")
result.test {
assertThat(awaitItem()).isEqualTo(aMatrixUserList().toUserSearchResults())
awaitComplete()
}
}
@Test @Test
fun `search - does not change results if they contain searched mxid`() = runTest { fun `search - does not change results if they contain searched mxid`() = runTest {
val searchResults = aMatrixUserListWithoutUserId(A_USER_ID) + MatrixUser(userId = A_USER_ID, displayName = A_USER_NAME) val searchResults = aMatrixUserListWithoutUserId(A_USER_ID) + MatrixUser(userId = A_USER_ID, displayName = A_USER_NAME)
val dataSource = FakeUserListDataSource() val dataSource = FakeUserListDataSource()
dataSource.givenSearchResult(searchResults) dataSource.givenSearchResult(searchResults)
val repository = MatrixUserRepository(dataSource) val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search(A_USER_ID.value) val result = repository.search(A_USER_ID.value)
@ -107,7 +139,7 @@ internal class MatrixUserRepositoryTest {
val dataSource = FakeUserListDataSource() val dataSource = FakeUserListDataSource()
dataSource.givenSearchResult(searchResults) dataSource.givenSearchResult(searchResults)
dataSource.givenUserProfile(userProfile) dataSource.givenUserProfile(userProfile)
val repository = MatrixUserRepository(dataSource) val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search(A_USER_ID.value) val result = repository.search(A_USER_ID.value)
@ -118,6 +150,24 @@ internal class MatrixUserRepositoryTest {
} }
} }
@Test
fun `search - doesn't add profile results if searched mxid is local user and not in results`() = runTest {
val userProfile = MatrixUser(userId = A_USER_ID, displayName = A_USER_NAME)
val searchResults = aMatrixUserListWithoutUserId(SESSION_ID)
val dataSource = FakeUserListDataSource()
dataSource.givenSearchResult(searchResults)
dataSource.givenUserProfile(userProfile)
val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search(SESSION_ID.value)
result.test {
assertThat(awaitItem()).isEqualTo(searchResults.toUserSearchResults())
awaitComplete()
}
}
@Test @Test
fun `search - returns unresolved user if profile can't be loaded`() = runTest { fun `search - returns unresolved user if profile can't be loaded`() = runTest {
val searchResults = aMatrixUserListWithoutUserId(A_USER_ID) val searchResults = aMatrixUserListWithoutUserId(A_USER_ID)
@ -125,7 +175,7 @@ internal class MatrixUserRepositoryTest {
val dataSource = FakeUserListDataSource() val dataSource = FakeUserListDataSource()
dataSource.givenSearchResult(searchResults) dataSource.givenSearchResult(searchResults)
dataSource.givenUserProfile(null) dataSource.givenUserProfile(null)
val repository = MatrixUserRepository(dataSource) val repository = MatrixUserRepository(FakeMatrixClient(SESSION_ID), dataSource)
val result = repository.search(A_USER_ID.value) val result = repository.search(A_USER_ID.value)

Loading…
Cancel
Save