Let SearchBar/SearchField use TextFieldState
This commit is contained in:
@@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.text.input.TextFieldState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
@@ -40,14 +41,13 @@ import kotlinx.collections.immutable.ImmutableList
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SearchUserBar(
|
||||
query: String,
|
||||
state: SearchBarResultState<ImmutableList<UserSearchResult>>,
|
||||
queryState: TextFieldState,
|
||||
resultState: SearchBarResultState<ImmutableList<UserSearchResult>>,
|
||||
showLoader: Boolean,
|
||||
selectedUsers: ImmutableList<MatrixUser>,
|
||||
active: Boolean,
|
||||
isMultiSelectionEnable: Boolean,
|
||||
onActiveChange: (Boolean) -> Unit,
|
||||
onTextChange: (String) -> Unit,
|
||||
onUserSelect: (MatrixUser) -> Unit,
|
||||
onUserDeselect: (MatrixUser) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -57,8 +57,7 @@ fun SearchUserBar(
|
||||
val columnState = rememberLazyListState()
|
||||
|
||||
SearchBar(
|
||||
query = query,
|
||||
onQueryChange = onTextChange,
|
||||
queryState = queryState,
|
||||
active = active,
|
||||
onActiveChange = onActiveChange,
|
||||
modifier = modifier,
|
||||
@@ -98,7 +97,7 @@ fun SearchUserBar(
|
||||
AsyncLoading()
|
||||
}
|
||||
},
|
||||
resultState = state,
|
||||
resultState = resultState,
|
||||
resultHandler = { users ->
|
||||
LazyColumn(state = columnState) {
|
||||
if (isMultiSelectionEnable) {
|
||||
|
||||
@@ -46,15 +46,14 @@ fun UserListView(
|
||||
) {
|
||||
SearchUserBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
query = state.searchQuery,
|
||||
state = state.searchResults,
|
||||
queryState = state.searchQuery,
|
||||
resultState = state.searchResults,
|
||||
selectedUsers = state.selectedUsers,
|
||||
active = state.isSearchActive,
|
||||
showLoader = state.showSearchLoader,
|
||||
isMultiSelectionEnable = state.isMultiSelectionEnabled,
|
||||
showBackButton = showBackButton,
|
||||
onActiveChange = { state.eventSink(UserListEvents.OnSearchActiveChanged(it)) },
|
||||
onTextChange = { state.eventSink(UserListEvents.UpdateSearchQuery(it)) },
|
||||
onUserSelect = {
|
||||
state.eventSink(UserListEvents.AddToSelection(it))
|
||||
onSelectUser(it)
|
||||
|
||||
@@ -27,10 +27,10 @@ open class StartChatStateProvider : PreviewParameterProvider<StartChatState> {
|
||||
aCreateRoomRootState(
|
||||
startDmAction = AsyncAction.Loading,
|
||||
userListState = aMatrixUser().let {
|
||||
aUserListState().copy(
|
||||
aUserListState(
|
||||
searchQuery = it.userId.value,
|
||||
searchResults = SearchBarResultState.Results(persistentListOf(UserSearchResult(it, false))),
|
||||
selectedUsers = persistentListOf(it),
|
||||
selectedUsers = listOf(it),
|
||||
isSearchActive = true,
|
||||
)
|
||||
}
|
||||
@@ -38,10 +38,10 @@ open class StartChatStateProvider : PreviewParameterProvider<StartChatState> {
|
||||
aCreateRoomRootState(
|
||||
startDmAction = AsyncAction.Failure(RuntimeException("error")),
|
||||
userListState = aMatrixUser().let {
|
||||
aUserListState().copy(
|
||||
aUserListState(
|
||||
searchQuery = it.userId.value,
|
||||
searchResults = SearchBarResultState.Results(persistentListOf(UserSearchResult(it, false))),
|
||||
selectedUsers = persistentListOf(it),
|
||||
selectedUsers = listOf(it),
|
||||
isSearchActive = true,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package io.element.android.features.startchat.impl.userlist
|
||||
|
||||
import androidx.compose.foundation.text.input.rememberTextFieldState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@@ -64,12 +65,13 @@ class DefaultUserListPresenter(
|
||||
}
|
||||
var isSearchActive by rememberSaveable { mutableStateOf(false) }
|
||||
val selectedUsers by userListDataStore.selectedUsers.collectAsState(emptyList())
|
||||
var searchQuery by rememberSaveable { mutableStateOf("") }
|
||||
val queryState = rememberTextFieldState()
|
||||
var searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> by remember {
|
||||
mutableStateOf(SearchBarResultState.Initial())
|
||||
}
|
||||
var showSearchLoader by remember { mutableStateOf(false) }
|
||||
|
||||
val searchQuery = queryState.text.toString()
|
||||
LaunchedEffect(searchQuery) {
|
||||
searchResults = SearchBarResultState.Initial()
|
||||
showSearchLoader = false
|
||||
@@ -86,14 +88,13 @@ class DefaultUserListPresenter(
|
||||
fun handleEvent(event: UserListEvents) {
|
||||
when (event) {
|
||||
is UserListEvents.OnSearchActiveChanged -> isSearchActive = event.active
|
||||
is UserListEvents.UpdateSearchQuery -> searchQuery = event.query
|
||||
is UserListEvents.AddToSelection -> userListDataStore.selectUser(event.matrixUser)
|
||||
is UserListEvents.RemoveFromSelection -> userListDataStore.removeUserFromSelection(event.matrixUser)
|
||||
}
|
||||
}
|
||||
|
||||
return UserListState(
|
||||
searchQuery = searchQuery,
|
||||
searchQuery = queryState,
|
||||
searchResults = searchResults,
|
||||
selectedUsers = selectedUsers.toImmutableList(),
|
||||
isSearchActive = isSearchActive,
|
||||
|
||||
@@ -11,7 +11,6 @@ package io.element.android.features.startchat.impl.userlist
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
|
||||
sealed interface UserListEvents {
|
||||
data class UpdateSearchQuery(val query: String) : UserListEvents
|
||||
data class AddToSelection(val matrixUser: MatrixUser) : UserListEvents
|
||||
data class RemoveFromSelection(val matrixUser: MatrixUser) : UserListEvents
|
||||
data class OnSearchActiveChanged(val active: Boolean) : UserListEvents
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package io.element.android.features.startchat.impl.userlist
|
||||
|
||||
import androidx.compose.foundation.text.input.TextFieldState
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.api.room.recent.RecentDirectRoom
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
@@ -15,7 +16,7 @@ import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class UserListState(
|
||||
val searchQuery: String,
|
||||
val searchQuery: TextFieldState,
|
||||
val searchResults: SearchBarResultState<ImmutableList<UserSearchResult>>,
|
||||
val showSearchLoader: Boolean,
|
||||
val selectedUsers: ImmutableList<MatrixUser>,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package io.element.android.features.startchat.impl.userlist
|
||||
|
||||
import androidx.compose.foundation.text.input.TextFieldState
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
@@ -69,7 +70,7 @@ fun aUserListState(
|
||||
recentDirectRooms: List<RecentDirectRoom> = emptyList(),
|
||||
eventSink: (UserListEvents) -> Unit = {},
|
||||
) = UserListState(
|
||||
searchQuery = searchQuery,
|
||||
searchQuery = TextFieldState(initialText = searchQuery),
|
||||
isSearchActive = isSearchActive,
|
||||
searchResults = searchResults,
|
||||
selectedUsers = selectedUsers.toImmutableList(),
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package io.element.android.features.startchat.impl.userlist
|
||||
|
||||
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
@@ -41,7 +42,7 @@ class DefaultUserListPresenterTest {
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.searchQuery).isEmpty()
|
||||
assertThat(initialState.searchQuery.text.toString()).isEmpty()
|
||||
assertThat(initialState.isMultiSelectionEnabled).isFalse()
|
||||
assertThat(initialState.isSearchActive).isFalse()
|
||||
assertThat(initialState.selectedUsers).isEmpty()
|
||||
@@ -61,7 +62,7 @@ class DefaultUserListPresenterTest {
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.searchQuery).isEmpty()
|
||||
assertThat(initialState.searchQuery.text.toString()).isEmpty()
|
||||
assertThat(initialState.isMultiSelectionEnabled).isTrue()
|
||||
assertThat(initialState.isSearchActive).isFalse()
|
||||
assertThat(initialState.selectedUsers).isEmpty()
|
||||
@@ -86,14 +87,14 @@ class DefaultUserListPresenterTest {
|
||||
assertThat(awaitItem().isSearchActive).isTrue()
|
||||
|
||||
val matrixIdQuery = "@name:matrix.org"
|
||||
initialState.eventSink(UserListEvents.UpdateSearchQuery(matrixIdQuery))
|
||||
assertThat(awaitItem().searchQuery).isEqualTo(matrixIdQuery)
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd(matrixIdQuery)
|
||||
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(matrixIdQuery)
|
||||
assertThat(userRepository.providedQuery).isEqualTo(matrixIdQuery)
|
||||
skipItems(1)
|
||||
|
||||
val notMatrixIdQuery = "name"
|
||||
initialState.eventSink(UserListEvents.UpdateSearchQuery(notMatrixIdQuery))
|
||||
assertThat(awaitItem().searchQuery).isEqualTo(notMatrixIdQuery)
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd(notMatrixIdQuery)
|
||||
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(notMatrixIdQuery)
|
||||
assertThat(userRepository.providedQuery).isEqualTo(notMatrixIdQuery)
|
||||
skipItems(1)
|
||||
|
||||
@@ -117,7 +118,7 @@ class DefaultUserListPresenterTest {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
|
||||
initialState.eventSink(UserListEvents.UpdateSearchQuery("alice"))
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
|
||||
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
||||
assertThat(userRepository.providedQuery).isEqualTo("alice")
|
||||
skipItems(2)
|
||||
@@ -168,7 +169,7 @@ class DefaultUserListPresenterTest {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
|
||||
initialState.eventSink(UserListEvents.UpdateSearchQuery("alice"))
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
|
||||
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
||||
assertThat(userRepository.providedQuery).isEqualTo("alice")
|
||||
skipItems(2)
|
||||
|
||||
Reference in New Issue
Block a user