Rename UserSearchResults as UserSearchResultState
This commit is contained in:
parent
a790cca1b9
commit
dbfa9b0dc6
6 changed files with 49 additions and 27 deletions
|
|
@ -24,7 +24,7 @@ import io.element.android.libraries.designsystem.theme.components.SearchBarResul
|
||||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||||
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.api.UserSearchResults
|
import io.element.android.libraries.usersearch.api.UserSearchResultState
|
||||||
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
@ -137,11 +137,11 @@ class DefaultUserListPresenterTests {
|
||||||
skipItems(2)
|
skipItems(2)
|
||||||
|
|
||||||
// When the user repository emits a result, it's copied to the state
|
// When the user repository emits a result, it's copied to the state
|
||||||
val result = UserSearchResults(
|
val result = UserSearchResultState(
|
||||||
results = listOf(UserSearchResult(aMatrixUser())),
|
results = listOf(UserSearchResult(aMatrixUser())),
|
||||||
isFetchingSearchResults = false,
|
isFetchingSearchResults = false,
|
||||||
)
|
)
|
||||||
userRepository.emitResult(result)
|
userRepository.emitState(result)
|
||||||
awaitItem().also { state ->
|
awaitItem().also { state ->
|
||||||
assertThat(state.searchResults).isEqualTo(
|
assertThat(state.searchResults).isEqualTo(
|
||||||
SearchBarResultState.Results(
|
SearchBarResultState.Results(
|
||||||
|
|
@ -151,11 +151,11 @@ class DefaultUserListPresenterTests {
|
||||||
assertThat(state.isFetchingSearchResults).isFalse()
|
assertThat(state.isFetchingSearchResults).isFalse()
|
||||||
}
|
}
|
||||||
// When the user repository emits another result, it replaces the previous value
|
// When the user repository emits another result, it replaces the previous value
|
||||||
val newResult = UserSearchResults(
|
val newResult = UserSearchResultState(
|
||||||
results = aMatrixUserList().map { UserSearchResult(it) },
|
results = aMatrixUserList().map { UserSearchResult(it) },
|
||||||
isFetchingSearchResults = false,
|
isFetchingSearchResults = false,
|
||||||
)
|
)
|
||||||
userRepository.emitResult(newResult)
|
userRepository.emitState(newResult)
|
||||||
awaitItem().also { state ->
|
awaitItem().also { state ->
|
||||||
assertThat(state.searchResults).isEqualTo(
|
assertThat(state.searchResults).isEqualTo(
|
||||||
SearchBarResultState.Results(
|
SearchBarResultState.Results(
|
||||||
|
|
@ -189,7 +189,7 @@ class DefaultUserListPresenterTests {
|
||||||
skipItems(2)
|
skipItems(2)
|
||||||
|
|
||||||
// When the results list is empty, the state is set to NoResults
|
// When the results list is empty, the state is set to NoResults
|
||||||
userRepository.emitResult(UserSearchResults(results = emptyList(), isFetchingSearchResults = false))
|
userRepository.emitState(UserSearchResultState(results = emptyList(), isFetchingSearchResults = false))
|
||||||
assertThat(awaitItem().searchResults).isInstanceOf(SearchBarResultState.NoResultsFound::class.java)
|
assertThat(awaitItem().searchResults).isInstanceOf(SearchBarResultState.NoResultsFound::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,14 @@ import io.element.android.libraries.designsystem.theme.components.SearchBarResul
|
||||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||||
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
|
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||||
|
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_ID_2
|
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||||
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.api.UserSearchResults
|
import io.element.android.libraries.usersearch.api.UserSearchResultState
|
||||||
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||||
|
|
@ -109,12 +110,12 @@ internal class RoomInviteMembersPresenterTest {
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink(RoomInviteMembersEvents.UpdateSearchQuery("some query"))
|
initialState.eventSink(RoomInviteMembersEvents.UpdateSearchQuery("some query"))
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitResult(UserSearchResults(results = emptyList(), isFetchingSearchResults = true))
|
repository.emitState(UserSearchResultState(results = emptyList(), isFetchingSearchResults = true))
|
||||||
consumeItemsUntilPredicate { it.isFetchingSearchResults }.last().also { state ->
|
consumeItemsUntilPredicate { it.isFetchingSearchResults }.last().also { state ->
|
||||||
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Empty::class.java)
|
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Empty::class.java)
|
||||||
assertThat(state.isFetchingSearchResults).isTrue()
|
assertThat(state.isFetchingSearchResults).isTrue()
|
||||||
}
|
}
|
||||||
repository.emitResult(UserSearchResults(results = emptyList(), isFetchingSearchResults = false))
|
repository.emitState(results = emptyList(), isFetchingSearchResults = false)
|
||||||
consumeItemsUntilPredicate { !it.isFetchingSearchResults }.last().also { state ->
|
consumeItemsUntilPredicate { !it.isFetchingSearchResults }.last().also { state ->
|
||||||
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.NoResultsFound::class.java)
|
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.NoResultsFound::class.java)
|
||||||
assertThat(state.isFetchingSearchResults).isFalse()
|
assertThat(state.isFetchingSearchResults).isFalse()
|
||||||
|
|
@ -140,7 +141,7 @@ internal class RoomInviteMembersPresenterTest {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitResult(UserSearchResults(results =aMatrixUserList().map { UserSearchResult(it) }))
|
repository.emitStateWithUsers(users = aMatrixUserList())
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
||||||
val resultState = awaitItem()
|
val resultState = awaitItem()
|
||||||
|
|
@ -192,7 +193,7 @@ internal class RoomInviteMembersPresenterTest {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitResult(UserSearchResults(results =aMatrixUserList().map { UserSearchResult(it) }))
|
repository.emitStateWithUsers(users = aMatrixUserList())
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
||||||
val resultState = awaitItem()
|
val resultState = awaitItem()
|
||||||
|
|
@ -253,7 +254,7 @@ internal class RoomInviteMembersPresenterTest {
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
|
|
||||||
val unresolvedUser = UserSearchResult(aMatrixUser(id = A_USER_ID.value), isUnresolved = true)
|
val unresolvedUser = UserSearchResult(aMatrixUser(id = A_USER_ID.value), isUnresolved = true)
|
||||||
repository.emitResult(UserSearchResults(results = listOf(unresolvedUser) + aMatrixUserList().map { UserSearchResult(it) }))
|
repository.emitState(listOf(unresolvedUser) + aMatrixUserList().map { UserSearchResult(it) })
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
||||||
val resultState = awaitItem()
|
val resultState = awaitItem()
|
||||||
|
|
@ -321,7 +322,7 @@ internal class RoomInviteMembersPresenterTest {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitResult(UserSearchResults(results = (aMatrixUserList() + selectedUser).map { UserSearchResult(it) }))
|
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
|
||||||
skipItems(2)
|
skipItems(2)
|
||||||
|
|
||||||
val resultState = awaitItem()
|
val resultState = awaitItem()
|
||||||
|
|
@ -361,7 +362,7 @@ internal class RoomInviteMembersPresenterTest {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitResult(UserSearchResults(results =(aMatrixUserList() + selectedUser).map { UserSearchResult(it) }))
|
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
|
||||||
skipItems(2)
|
skipItems(2)
|
||||||
|
|
||||||
// And then a user is toggled
|
// And then a user is toggled
|
||||||
|
|
@ -384,6 +385,27 @@ internal class RoomInviteMembersPresenterTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun FakeUserRepository.emitStateWithUsers(
|
||||||
|
users: List<MatrixUser>,
|
||||||
|
isFetchingSearchResults: Boolean = false
|
||||||
|
) {
|
||||||
|
emitState(
|
||||||
|
results = users.map { UserSearchResult(it) },
|
||||||
|
isFetchingSearchResults = isFetchingSearchResults,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun FakeUserRepository.emitState(
|
||||||
|
results: List<UserSearchResult>,
|
||||||
|
isFetchingSearchResults: Boolean = false
|
||||||
|
) {
|
||||||
|
val state = UserSearchResultState(
|
||||||
|
results = results,
|
||||||
|
isFetchingSearchResults = isFetchingSearchResults
|
||||||
|
)
|
||||||
|
emitState(state)
|
||||||
|
}
|
||||||
|
|
||||||
private fun TestScope.createDataSource(
|
private fun TestScope.createDataSource(
|
||||||
matrixRoom: MatrixRoom = aMatrixRoom().apply {
|
matrixRoom: MatrixRoom = aMatrixRoom().apply {
|
||||||
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
|
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,5 @@ import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface UserRepository {
|
interface UserRepository {
|
||||||
|
|
||||||
fun search(query: String): Flow<UserSearchResults>
|
fun search(query: String): Flow<UserSearchResultState>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ data class UserSearchResult(
|
||||||
val isUnresolved: Boolean = false,
|
val isUnresolved: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class UserSearchResults(
|
data class UserSearchResultState(
|
||||||
val results: List<UserSearchResult>,
|
val results: List<UserSearchResult>,
|
||||||
val isFetchingSearchResults: Boolean = false,
|
val isFetchingSearchResults: Boolean,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import io.element.android.libraries.usersearch.api.UserListDataSource
|
import io.element.android.libraries.usersearch.api.UserListDataSource
|
||||||
import io.element.android.libraries.usersearch.api.UserRepository
|
import io.element.android.libraries.usersearch.api.UserRepository
|
||||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||||
import io.element.android.libraries.usersearch.api.UserSearchResults
|
import io.element.android.libraries.usersearch.api.UserSearchResultState
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
|
|
@ -37,7 +37,7 @@ class MatrixUserRepository @Inject constructor(
|
||||||
private val dataSource: UserListDataSource
|
private val dataSource: UserListDataSource
|
||||||
) : UserRepository {
|
) : UserRepository {
|
||||||
|
|
||||||
override fun search(query: String): Flow<UserSearchResults> = flow {
|
override fun search(query: String): Flow<UserSearchResultState> = flow {
|
||||||
val shouldQueryProfile = MatrixPatterns.isUserId(query) && !client.isMe(UserId(query))
|
val shouldQueryProfile = MatrixPatterns.isUserId(query) && !client.isMe(UserId(query))
|
||||||
val shouldFetchSearchResults = query.length >= MINIMUM_SEARCH_LENGTH
|
val shouldFetchSearchResults = query.length >= MINIMUM_SEARCH_LENGTH
|
||||||
// If the search term is a MXID that's not ours, we'll show a 'fake' result for that user, then update it when we get search results.
|
// If the search term is a MXID that's not ours, we'll show a 'fake' result for that user, then update it when we get search results.
|
||||||
|
|
@ -47,7 +47,7 @@ class MatrixUserRepository @Inject constructor(
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
if (shouldQueryProfile || shouldFetchSearchResults) {
|
if (shouldQueryProfile || shouldFetchSearchResults) {
|
||||||
emit(UserSearchResults(isFetchingSearchResults = shouldFetchSearchResults, results = listOfNotNull(fakeSearchResult)))
|
emit(UserSearchResultState(isFetchingSearchResults = shouldFetchSearchResults, results = listOfNotNull(fakeSearchResult)))
|
||||||
}
|
}
|
||||||
if (shouldFetchSearchResults) {
|
if (shouldFetchSearchResults) {
|
||||||
val results = fetchSearchResults(query, shouldQueryProfile)
|
val results = fetchSearchResults(query, shouldQueryProfile)
|
||||||
|
|
@ -55,7 +55,7 @@ class MatrixUserRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun fetchSearchResults(query: String, shouldQueryProfile: Boolean): UserSearchResults {
|
private suspend fun fetchSearchResults(query: String, shouldQueryProfile: Boolean): UserSearchResultState {
|
||||||
// Debounce
|
// Debounce
|
||||||
delay(DEBOUNCE_TIME_MILLIS)
|
delay(DEBOUNCE_TIME_MILLIS)
|
||||||
val results = dataSource
|
val results = dataSource
|
||||||
|
|
@ -73,7 +73,7 @@ class MatrixUserRepository @Inject constructor(
|
||||||
?: UserSearchResult(MatrixUser(UserId(query)), isUnresolved = true))
|
?: UserSearchResult(MatrixUser(UserId(query)), isUnresolved = true))
|
||||||
}
|
}
|
||||||
|
|
||||||
return UserSearchResults(results = results, isFetchingSearchResults = false)
|
return UserSearchResultState(results = results, isFetchingSearchResults = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
package io.element.android.libraries.usersearch.test
|
package io.element.android.libraries.usersearch.test
|
||||||
|
|
||||||
import io.element.android.libraries.usersearch.api.UserRepository
|
import io.element.android.libraries.usersearch.api.UserRepository
|
||||||
import io.element.android.libraries.usersearch.api.UserSearchResults
|
import io.element.android.libraries.usersearch.api.UserSearchResultState
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
|
||||||
|
|
@ -26,15 +26,15 @@ class FakeUserRepository : UserRepository {
|
||||||
var providedQuery: String? = null
|
var providedQuery: String? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private val flow = MutableSharedFlow<UserSearchResults>()
|
private val flow = MutableSharedFlow<UserSearchResultState>()
|
||||||
|
|
||||||
override fun search(query: String): Flow<UserSearchResults> {
|
override fun search(query: String): Flow<UserSearchResultState> {
|
||||||
providedQuery = query
|
providedQuery = query
|
||||||
return flow
|
return flow
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun emitResult(result: UserSearchResults) {
|
suspend fun emitState(state: UserSearchResultState) {
|
||||||
flow.emit(result)
|
flow.emit(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue