Use the right insets in the home screen UI (#7271)

* Use the right insets in the home screen UI

That's `WindowInsets.statusBar` for the `Scaffold` component, then `WindowInsets.navigationBar` for the `LazyColum.contentPadding`

* Apply it to other screens with long lists of items too

* Apply the insets to `PreferencePage` too

* Apply inset changes to other screens with scrollable content

* Add helper insets/padding values based on review suggestions.

* Use the newly added insets/padding values in several scaffold and scrollable columns

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa
2026-07-27 18:17:14 +02:00
committed by GitHub
parent 0442fbd307
commit 77edfec61a
31 changed files with 208 additions and 73 deletions
@@ -19,6 +19,7 @@ import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.plus
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
@@ -65,6 +66,8 @@ import io.element.android.libraries.designsystem.theme.components.HorizontalFloa
import io.element.android.libraries.designsystem.theme.components.HorizontalFloatingToolbarSeparator import io.element.android.libraries.designsystem.theme.components.HorizontalFloatingToolbarSeparator
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
@@ -234,7 +237,15 @@ private fun HomeScaffold(
) )
}, },
floatingActionButtonPosition = FabPosition.Center, floatingActionButtonPosition = FabPosition.Center,
contentWindowInsets = scaffoldScrollableContentInsets,
content = { padding -> content = { padding ->
val outerPadding = PaddingValues(
start = padding.calculateStartPadding(LocalLayoutDirection.current),
end = padding.calculateEndPadding(LocalLayoutDirection.current),
// Remove these two lines once https://issuetracker.google.com/issues/436432313 has been fixed
bottom = padding.calculateBottomPadding(),
top = padding.calculateTopPadding()
)
val contentPadding = PaddingValues( val contentPadding = PaddingValues(
bottom = 96.dp, bottom = 96.dp,
) )
@@ -251,18 +262,10 @@ private fun HomeScaffold(
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
onRoomClick = ::onRoomClick, onRoomClick = ::onRoomClick,
onCreateRoomClick = onStartChatClick, onCreateRoomClick = onStartChatClick,
contentPadding = contentPadding, contentPadding = lazyColumnContentPadding + contentPadding,
modifier = Modifier modifier = Modifier
.padding( .padding(outerPadding)
PaddingValues( .consumeWindowInsets(outerPadding)
start = padding.calculateStartPadding(LocalLayoutDirection.current),
end = padding.calculateEndPadding(LocalLayoutDirection.current),
// Remove these two lines once https://issuetracker.google.com/issues/436432313 has been fixed
bottom = padding.calculateBottomPadding(),
top = padding.calculateTopPadding()
)
)
.consumeWindowInsets(padding)
.hazeSource(state = hazeState) .hazeSource(state = hazeState)
) )
SpaceFiltersView(roomListState.spaceFiltersState) SpaceFiltersView(roomListState.spaceFiltersState)
@@ -271,8 +274,8 @@ private fun HomeScaffold(
HomeSpacesView( HomeSpacesView(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(padding) .padding(outerPadding)
.consumeWindowInsets(padding) .consumeWindowInsets(outerPadding)
.hazeSource(state = hazeState), .hazeSource(state = hazeState),
contentPadding = contentPadding, contentPadding = contentPadding,
state = state.homeSpacesState, state = state.homeSpacesState,
@@ -13,9 +13,15 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
@@ -153,7 +159,8 @@ private fun RoomListSearchContent(
} }
}, },
) )
} },
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom),
) { padding -> ) { padding ->
Column( Column(
modifier = Modifier modifier = Modifier
@@ -167,6 +174,7 @@ private fun RoomListSearchContent(
LazyColumn( LazyColumn(
state = lazyListState, state = lazyListState,
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
) { ) {
items( items(
items = state.results, items = state.results,
@@ -15,9 +15,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
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.items import androidx.compose.foundation.lazy.items
@@ -45,6 +43,8 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.SearchField import io.element.android.libraries.designsystem.theme.components.SearchField
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@@ -75,9 +75,7 @@ fun SpaceFiltersView(
} }
if (sheetState.isVisible || isSelecting) { if (sheetState.isVisible || isSelecting) {
ModalBottomSheet( ModalBottomSheet(
modifier = modifier modifier = modifier,
.systemBarsPadding()
.navigationBarsPadding(),
sheetState = sheetState, sheetState = sheetState,
onDismissRequest = { onDismissRequest = {
if (state is SpaceFiltersState.Selecting) { if (state is SpaceFiltersState.Selecting) {
@@ -85,6 +83,7 @@ fun SpaceFiltersView(
} }
}, },
scrollable = false, scrollable = false,
contentWindowInsets = { scaffoldScrollableContentInsets },
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
@@ -113,7 +112,7 @@ private fun SpaceFiltersBottomSheetContent(
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Column( Column(
modifier = modifier.padding(vertical = 16.dp) modifier = modifier.padding(top = 16.dp)
) { ) {
Text( Text(
text = stringResource(R.string.screen_roomlist_your_spaces), text = stringResource(R.string.screen_roomlist_your_spaces),
@@ -131,7 +130,9 @@ private fun SpaceFiltersBottomSheetContent(
placeholder = stringResource(CommonStrings.action_search), placeholder = stringResource(CommonStrings.action_search),
) )
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
LazyColumn { LazyColumn(
contentPadding = lazyColumnContentPadding,
) {
items(filters) { filter -> items(filters) { filter ->
SpaceFilterItem( SpaceFilterItem(
filter = filter, filter = filter,
@@ -23,6 +23,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.plus
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
@@ -73,6 +74,8 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@@ -94,7 +97,8 @@ fun KnockRequestsListView(
.padding(padding) .padding(padding)
.consumeWindowInsets(padding), .consumeWindowInsets(padding),
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) )
} }
@@ -132,7 +136,7 @@ private fun KnockRequestsListContent(
onAcceptClick = ::onAcceptClick, onAcceptClick = ::onAcceptClick,
onDeclineClick = ::onDeclineClick, onDeclineClick = ::onDeclineClick,
onBanClick = ::onBanClick, onBanClick = ::onBanClick,
contentPadding = PaddingValues(bottom = bottomPaddingInPixels.toDp()), contentPadding = lazyColumnContentPadding + PaddingValues(bottom = bottomPaddingInPixels.toDp()),
) )
} }
} }
@@ -9,7 +9,7 @@
package io.element.android.features.licenses.impl.details package io.element.android.features.licenses.impl.details
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.plus
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@@ -25,6 +25,8 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItem
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@@ -41,9 +43,10 @@ fun DependenciesDetailsView(
navigationIcon = { BackButton(onClick = onBack) }, navigationIcon = { BackButton(onClick = onBack) },
) )
}, },
contentWindowInsets = scaffoldScrollableContentInsets,
) { contentPadding -> ) { contentPadding ->
LazyColumn( LazyColumn(
modifier = Modifier.padding(contentPadding), contentPadding = contentPadding + lazyColumnContentPadding,
) { ) {
val licenses = licenseItem.licenses.orEmpty() + val licenses = licenseItem.licenses.orEmpty() +
licenseItem.unknownLicenses.orEmpty() licenseItem.unknownLicenses.orEmpty()
@@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.plus
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@@ -34,6 +35,8 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextField import io.element.android.libraries.designsystem.theme.components.TextField
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -52,10 +55,11 @@ fun DependencyLicensesListView(
navigationIcon = { BackButton(onClick = onBackClick) }, navigationIcon = { BackButton(onClick = onBackClick) },
) )
}, },
contentWindowInsets = scaffoldScrollableContentInsets,
) { contentPadding -> ) { contentPadding ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(contentPadding) .padding(contentPadding + lazyColumnContentPadding)
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
) { ) {
if (state.licenses.isSuccess()) { if (state.licenses.isSuccess()) {
@@ -72,7 +76,9 @@ fun DependencyLicensesListView(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) )
} }
LazyColumn { LazyColumn(
contentPadding = lazyColumnContentPadding,
) {
when (state.licenses) { when (state.licenses) {
is AsyncData.Failure -> item { is AsyncData.Failure -> item {
Text( Text(
@@ -39,6 +39,8 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
/** /**
* https://www.figma.com/file/o9p34zmiuEpZRyvZXJZAYL/FTUE?type=design&node-id=604-60817 * https://www.figma.com/file/o9p34zmiuEpZRyvZXJZAYL/FTUE?type=design&node-id=604-60817
@@ -59,7 +61,8 @@ fun ChangeAccountProviderView(
title = {}, title = {},
navigationIcon = { BackButton(onClick = onBackClick) } navigationIcon = { BackButton(onClick = onBackClick) }
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) { padding -> ) { padding ->
Box( Box(
modifier = Modifier modifier = Modifier
@@ -71,6 +74,7 @@ fun ChangeAccountProviderView(
Column( Column(
modifier = Modifier modifier = Modifier
.verticalScroll(state = rememberScrollState()) .verticalScroll(state = rememberScrollState())
.padding(lazyColumnContentPadding)
) { ) {
IconTitleSubtitleMolecule( IconTitleSubtitleMolecule(
modifier = Modifier.padding(top = 16.dp, bottom = 32.dp, start = 16.dp, end = 16.dp), modifier = Modifier.padding(top = 16.dp, bottom = 32.dp, start = 16.dp, end = 16.dp),
@@ -44,6 +44,8 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@@ -71,7 +73,8 @@ fun ChooseAccountProviderView(
title = {}, title = {},
navigationIcon = { BackButton(onClick = onBackClick) } navigationIcon = { BackButton(onClick = onBackClick) }
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) { padding -> ) { padding ->
Box( Box(
modifier = Modifier modifier = Modifier
@@ -84,6 +87,7 @@ fun ChooseAccountProviderView(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.verticalScroll(state = rememberScrollState()) .verticalScroll(state = rememberScrollState())
.padding(lazyColumnContentPadding)
) { ) {
IconTitleSubtitleMolecule( IconTitleSubtitleMolecule(
modifier = Modifier.padding(top = 16.dp, bottom = 32.dp, start = 16.dp, end = 16.dp), modifier = Modifier.padding(top = 16.dp, bottom = 32.dp, start = 16.dp, end = 16.dp),
@@ -19,7 +19,6 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@@ -27,7 +26,6 @@ import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@@ -112,6 +110,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.HideKeyboardWhenDisposed import io.element.android.libraries.designsystem.utils.HideKeyboardWhenDisposed
import io.element.android.libraries.designsystem.utils.KeepScreenOn import io.element.android.libraries.designsystem.utils.KeepScreenOn
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
@@ -226,7 +225,7 @@ fun MessagesView(
}, },
content = { content = {
Scaffold( Scaffold(
contentWindowInsets = WindowInsets.statusBars, contentWindowInsets = scaffoldScrollableContentInsets,
topBar = { topBar = {
if (state.timelineState.timelineMode is Timeline.Mode.Thread) { if (state.timelineState.timelineMode is Timeline.Mode.Thread) {
ThreadTopBar( ThreadTopBar(
@@ -10,9 +10,13 @@ package io.element.android.features.messages.impl.pinned.list
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.plus
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
@@ -47,6 +51,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@@ -90,7 +95,8 @@ fun PinnedMessagesListView(
.padding(padding) .padding(padding)
.consumeWindowInsets(padding), .consumeWindowInsets(padding),
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) )
} }
@@ -206,11 +212,12 @@ private fun PinnedMessagesListLoaded(
onEmojiReactionClick = { _, _ -> }, onEmojiReactionClick = { _, _ -> },
onVerifiedUserSendFailureClick = {} onVerifiedUserSendFailureClick = {}
) )
LazyColumn( LazyColumn(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
state = rememberLazyListState(), state = rememberLazyListState(),
reverseLayout = true, reverseLayout = true,
contentPadding = PaddingValues(vertical = 8.dp), contentPadding = WindowInsets.navigationBars.asPaddingValues() + PaddingValues(vertical = 8.dp),
) { ) {
items( items(
items = state.timelineItems, items = state.timelineItems,
@@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.plus
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
@@ -54,6 +55,8 @@ import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
@@ -129,14 +132,15 @@ fun ThreadsListView(
}, },
navigationIcon = { navigationIcon = {
BackButton(onBackClick) BackButton(onBackClick)
} },
windowInsets = scaffoldScrollableContentInsets,
) )
} }
) { padding -> ) { padding ->
val lazyListState = rememberLazyListState() val lazyListState = rememberLazyListState()
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentPadding = padding, contentPadding = padding + lazyColumnContentPadding,
state = lazyListState, state = lazyListState,
) { ) {
itemsIndexed(state.threads, key = { _, row -> row.item.threadId }) { index, row -> itemsIndexed(state.threads, key = { _, row -> row.item.threadId }) { index, row ->
@@ -19,16 +19,15 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.statusBars
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
private val INDICATOR_VERTICAL_PADDING = 6.dp private val INDICATOR_VERTICAL_PADDING = 6.dp
@@ -47,7 +46,7 @@ fun ConnectivityIndicatorContainer(
// Needed to get valid UI previews // Needed to get valid UI previews
24.dp 24.dp
} else { } else {
WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + INDICATOR_VERTICAL_PADDING scaffoldScrollableContentInsets.asPaddingValues().calculateTopPadding() + INDICATOR_VERTICAL_PADDING
} }
val target = if (isIndicatorVisible.targetState) statusBarTopPadding else 0.dp val target = if (isIndicatorVisible.targetState) statusBarTopPadding else 0.dp
val topWindowInset by animateDpAsState( val topWindowInset by animateDpAsState(
@@ -78,6 +78,8 @@ import io.element.android.libraries.designsystem.theme.components.ListItemStyle
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomAlias
@@ -135,12 +137,14 @@ fun RoomDetailsView(
) )
}, },
snackbarHost = { SnackbarHost(snackbarHostState) }, snackbarHost = { SnackbarHost(snackbarHostState) },
contentWindowInsets = scaffoldScrollableContentInsets,
) { padding -> ) { padding ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(padding) .padding(padding)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.consumeWindowInsets(padding) .consumeWindowInsets(padding)
.padding(lazyColumnContentPadding)
) { ) {
leaveRoomView() leaveRoomView()
@@ -50,6 +50,8 @@ import io.element.android.libraries.designsystem.theme.components.SegmentedButto
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
@@ -78,7 +80,8 @@ fun RoomMemberListView(
onBackClick = navigator::exitRoomMemberList, onBackClick = navigator::exitRoomMemberList,
onInviteClick = navigator::openInviteMembers, onInviteClick = navigator::openInviteMembers,
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) { padding -> ) { padding ->
Column( Column(
modifier = Modifier modifier = Modifier
@@ -115,7 +118,11 @@ private fun RoomMemberList(
onSelectedSectionChange: (SelectedSection) -> Unit, onSelectedSectionChange: (SelectedSection) -> Unit,
onSelectUser: (RoomMember) -> Unit, onSelectUser: (RoomMember) -> Unit,
) { ) {
LazyColumn(modifier = Modifier.fillMaxWidth(), state = rememberLazyListState()) { LazyColumn(
modifier = Modifier.fillMaxWidth(),
state = rememberLazyListState(),
contentPadding = lazyColumnContentPadding,
) {
stickyHeader { stickyHeader {
Column { Column {
AnimatedVisibility(visible = showBannedSection) { AnimatedVisibility(visible = showBannedSection) {
@@ -52,6 +52,8 @@ import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@@ -76,7 +78,8 @@ fun RoomDirectoryView(
.padding(padding) .padding(padding)
.consumeWindowInsets(padding) .consumeWindowInsets(padding)
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) )
} }
@@ -127,7 +130,10 @@ private fun RoomDirectoryRoomList(
onReachedLoadMore: () -> Unit, onReachedLoadMore: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
LazyColumn(modifier = modifier) { LazyColumn(
modifier = modifier,
contentPadding = lazyColumnContentPadding,
) {
items(roomDescriptions) { roomDescription -> items(roomDescriptions) { roomDescription ->
RoomDirectoryRoomRow( RoomDirectoryRoomRow(
roomDescription = roomDescription, roomDescription = roomDescription,
@@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@@ -228,7 +227,7 @@ private fun RoomMemberActionsBottomSheet(
enabledValues = setOf(SheetValue.Hidden, SheetValue.Expanded), enabledValues = setOf(SheetValue.Hidden, SheetValue.Expanded),
) )
ModalBottomSheet( ModalBottomSheet(
modifier = Modifier.systemBarsPadding(), modifier = Modifier.statusBarsPadding(),
sheetState = bottomSheetState, sheetState = bottomSheetState,
onDismissRequest = { onDismissRequest = {
coroutineScope.launch { coroutineScope.launch {
@@ -54,6 +54,8 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@@ -78,14 +80,16 @@ fun SecurityAndPrivacyView(
state.eventSink(SecurityAndPrivacyEvent.Save) state.eventSink(SecurityAndPrivacyEvent.Save)
}, },
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) { padding -> ) { padding ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(padding) .padding(padding)
.imePadding() .imePadding()
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.consumeWindowInsets(padding), .consumeWindowInsets(padding)
.padding(lazyColumnContentPadding),
verticalArrangement = Arrangement.spacedBy(32.dp), verticalArrangement = Arrangement.spacedBy(32.dp),
) { ) {
if (state.showRoomAccessSection) { if (state.showRoomAccessSection) {
@@ -47,6 +47,8 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.OnVisibleRangeChangeEffect import io.element.android.libraries.designsystem.utils.OnVisibleRangeChangeEffect
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.ui.components.SelectedRoom import io.element.android.libraries.matrix.ui.components.SelectedRoom
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getAvatarData
@@ -101,7 +103,8 @@ fun AddRoomToSpaceView(
) )
} }
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) { paddingValues -> ) { paddingValues ->
Column( Column(
Modifier Modifier
@@ -130,7 +133,9 @@ fun AddRoomToSpaceView(
OnVisibleRangeChangeEffect(lazyListState) { visibleRange -> OnVisibleRangeChangeEffect(lazyListState) { visibleRange ->
state.eventSink(AddRoomToSpaceEvent.UpdateSearchVisibleRange(visibleRange)) state.eventSink(AddRoomToSpaceEvent.UpdateSearchVisibleRange(visibleRange))
} }
LazyColumn { LazyColumn(
contentPadding = lazyColumnContentPadding,
) {
items(rooms, key = { it.roomId }) { roomInfo -> items(rooms, key = { it.roomId }) { roomInfo ->
RoomListItem( RoomListItem(
roomInfo = roomInfo, roomInfo = roomInfo,
@@ -82,6 +82,8 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.api.spaces.SpaceRoom
@@ -157,6 +159,7 @@ fun SpaceView(
} }
} }
}, },
contentWindowInsets = scaffoldScrollableContentInsets,
content = { padding -> content = { padding ->
Box( Box(
modifier = Modifier.padding(padding) modifier = Modifier.padding(padding)
@@ -251,7 +254,10 @@ private fun SpaceViewContent(
onAddRoomClick: () -> Unit, onAddRoomClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
LazyColumn(modifier.fillMaxSize()) { LazyColumn(
modifier = modifier.fillMaxSize(),
contentPadding = lazyColumnContentPadding,
) {
val spaceInfo = state.spaceInfo val spaceInfo = state.spaceInfo
item(key = "space_header") { item(key = "space_header") {
AnimatedVisibility( AnimatedVisibility(
@@ -43,6 +43,8 @@ import io.element.android.libraries.designsystem.theme.components.ListItemStyle
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@@ -62,11 +64,13 @@ fun SpaceSettingsView(
topBar = { topBar = {
SpaceSettingsTopBar(onBackClick = onBackClick) SpaceSettingsTopBar(onBackClick = onBackClick)
}, },
contentWindowInsets = scaffoldScrollableContentInsets,
) { padding -> ) { padding ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(padding) .padding(padding)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.padding(lazyColumnContentPadding)
) { ) {
SpaceInfoSection( SpaceInfoSection(
roomId = state.roomId, roomId = state.roomId,
@@ -10,7 +10,10 @@ package io.element.android.features.startchat.impl.components
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -76,7 +79,9 @@ fun UserListView(
) )
} }
if (!state.isSearchActive && state.recentDirectRooms.isNotEmpty()) { if (!state.isSearchActive && state.recentDirectRooms.isNotEmpty()) {
LazyColumn { LazyColumn(
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
) {
item { item {
ListSectionHeader( ListSectionHeader(
title = stringResource(id = CommonStrings.common_suggestions), title = stringResource(id = CommonStrings.common_suggestions),
@@ -45,6 +45,7 @@ import io.element.android.libraries.designsystem.theme.components.ListSectionHea
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.ui.components.CreateDmConfirmationBottomSheet import io.element.android.libraries.matrix.ui.components.CreateDmConfirmationBottomSheet
import io.element.android.libraries.matrix.ui.components.MatrixUserRow import io.element.android.libraries.matrix.ui.components.MatrixUserRow
@@ -71,7 +72,8 @@ fun StartChatView(
if (!state.userListState.isSearchActive) { if (!state.userListState.isSearchActive) {
CreateRoomRootViewTopBar(onCloseClick = onCloseClick) CreateRoomRootViewTopBar(onCloseClick = onCloseClick)
} }
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) { paddingValues -> ) { paddingValues ->
Column( Column(
modifier = Modifier modifier = Modifier
@@ -10,13 +10,11 @@ package io.element.android.libraries.designsystem.components.preferences
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.plus
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@@ -34,6 +32,8 @@ import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
@Composable @Composable
fun PreferencePage( fun PreferencePage(
@@ -46,9 +46,8 @@ fun PreferencePage(
Scaffold( Scaffold(
modifier = modifier modifier = modifier
.fillMaxSize() .fillMaxSize()
.systemBarsPadding()
.imePadding(), .imePadding(),
contentWindowInsets = WindowInsets.statusBars, contentWindowInsets = scaffoldScrollableContentInsets,
topBar = { topBar = {
PreferenceTopAppBar( PreferenceTopAppBar(
title = title, title = title,
@@ -56,12 +55,12 @@ fun PreferencePage(
) )
}, },
snackbarHost = snackbarHost, snackbarHost = snackbarHost,
content = { content = { contentPadding ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(it)
.consumeWindowInsets(it)
.verticalScroll(state = rememberScrollState()) .verticalScroll(state = rememberScrollState())
.padding(contentPadding + lazyColumnContentPadding)
.consumeWindowInsets(contentPadding + lazyColumnContentPadding)
) { ) {
content() content()
} }
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.designsystem.utils
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import io.element.android.libraries.designsystem.theme.components.Scaffold
/**
* Content insets meant to be used for [Column] or [LazyColumn] components that are used as the main content of a screen,
* to avoid overlapping with navigation bars, IME or cut-out display parts, but ignoring the status bar.
*
* Counterpart of [scaffoldScrollableContentInsets] for [Column] or [LazyColumn] components.
*/
val lazyColumnContentPadding @Composable
get() = WindowInsets.safeDrawing
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
.asPaddingValues()
/**
* Content insets meant to be used for [Scaffold] components that contain some content that is scrollable like [Column] or [LazyColumn],
* and this content should handle its own content padding. The insets will only apply the top padding to avoid overlapping with the status bar,
* while ignoring navigation bars, IME or cut-out display parts.
*
* Counterpart of [lazyColumnContentPadding] for [Scaffold] components.
*/
val scaffoldScrollableContentInsets @Composable
get() = WindowInsets.safeDrawing
.only(WindowInsetsSides.Top)
@@ -14,11 +14,14 @@ import androidx.compose.foundation.clickable
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.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
@@ -67,6 +70,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.SegmentedButton import io.element.android.libraries.designsystem.theme.components.SegmentedButton
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.Timeline
@@ -125,6 +129,7 @@ fun MediaGalleryView(
}, },
) )
}, },
contentWindowInsets = scaffoldScrollableContentInsets,
) { paddingValues -> ) { paddingValues ->
Column( Column(
modifier = Modifier modifier = Modifier
@@ -320,6 +325,7 @@ private fun MediaGalleryFilesList(
val presenterFactories = LocalMediaItemPresenterFactories.current val presenterFactories = LocalMediaItemPresenterFactories.current
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
) { ) {
items( items(
items = files, items = files,
@@ -396,6 +402,7 @@ private fun MediaGalleryImageGrid(
columns = GridCells.Adaptive(80.dp), columns = GridCells.Adaptive(80.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalArrangement = Arrangement.spacedBy(4.dp), verticalArrangement = Arrangement.spacedBy(4.dp),
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
) { ) {
items( items(
items = imagesAndVideos, items = imagesAndVideos,
@@ -53,6 +53,8 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.OnVisibleRangeChangeEffect import io.element.android.libraries.designsystem.utils.OnVisibleRangeChangeEffect
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.ui.components.SelectedRoom import io.element.android.libraries.matrix.ui.components.SelectedRoom
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
@@ -133,7 +135,8 @@ fun RoomSelectView(
) )
} }
) )
} },
contentWindowInsets = scaffoldScrollableContentInsets,
) { paddingValues -> ) { paddingValues ->
Column( Column(
Modifier Modifier
@@ -149,7 +152,10 @@ fun RoomSelectView(
resultState = state.resultState, resultState = state.resultState,
showBackButton = false, showBackButton = false,
) { summaries -> ) { summaries ->
LazyColumn(state = lazyListState) { LazyColumn(
state = lazyListState,
contentPadding = lazyColumnContentPadding,
) {
item { item {
SelectedRoomsHelper( SelectedRoomsHelper(
selectedRooms = state.selectedRooms, selectedRooms = state.selectedRooms,
@@ -11,14 +11,12 @@ package io.element.android.libraries.troubleshoot.impl.history
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
@@ -50,6 +48,7 @@ import io.element.android.libraries.designsystem.theme.components.ListItem
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.push.api.history.PushHistoryItem import io.element.android.libraries.push.api.history.PushHistoryItem
import io.element.android.libraries.troubleshoot.impl.R import io.element.android.libraries.troubleshoot.impl.R
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@@ -68,7 +67,7 @@ fun PushHistoryView(
.fillMaxSize() .fillMaxSize()
.systemBarsPadding() .systemBarsPadding()
.imePadding(), .imePadding(),
contentWindowInsets = WindowInsets.statusBars, contentWindowInsets = scaffoldScrollableContentInsets,
topBar = { topBar = {
TopAppBar( TopAppBar(
navigationIcon = { navigationIcon = {