design(home) : allow scrolling to top when clicking on already selected tab
This commit is contained in:
parent
dfb9bc5ab0
commit
21c21259cb
3 changed files with 81 additions and 33 deletions
|
|
@ -18,6 +18,7 @@ import androidx.compose.foundation.layout.calculateStartPadding
|
|||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
|
|
@ -25,7 +26,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
|
|
@ -40,9 +40,9 @@ import dev.chrisbanes.haze.materials.HazeMaterials
|
|||
import dev.chrisbanes.haze.rememberHazeState
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.features.home.impl.components.HomeTopBar
|
||||
import io.element.android.features.home.impl.components.RoomListContentView
|
||||
import io.element.android.features.home.impl.components.RoomListMenuAction
|
||||
import io.element.android.features.home.impl.components.HomeTopBar
|
||||
import io.element.android.features.home.impl.model.RoomListRoomSummary
|
||||
import io.element.android.features.home.impl.roomlist.RoomListContextMenu
|
||||
import io.element.android.features.home.impl.roomlist.RoomListDeclineInviteMenu
|
||||
|
|
@ -63,6 +63,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
|
|||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun HomeView(
|
||||
|
|
@ -155,6 +156,8 @@ private fun HomeScaffold(
|
|||
}
|
||||
|
||||
val hazeState = rememberHazeState()
|
||||
val roomsLazyListState = rememberLazyListState()
|
||||
val spacesLazyListState = rememberLazyListState()
|
||||
|
||||
Scaffold(
|
||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
|
|
@ -181,41 +184,39 @@ private fun HomeScaffold(
|
|||
style = HazeMaterials.thick(),
|
||||
)
|
||||
} else {
|
||||
Modifier
|
||||
.background(ElementTheme.colors.bgCanvasDefault)
|
||||
Modifier.background(ElementTheme.colors.bgCanvasDefault)
|
||||
}
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
if (state.showNavigationBar) {
|
||||
NavigationBar(
|
||||
containerColor = Color.Transparent,
|
||||
modifier = Modifier
|
||||
.hazeEffect(
|
||||
state = hazeState,
|
||||
style = HazeMaterials.thick(),
|
||||
)
|
||||
) {
|
||||
HomeNavigationBarItem.entries.forEach { item ->
|
||||
val isSelected = state.currentHomeNavigationBarItem == item
|
||||
NavigationBarItem(
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
state.eventSink(HomeEvents.SelectHomeNavigationBarItem(item))
|
||||
},
|
||||
icon = {
|
||||
NavigationBarIcon(
|
||||
imageVector = item.icon(isSelected),
|
||||
)
|
||||
},
|
||||
label = {
|
||||
NavigationBarText(
|
||||
text = stringResource(item.labelRes),
|
||||
)
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
HomeBottomBar(
|
||||
currentHomeNavigationBarItem = state.currentHomeNavigationBarItem,
|
||||
onItemClick = { item ->
|
||||
// scroll to top if selecting the same item
|
||||
if (item == state.currentHomeNavigationBarItem) {
|
||||
val lazyListStateTarget = when (item) {
|
||||
HomeNavigationBarItem.Chats -> roomsLazyListState
|
||||
HomeNavigationBarItem.Spaces -> spacesLazyListState
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
coroutineScope.launch {
|
||||
if (lazyListStateTarget.firstVisibleItemIndex > 10) {
|
||||
lazyListStateTarget.scrollToItem(10)
|
||||
}
|
||||
// Also reset the scrollBehavior height offset as it's not triggered by programmatic scrolls
|
||||
scrollBehavior.state.heightOffset = 0f
|
||||
lazyListStateTarget.animateScrollToItem(0)
|
||||
}
|
||||
} else {
|
||||
state.eventSink(HomeEvents.SelectHomeNavigationBarItem(item))
|
||||
}
|
||||
},
|
||||
modifier = Modifier.hazeEffect(
|
||||
state = hazeState,
|
||||
style = HazeMaterials.thick(),
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
content = { padding ->
|
||||
|
|
@ -224,6 +225,7 @@ private fun HomeScaffold(
|
|||
RoomListContentView(
|
||||
contentState = roomListState.contentState,
|
||||
filtersState = roomListState.filtersState,
|
||||
lazyListState = roomsLazyListState,
|
||||
hideInvitesAvatars = roomListState.hideInvitesAvatars,
|
||||
eventSink = roomListState.eventSink,
|
||||
onSetUpRecoveryClick = onSetUpRecoveryClick,
|
||||
|
|
@ -261,6 +263,7 @@ private fun HomeScaffold(
|
|||
.consumeWindowInsets(padding)
|
||||
.hazeSource(state = hazeState),
|
||||
state = state.homeSpacesState,
|
||||
lazyListState = spacesLazyListState,
|
||||
onSpaceClick = { spaceId ->
|
||||
onRoomClick(spaceId)
|
||||
}
|
||||
|
|
@ -284,6 +287,38 @@ private fun HomeScaffold(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HomeBottomBar(
|
||||
currentHomeNavigationBarItem: HomeNavigationBarItem,
|
||||
onItemClick: (HomeNavigationBarItem) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
NavigationBar(
|
||||
containerColor = Color.Transparent,
|
||||
modifier = modifier
|
||||
) {
|
||||
HomeNavigationBarItem.entries.forEach { item ->
|
||||
val isSelected = currentHomeNavigationBarItem == item
|
||||
NavigationBarItem(
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
onItemClick(item)
|
||||
},
|
||||
icon = {
|
||||
NavigationBarIcon(
|
||||
imageVector = item.icon(isSelected),
|
||||
)
|
||||
},
|
||||
label = {
|
||||
NavigationBarText(
|
||||
text = stringResource(item.labelRes),
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun RoomListRoomSummary.contentType() = displayType.ordinal
|
||||
|
||||
@PreviewsDayNight
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -60,6 +61,7 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
fun RoomListContentView(
|
||||
contentState: RoomListContentState,
|
||||
filtersState: RoomListFiltersState,
|
||||
lazyListState: LazyListState,
|
||||
hideInvitesAvatars: Boolean,
|
||||
eventSink: (RoomListEvents) -> Unit,
|
||||
onSetUpRecoveryClick: () -> Unit,
|
||||
|
|
@ -97,6 +99,7 @@ fun RoomListContentView(
|
|||
onSetUpRecoveryClick = onSetUpRecoveryClick,
|
||||
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
||||
onRoomClick = onRoomClick,
|
||||
lazyListState = lazyListState,
|
||||
contentPadding = contentPadding,
|
||||
)
|
||||
}
|
||||
|
|
@ -176,6 +179,7 @@ private fun RoomsView(
|
|||
onConfirmRecoveryKeyClick: () -> Unit,
|
||||
onRoomClick: (RoomListRoomSummary) -> Unit,
|
||||
contentPadding: PaddingValues,
|
||||
lazyListState: LazyListState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (state.summaries.isEmpty() && filtersState.hasAnyFilterSelected) {
|
||||
|
|
@ -192,6 +196,7 @@ private fun RoomsView(
|
|||
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
||||
onRoomClick = onRoomClick,
|
||||
contentPadding = contentPadding,
|
||||
lazyListState = lazyListState,
|
||||
modifier = modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
|
@ -206,9 +211,9 @@ private fun RoomsViewList(
|
|||
onConfirmRecoveryKeyClick: () -> Unit,
|
||||
onRoomClick: (RoomListRoomSummary) -> Unit,
|
||||
contentPadding: PaddingValues,
|
||||
lazyListState: LazyListState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
val visibleRange by remember {
|
||||
derivedStateOf {
|
||||
val layoutInfo = lazyListState.layoutInfo
|
||||
|
|
@ -343,6 +348,7 @@ internal fun RoomListContentViewPreview(@PreviewParameter(RoomListContentStatePr
|
|||
onConfirmRecoveryKeyClick = {},
|
||||
onRoomClick = {},
|
||||
onCreateRoomClick = {},
|
||||
lazyListState = rememberLazyListState(),
|
||||
contentPadding = PaddingValues(0.dp),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
package io.element.android.features.home.impl.spaces
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
|
|
@ -26,10 +28,14 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
@Composable
|
||||
fun HomeSpacesView(
|
||||
state: HomeSpacesState,
|
||||
lazyListState: LazyListState,
|
||||
onSpaceClick: (RoomId) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
LazyColumn(modifier) {
|
||||
LazyColumn(
|
||||
modifier = modifier,
|
||||
state = lazyListState
|
||||
) {
|
||||
val space = state.space
|
||||
when (space) {
|
||||
CurrentSpace.Root -> {
|
||||
|
|
@ -77,6 +83,7 @@ internal fun HomeSpacesViewPreview(
|
|||
) = ElementPreview {
|
||||
HomeSpacesView(
|
||||
state = state,
|
||||
lazyListState = rememberLazyListState(),
|
||||
onSpaceClick = {},
|
||||
modifier = Modifier,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue