Scrolling to first item of the selected users list after adding a user

This commit is contained in:
Maxime NATUREL 2023-03-16 15:43:06 +01:00 committed by Florian Renaud
parent ddcde735fe
commit 9188408160
4 changed files with 30 additions and 1 deletions

View file

@ -16,6 +16,7 @@
package io.element.android.features.selectusers.api
import androidx.compose.foundation.lazy.LazyListState
import io.element.android.libraries.matrix.ui.model.MatrixUser
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableSet
@ -24,6 +25,7 @@ data class SelectUsersState(
val searchQuery: String,
val searchResults: ImmutableList<MatrixUser>,
val selectedUsers: ImmutableSet<MatrixUser>,
val selectedUsersListState: LazyListState,
val isSearchActive: Boolean,
val isMultiSelectionEnabled: Boolean,
val eventSink: (SelectUsersEvents) -> Unit,

View file

@ -16,6 +16,7 @@
package io.element.android.features.selectusers.api
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.ui.model.MatrixUser
@ -55,6 +56,10 @@ fun aSelectUsersState() = SelectUsersState(
searchQuery = "",
searchResults = persistentListOf(),
selectedUsers = persistentSetOf(),
selectedUsersListState = LazyListState(
firstVisibleItemIndex = 0,
firstVisibleItemScrollOffset = 0,
),
isMultiSelectionEnabled = false,
eventSink = {}
)

View file

@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
@ -80,6 +81,7 @@ fun SelectUsersView(
query = state.searchQuery,
results = state.searchResults,
selectedUsers = state.selectedUsers,
selectedUsersListState = state.selectedUsersListState,
active = state.isSearchActive,
isMultiSelectionEnabled = state.isMultiSelectionEnabled,
onActiveChanged = { eventSink.invoke(SelectUsersEvents.OnSearchActiveChanged(it)) },
@ -96,6 +98,7 @@ fun SelectUsersView(
if (state.isMultiSelectionEnabled && !state.isSearchActive && state.selectedUsers.isNotEmpty()) {
SelectedUsersList(
listState = state.selectedUsersListState,
modifier = Modifier.padding(16.dp),
selectedUsers = state.selectedUsers,
onUserRemoved = {
@ -113,6 +116,7 @@ fun SearchUserBar(
query: String,
results: ImmutableList<MatrixUser>,
selectedUsers: ImmutableSet<MatrixUser>,
selectedUsersListState: LazyListState,
active: Boolean,
isMultiSelectionEnabled: Boolean,
modifier: Modifier = Modifier,
@ -171,6 +175,7 @@ fun SearchUserBar(
content = {
if (isMultiSelectionEnabled && active && selectedUsers.isNotEmpty()) {
SelectedUsersList(
listState = selectedUsersListState,
modifier = Modifier.padding(16.dp),
selectedUsers = selectedUsers,
onUserRemoved = onUserDeselected,
@ -239,11 +244,13 @@ fun SearchSingleUserResultItem(
@Composable
fun SelectedUsersList(
listState: LazyListState,
selectedUsers: ImmutableSet<MatrixUser>,
modifier: Modifier = Modifier,
onUserRemoved: (MatrixUser) -> Unit = {},
) {
LazyRow(
state = listState,
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(24.dp),
) {

View file

@ -16,12 +16,15 @@
package io.element.android.features.selectusers.impl
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import io.element.android.features.selectusers.api.SelectUsersEvents
@ -36,15 +39,19 @@ import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean) : SelectUsersPresenter {
@Composable
override fun present(): SelectUsersState {
val localCoroutineScope = rememberCoroutineScope()
var isSearchActive by rememberSaveable { mutableStateOf(false) }
val selectedUsers: MutableState<ImmutableSet<MatrixUser>> = remember {
mutableStateOf(persistentSetOf())
}
val selectedUsersListState = rememberLazyListState()
var searchQuery by rememberSaveable { mutableStateOf("") }
val searchResults: MutableState<ImmutableList<MatrixUser>> = remember {
mutableStateOf(persistentListOf())
@ -54,7 +61,10 @@ class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean)
when (event) {
is SelectUsersEvents.OnSearchActiveChanged -> isSearchActive = event.active
is SelectUsersEvents.UpdateSearchQuery -> searchQuery = event.query
is SelectUsersEvents.AddToSelection -> selectedUsers.value = selectedUsers.value.plus(event.matrixUser).toImmutableSet()
is SelectUsersEvents.AddToSelection -> {
selectedUsers.value = selectedUsers.value.plus(event.matrixUser).toImmutableSet()
localCoroutineScope.scrollToFirstSelectedUser(selectedUsersListState)
}
is SelectUsersEvents.RemoveFromSelection -> selectedUsers.value = selectedUsers.value.minus(event.matrixUser).toImmutableSet()
}
}
@ -76,6 +86,7 @@ class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean)
searchQuery = searchQuery,
searchResults = searchResults.value,
selectedUsers = selectedUsers.value.reversed().toImmutableSet(),
selectedUsersListState = selectedUsersListState,
isSearchActive = isSearchActive,
isMultiSelectionEnabled = isMultiSelectionEnabled,
eventSink = ::handleEvents,
@ -92,4 +103,8 @@ class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean)
}
return results.toImmutableList()
}
private fun CoroutineScope.scrollToFirstSelectedUser(listState: LazyListState) = launch {
listState.scrollToItem(index = 0)
}
}