Scrolling to first item of the selected users list after adding a user
This commit is contained in:
parent
875b0f8f1f
commit
90276195a2
4 changed files with 30 additions and 1 deletions
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package io.element.android.features.selectusers.api
|
package io.element.android.features.selectusers.api
|
||||||
|
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
|
|
@ -24,6 +25,7 @@ data class SelectUsersState(
|
||||||
val searchQuery: String,
|
val searchQuery: String,
|
||||||
val searchResults: ImmutableList<MatrixUser>,
|
val searchResults: ImmutableList<MatrixUser>,
|
||||||
val selectedUsers: ImmutableSet<MatrixUser>,
|
val selectedUsers: ImmutableSet<MatrixUser>,
|
||||||
|
val selectedUsersListState: LazyListState,
|
||||||
val isSearchActive: Boolean,
|
val isSearchActive: Boolean,
|
||||||
val isMultiSelectionEnabled: Boolean,
|
val isMultiSelectionEnabled: Boolean,
|
||||||
val eventSink: (SelectUsersEvents) -> Unit,
|
val eventSink: (SelectUsersEvents) -> Unit,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package io.element.android.features.selectusers.api
|
package io.element.android.features.selectusers.api
|
||||||
|
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||||
|
|
@ -55,6 +56,10 @@ fun aSelectUsersState() = SelectUsersState(
|
||||||
searchQuery = "",
|
searchQuery = "",
|
||||||
searchResults = persistentListOf(),
|
searchResults = persistentListOf(),
|
||||||
selectedUsers = persistentSetOf(),
|
selectedUsers = persistentSetOf(),
|
||||||
|
selectedUsersListState = LazyListState(
|
||||||
|
firstVisibleItemIndex = 0,
|
||||||
|
firstVisibleItemScrollOffset = 0,
|
||||||
|
),
|
||||||
isMultiSelectionEnabled = false,
|
isMultiSelectionEnabled = false,
|
||||||
eventSink = {}
|
eventSink = {}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
|
@ -80,6 +81,7 @@ fun SelectUsersView(
|
||||||
query = state.searchQuery,
|
query = state.searchQuery,
|
||||||
results = state.searchResults,
|
results = state.searchResults,
|
||||||
selectedUsers = state.selectedUsers,
|
selectedUsers = state.selectedUsers,
|
||||||
|
selectedUsersListState = state.selectedUsersListState,
|
||||||
active = state.isSearchActive,
|
active = state.isSearchActive,
|
||||||
isMultiSelectionEnabled = state.isMultiSelectionEnabled,
|
isMultiSelectionEnabled = state.isMultiSelectionEnabled,
|
||||||
onActiveChanged = { eventSink.invoke(SelectUsersEvents.OnSearchActiveChanged(it)) },
|
onActiveChanged = { eventSink.invoke(SelectUsersEvents.OnSearchActiveChanged(it)) },
|
||||||
|
|
@ -96,6 +98,7 @@ fun SelectUsersView(
|
||||||
|
|
||||||
if (state.isMultiSelectionEnabled && !state.isSearchActive && state.selectedUsers.isNotEmpty()) {
|
if (state.isMultiSelectionEnabled && !state.isSearchActive && state.selectedUsers.isNotEmpty()) {
|
||||||
SelectedUsersList(
|
SelectedUsersList(
|
||||||
|
listState = state.selectedUsersListState,
|
||||||
modifier = Modifier.padding(16.dp),
|
modifier = Modifier.padding(16.dp),
|
||||||
selectedUsers = state.selectedUsers,
|
selectedUsers = state.selectedUsers,
|
||||||
onUserRemoved = {
|
onUserRemoved = {
|
||||||
|
|
@ -113,6 +116,7 @@ fun SearchUserBar(
|
||||||
query: String,
|
query: String,
|
||||||
results: ImmutableList<MatrixUser>,
|
results: ImmutableList<MatrixUser>,
|
||||||
selectedUsers: ImmutableSet<MatrixUser>,
|
selectedUsers: ImmutableSet<MatrixUser>,
|
||||||
|
selectedUsersListState: LazyListState,
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
isMultiSelectionEnabled: Boolean,
|
isMultiSelectionEnabled: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
|
@ -171,6 +175,7 @@ fun SearchUserBar(
|
||||||
content = {
|
content = {
|
||||||
if (isMultiSelectionEnabled && active && selectedUsers.isNotEmpty()) {
|
if (isMultiSelectionEnabled && active && selectedUsers.isNotEmpty()) {
|
||||||
SelectedUsersList(
|
SelectedUsersList(
|
||||||
|
listState = selectedUsersListState,
|
||||||
modifier = Modifier.padding(16.dp),
|
modifier = Modifier.padding(16.dp),
|
||||||
selectedUsers = selectedUsers,
|
selectedUsers = selectedUsers,
|
||||||
onUserRemoved = onUserDeselected,
|
onUserRemoved = onUserDeselected,
|
||||||
|
|
@ -239,11 +244,13 @@ fun SearchSingleUserResultItem(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SelectedUsersList(
|
fun SelectedUsersList(
|
||||||
|
listState: LazyListState,
|
||||||
selectedUsers: ImmutableSet<MatrixUser>,
|
selectedUsers: ImmutableSet<MatrixUser>,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onUserRemoved: (MatrixUser) -> Unit = {},
|
onUserRemoved: (MatrixUser) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
LazyRow(
|
LazyRow(
|
||||||
|
state = listState,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,15 @@
|
||||||
|
|
||||||
package io.element.android.features.selectusers.impl
|
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.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import io.element.android.features.selectusers.api.SelectUsersEvents
|
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.persistentSetOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean) : SelectUsersPresenter {
|
class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean) : SelectUsersPresenter {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): SelectUsersState {
|
override fun present(): SelectUsersState {
|
||||||
|
val localCoroutineScope = rememberCoroutineScope()
|
||||||
var isSearchActive by rememberSaveable { mutableStateOf(false) }
|
var isSearchActive by rememberSaveable { mutableStateOf(false) }
|
||||||
val selectedUsers: MutableState<ImmutableSet<MatrixUser>> = remember {
|
val selectedUsers: MutableState<ImmutableSet<MatrixUser>> = remember {
|
||||||
mutableStateOf(persistentSetOf())
|
mutableStateOf(persistentSetOf())
|
||||||
}
|
}
|
||||||
|
val selectedUsersListState = rememberLazyListState()
|
||||||
var searchQuery by rememberSaveable { mutableStateOf("") }
|
var searchQuery by rememberSaveable { mutableStateOf("") }
|
||||||
val searchResults: MutableState<ImmutableList<MatrixUser>> = remember {
|
val searchResults: MutableState<ImmutableList<MatrixUser>> = remember {
|
||||||
mutableStateOf(persistentListOf())
|
mutableStateOf(persistentListOf())
|
||||||
|
|
@ -54,7 +61,10 @@ class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean)
|
||||||
when (event) {
|
when (event) {
|
||||||
is SelectUsersEvents.OnSearchActiveChanged -> isSearchActive = event.active
|
is SelectUsersEvents.OnSearchActiveChanged -> isSearchActive = event.active
|
||||||
is SelectUsersEvents.UpdateSearchQuery -> searchQuery = event.query
|
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()
|
is SelectUsersEvents.RemoveFromSelection -> selectedUsers.value = selectedUsers.value.minus(event.matrixUser).toImmutableSet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -76,6 +86,7 @@ class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean)
|
||||||
searchQuery = searchQuery,
|
searchQuery = searchQuery,
|
||||||
searchResults = searchResults.value,
|
searchResults = searchResults.value,
|
||||||
selectedUsers = selectedUsers.value.reversed().toImmutableSet(),
|
selectedUsers = selectedUsers.value.reversed().toImmutableSet(),
|
||||||
|
selectedUsersListState = selectedUsersListState,
|
||||||
isSearchActive = isSearchActive,
|
isSearchActive = isSearchActive,
|
||||||
isMultiSelectionEnabled = isMultiSelectionEnabled,
|
isMultiSelectionEnabled = isMultiSelectionEnabled,
|
||||||
eventSink = ::handleEvents,
|
eventSink = ::handleEvents,
|
||||||
|
|
@ -92,4 +103,8 @@ class DefaultSelectUsersPresenter(private val isMultiSelectionEnabled: Boolean)
|
||||||
}
|
}
|
||||||
return results.toImmutableList()
|
return results.toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CoroutineScope.scrollToFirstSelectedUser(listState: LazyListState) = launch {
|
||||||
|
listState.scrollToItem(index = 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue