|
|
@ -22,6 +22,7 @@ import androidx.compose.animation.core.spring |
|
|
|
import androidx.compose.foundation.ExperimentalFoundationApi |
|
|
|
import androidx.compose.foundation.ExperimentalFoundationApi |
|
|
|
import androidx.compose.foundation.background |
|
|
|
import androidx.compose.foundation.background |
|
|
|
import androidx.compose.foundation.clickable |
|
|
|
import androidx.compose.foundation.clickable |
|
|
|
|
|
|
|
import androidx.compose.foundation.gestures.animateScrollBy |
|
|
|
import androidx.compose.foundation.layout.Arrangement |
|
|
|
import androidx.compose.foundation.layout.Arrangement |
|
|
|
import androidx.compose.foundation.layout.Box |
|
|
|
import androidx.compose.foundation.layout.Box |
|
|
|
import androidx.compose.foundation.layout.PaddingValues |
|
|
|
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.FilterChip |
|
|
|
import androidx.compose.material3.FilterChipDefaults |
|
|
|
import androidx.compose.material3.FilterChipDefaults |
|
|
|
import androidx.compose.runtime.Composable |
|
|
|
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.mutableStateOf |
|
|
|
import androidx.compose.runtime.remember |
|
|
|
import androidx.compose.runtime.remember |
|
|
|
|
|
|
|
import androidx.compose.runtime.setValue |
|
|
|
import androidx.compose.ui.Alignment |
|
|
|
import androidx.compose.ui.Alignment |
|
|
|
import androidx.compose.ui.Modifier |
|
|
|
import androidx.compose.ui.Modifier |
|
|
|
import androidx.compose.ui.draw.clip |
|
|
|
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.designsystem.theme.components.Text |
|
|
|
import io.element.android.libraries.testtags.TestTags |
|
|
|
import io.element.android.libraries.testtags.TestTags |
|
|
|
import io.element.android.libraries.testtags.testTag |
|
|
|
import io.element.android.libraries.testtags.testTag |
|
|
|
|
|
|
|
import timber.log.Timber |
|
|
|
|
|
|
|
|
|
|
|
@OptIn(ExperimentalFoundationApi::class) |
|
|
|
@OptIn(ExperimentalFoundationApi::class) |
|
|
|
@Composable |
|
|
|
@Composable |
|
|
@ -66,7 +72,31 @@ fun RoomListFiltersView( |
|
|
|
state.eventSink(RoomListFiltersEvents.ToggleFilter(filter)) |
|
|
|
state.eventSink(RoomListFiltersEvents.ToggleFilter(filter)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var scrollToStart by remember { mutableIntStateOf(0) } |
|
|
|
val lazyListState = rememberLazyListState() |
|
|
|
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<RoomListFilter>()) } |
|
|
|
val previousFilters = remember { mutableStateOf(listOf<RoomListFilter>()) } |
|
|
|
LazyRow( |
|
|
|
LazyRow( |
|
|
|
contentPadding = PaddingValues(start = 8.dp, end = 16.dp), |
|
|
|
contentPadding = PaddingValues(start = 8.dp, end = 16.dp), |
|
|
@ -84,6 +114,9 @@ fun RoomListFiltersView( |
|
|
|
onClick = { |
|
|
|
onClick = { |
|
|
|
previousFilters.value = state.selectedFilters() |
|
|
|
previousFilters.value = state.selectedFilters() |
|
|
|
onClearFiltersClick() |
|
|
|
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 = { |
|
|
|
onClick = { |
|
|
|
previousFilters.value = state.selectedFilters() |
|
|
|
previousFilters.value = state.selectedFilters() |
|
|
|
onToggleFilter(it) |
|
|
|
onToggleFilter(it) |
|
|
|
|
|
|
|
// When selecting a filter, we want to scroll to the start of the list |
|
|
|
|
|
|
|
if (filterWithSelection.isSelected.not()) { |
|
|
|
|
|
|
|
scrollToStart++ |
|
|
|
|
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|