diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index b85901fc2b..34d0332c0f 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -29,7 +29,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.shape.CircleShape @@ -77,7 +76,6 @@ fun ConfigureRoomView( modifier: Modifier = Modifier, onBackPressed: () -> Unit = {}, ) { - val selectedUsersListState = rememberLazyListState() val context = LocalContext.current Scaffold( modifier = modifier, @@ -106,7 +104,6 @@ fun ConfigureRoomView( onTopicChanged = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) }, ) SelectedUsersList( - listState = selectedUsersListState, contentPadding = PaddingValues(horizontal = 24.dp), selectedUsers = state.config.invites, onUserRemoved = { state.eventSink(ConfigureRoomEvents.RemoveFromSelection(it)) }, diff --git a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/UserListState.kt b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/UserListState.kt index 80de1e991f..dfbfddbcf5 100644 --- a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/UserListState.kt +++ b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/UserListState.kt @@ -16,7 +16,6 @@ package io.element.android.features.userlist.api -import androidx.compose.foundation.lazy.LazyListState import io.element.android.libraries.matrix.ui.model.MatrixUser import kotlinx.collections.immutable.ImmutableList @@ -24,7 +23,6 @@ data class UserListState( val searchQuery: String, val searchResults: ImmutableList, val selectedUsers: ImmutableList, - val selectedUsersListState: LazyListState, val isSearchActive: Boolean, val selectionMode: SelectionMode, val eventSink: (UserListEvents) -> Unit, diff --git a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/UserListStateProvider.kt b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/UserListStateProvider.kt index 8d3bf68f0d..7ea0ba0827 100644 --- a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/UserListStateProvider.kt +++ b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/UserListStateProvider.kt @@ -16,7 +16,6 @@ package io.element.android.features.userlist.api -import androidx.compose.foundation.lazy.LazyListState import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.ui.components.aMatrixUserList import kotlinx.collections.immutable.persistentListOf @@ -55,10 +54,6 @@ fun aUserListState() = UserListState( searchQuery = "", searchResults = persistentListOf(), selectedUsers = persistentListOf(), - selectedUsersListState = LazyListState( - firstVisibleItemIndex = 0, - firstVisibleItemScrollOffset = 0, - ), selectionMode = SelectionMode.Single, eventSink = {} ) diff --git a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/SearchUserBar.kt b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/SearchUserBar.kt index 83aad4151b..baee8c5b2a 100644 --- a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/SearchUserBar.kt +++ b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/SearchUserBar.kt @@ -20,7 +20,6 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close @@ -49,7 +48,6 @@ fun SearchUserBar( query: String, results: ImmutableList, selectedUsers: ImmutableList, - selectedUsersListState: LazyListState, active: Boolean, isMultiSelectionEnabled: Boolean, modifier: Modifier = Modifier, @@ -108,9 +106,9 @@ fun SearchUserBar( content = { if (isMultiSelectionEnabled && active && selectedUsers.isNotEmpty()) { SelectedUsersList( - listState = selectedUsersListState, contentPadding = PaddingValues(16.dp), selectedUsers = selectedUsers, + autoScroll = true, onUserRemoved = onUserDeselected, ) } diff --git a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/SelectedUsersList.kt b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/SelectedUsersList.kt index 4c2a0b10d3..491fb7827f 100644 --- a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/SelectedUsersList.kt +++ b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/SelectedUsersList.kt @@ -18,10 +18,15 @@ package io.element.android.features.userlist.api.components import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -29,18 +34,29 @@ import io.element.android.features.userlist.api.aListOfSelectedUsers import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.matrix.ui.model.MatrixUser -import kotlinx.collections.immutable.ImmutableList @Composable fun SelectedUsersList( - listState: LazyListState, - selectedUsers: ImmutableList, + selectedUsers: List, modifier: Modifier = Modifier, + autoScroll: Boolean = false, contentPadding: PaddingValues = PaddingValues(0.dp), onUserRemoved: (MatrixUser) -> Unit = {}, ) { + val lazyListState = rememberLazyListState() + if (autoScroll) { + var currentSize by rememberSaveable { mutableStateOf(selectedUsers.size) } + LaunchedEffect(selectedUsers.size) { + val isItemAdded = selectedUsers.size > currentSize + if (isItemAdded) { + lazyListState.animateScrollToItem(selectedUsers.lastIndex) + } + currentSize = selectedUsers.size + } + } + LazyRow( - state = listState, + state = lazyListState, modifier = modifier, contentPadding = contentPadding, horizontalArrangement = Arrangement.spacedBy(24.dp), @@ -65,7 +81,6 @@ internal fun SelectedUsersListDarkPreview() = ElementPreviewDark { ContentToPrev @Composable private fun ContentToPreview() { SelectedUsersList( - listState = LazyListState(), selectedUsers = aListOfSelectedUsers(), ) } diff --git a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/UserListView.kt b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/UserListView.kt index 42b96ab3a2..6532dea2b6 100644 --- a/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/UserListView.kt +++ b/features/userlist/api/src/main/kotlin/io/element/android/features/userlist/api/components/UserListView.kt @@ -46,7 +46,6 @@ fun UserListView( query = state.searchQuery, results = state.searchResults, selectedUsers = state.selectedUsers, - selectedUsersListState = state.selectedUsersListState, active = state.isSearchActive, isMultiSelectionEnabled = state.isMultiSelectionEnabled, onActiveChanged = { state.eventSink(UserListEvents.OnSearchActiveChanged(it)) }, @@ -63,9 +62,9 @@ fun UserListView( if (state.isMultiSelectionEnabled && !state.isSearchActive && state.selectedUsers.isNotEmpty()) { SelectedUsersList( - listState = state.selectedUsersListState, contentPadding = PaddingValues(16.dp), selectedUsers = state.selectedUsers, + autoScroll = true, onUserRemoved = { state.eventSink(UserListEvents.RemoveFromSelection(it)) onUserDeselected(it) diff --git a/features/userlist/impl/src/main/kotlin/io/element/android/features/userlist/impl/DefaultUserListPresenter.kt b/features/userlist/impl/src/main/kotlin/io/element/android/features/userlist/impl/DefaultUserListPresenter.kt index 8e1829f4a7..965bf40983 100644 --- a/features/userlist/impl/src/main/kotlin/io/element/android/features/userlist/impl/DefaultUserListPresenter.kt +++ b/features/userlist/impl/src/main/kotlin/io/element/android/features/userlist/impl/DefaultUserListPresenter.kt @@ -16,8 +16,6 @@ package io.element.android.features.userlist.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 @@ -25,7 +23,6 @@ import androidx.compose.runtime.collectAsState 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 com.squareup.anvil.annotations.ContributesBinding @@ -45,8 +42,6 @@ import io.element.android.libraries.matrix.ui.model.MatrixUser import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch class DefaultUserListPresenter @AssistedInject constructor( @Assisted val args: UserListPresenterArgs, @@ -66,10 +61,8 @@ class DefaultUserListPresenter @AssistedInject constructor( @Composable override fun present(): UserListState { - val localCoroutineScope = rememberCoroutineScope() var isSearchActive by rememberSaveable { mutableStateOf(false) } val selectedUsers = userListDataStore.selectedUsers().collectAsState(emptyList()) - val selectedUsersListState = rememberLazyListState() var searchQuery by rememberSaveable { mutableStateOf("") } val searchResults: MutableState> = remember { mutableStateOf(persistentListOf()) @@ -83,7 +76,6 @@ class DefaultUserListPresenter @AssistedInject constructor( if (event.matrixUser !in selectedUsers.value) { userListDataStore.selectUser(event.matrixUser) } - localCoroutineScope.scrollToFirstSelectedUser(selectedUsersListState) } is UserListEvents.RemoveFromSelection -> userListDataStore.removeUserFromSelection(event.matrixUser) } @@ -105,8 +97,7 @@ class DefaultUserListPresenter @AssistedInject constructor( return UserListState( searchQuery = searchQuery, searchResults = searchResults.value, - selectedUsers = selectedUsers.value.reversed().toImmutableList(), - selectedUsersListState = selectedUsersListState, + selectedUsers = selectedUsers.value.toImmutableList(), isSearchActive = isSearchActive, selectionMode = args.selectionMode, eventSink = ::handleEvents, @@ -123,8 +114,4 @@ class DefaultUserListPresenter @AssistedInject constructor( } return results.toImmutableList() } - - private fun CoroutineScope.scrollToFirstSelectedUser(listState: LazyListState) = launch { - listState.scrollToItem(index = 0) - } }