From 6589fef196f8fddc129bf8fba1194b60faa80afc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 24 Jun 2024 15:36:23 +0200 Subject: [PATCH] Improve room filtering behavior. --- .../impl/filters/RoomListFiltersView.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt index 545884c875..31fed9f18d 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt @@ -22,6 +22,7 @@ import androidx.compose.animation.core.spring import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.animateScrollBy import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues @@ -34,8 +35,12 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChipDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -51,6 +56,7 @@ import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag +import timber.log.Timber @OptIn(ExperimentalFoundationApi::class) @Composable @@ -66,7 +72,31 @@ fun RoomListFiltersView( state.eventSink(RoomListFiltersEvents.ToggleFilter(filter)) } + var scrollToStart by remember { mutableIntStateOf(0) } val lazyListState = rememberLazyListState() + LaunchedEffect(scrollToStart) { + // Scroll until the first item start to be displayed + // Since all items have different size, there is no way to compute the amount of + // pixel to scroll to go directly to the start of the row. + // But IRL it should only happen for one item. + while (lazyListState.firstVisibleItemIndex > 0) { + lazyListState.animateScrollBy( + value = -(lazyListState.firstVisibleItemScrollOffset + 1f), + animationSpec = spring( + stiffness = Spring.StiffnessMediumLow, + ) + ) + } + // Then scroll to the start of the list, a bit faster, to fully reveal the first + // item, which can be the close button to reset filter, or the first item + // if the user has scroll a bit before clicking on the close button. + lazyListState.animateScrollBy( + value = -lazyListState.firstVisibleItemScrollOffset.toFloat(), + animationSpec = spring( + stiffness = Spring.StiffnessMedium, + ) + ) + } val previousFilters = remember { mutableStateOf(listOf()) } LazyRow( contentPadding = PaddingValues(start = 8.dp, end = 16.dp), @@ -84,6 +114,9 @@ fun RoomListFiltersView( onClick = { previousFilters.value = state.selectedFilters() onClearFiltersClick() + // When clearing filter, we want to ensure that the list + // of filters is scrolled to the start. + scrollToStart++ } ) } @@ -100,6 +133,10 @@ fun RoomListFiltersView( onClick = { previousFilters.value = state.selectedFilters() onToggleFilter(it) + // When selecting a filter, we want to scroll to the start of the list + if (filterWithSelection.isSelected.not()) { + scrollToStart++ + } }, ) }