diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/AppBottomBar.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/AppBottomBar.kt index d136372dc..9f809abd7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/AppBottomBar.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/AppBottomBar.kt @@ -54,6 +54,11 @@ import com.vitorpamplona.amethyst.ui.theme.Size10Modifier import com.vitorpamplona.amethyst.ui.theme.Size24dp import com.vitorpamplona.amethyst.ui.theme.Size27dp +/** Content height of the [AppBottomBar] (the 50.dp Column inside [RenderBottomMenu]), + * exclusive of the system navigation-bar inset. Used by FAB callers that want to + * reserve the same vertical space when the bar hides itself on canPop entries. */ +val AppBottomBarHeight = 50.dp + @Composable fun AppBottomBar( selectedRoute: Route?, @@ -99,7 +104,7 @@ private fun RenderBottomMenu( .background(MaterialTheme.colorScheme.background) .windowInsetsPadding(windowInsets) .consumeWindowInsets(windowInsets) - .height(50.dp), + .height(AppBottomBarHeight), ) { HorizontalDivider( thickness = DividerThickness, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/FabBottomBarPadding.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/FabBottomBarPadding.kt new file mode 100644 index 000000000..9f181d4db --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/FabBottomBarPadding.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.amethyst.ui.navigation.bottombars + +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vitorpamplona.amethyst.ui.navigation.navs.INav + +/** + * Reserves the visual space the [AppBottomBar] occupies on root tab entries so a + * FloatingActionButton stays at the same vertical position whether or not the bar is + * rendered. [AppBottomBar] hides itself on canPop entries (drawer pushes, in-app + * navigations) — without this padding the FAB drops by [AppBottomBarHeight] there. + * + * The system-navigation-bar inset is already handled by the surrounding Scaffold, so + * only the bar's content height needs to be reserved. + */ +@Composable +fun Modifier.fabBottomBarPadding(nav: INav): Modifier = if (nav.canPop()) padding(bottom = AppBottomBarHeight) else this diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/list/ListOfBookmarkGroupsScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/list/ListOfBookmarkGroupsScreen.kt index e9a2dc950..469a490eb 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/list/ListOfBookmarkGroupsScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/list/ListOfBookmarkGroupsScreen.kt @@ -40,6 +40,7 @@ import com.vitorpamplona.amethyst.model.nip51Lists.OldBookmarkListState import com.vitorpamplona.amethyst.model.nip51Lists.PinListState import com.vitorpamplona.amethyst.model.nip51Lists.labeledBookmarkLists.LabeledBookmarkList import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar +import com.vitorpamplona.amethyst.ui.navigation.bottombars.fabBottomBarPadding import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton @@ -130,7 +131,10 @@ fun ListOfBookmarkGroupsFeed( } }, floatingActionButton = { - BookmarkGroupFab(onAddGroup = addBookmarkGroup) + BookmarkGroupFab( + onAddGroup = addBookmarkGroup, + modifier = Modifier.fabBottomBarPadding(nav), + ) }, ) { paddingValues -> Column( @@ -160,7 +164,10 @@ fun ListOfBookmarkGroupsFeed( } @Composable -fun BookmarkGroupFab(onAddGroup: () -> Unit) { +fun BookmarkGroupFab( + onAddGroup: () -> Unit, + modifier: Modifier = Modifier, +) { ExtendedFloatingActionButton( text = { Text(text = stringRes(R.string.follow_set_create_btn_label)) @@ -174,5 +181,6 @@ fun BookmarkGroupFab(onAddGroup: () -> Unit) { onClick = onAddGroup, shape = CircleShape, containerColor = MaterialTheme.colorScheme.primary, + modifier = modifier, ) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/emojipacks/list/ListOfEmojiPacksScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/emojipacks/list/ListOfEmojiPacksScreen.kt index dd8494f75..37fa090d3 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/emojipacks/list/ListOfEmojiPacksScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/emojipacks/list/ListOfEmojiPacksScreen.kt @@ -62,6 +62,7 @@ import com.vitorpamplona.amethyst.ui.components.M3ActionDialog import com.vitorpamplona.amethyst.ui.components.M3ActionRow import com.vitorpamplona.amethyst.ui.components.M3ActionSection import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar +import com.vitorpamplona.amethyst.ui.navigation.bottombars.fabBottomBarPadding import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton @@ -126,7 +127,10 @@ fun ListOfEmojiPacksFeed( } }, floatingActionButton = { - EmojiPackFab(onAddPack = addEmojiPack) + EmojiPackFab( + onAddPack = addEmojiPack, + modifier = Modifier.fabBottomBarPadding(nav), + ) }, ) { paddingValues -> Column( @@ -308,7 +312,10 @@ private fun MyEmojiListRow( } @Composable -fun EmojiPackFab(onAddPack: () -> Unit) { +fun EmojiPackFab( + onAddPack: () -> Unit, + modifier: Modifier = Modifier, +) { ExtendedFloatingActionButton( text = { Text(text = stringRes(R.string.new_emoji_pack)) @@ -322,5 +329,6 @@ fun EmojiPackFab(onAddPack: () -> Unit) { onClick = onAddPack, shape = CircleShape, containerColor = MaterialTheme.colorScheme.primary, + modifier = modifier, ) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/interestSets/list/ListOfInterestSetsScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/interestSets/list/ListOfInterestSetsScreen.kt index 3f98a03fc..1a6748960 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/interestSets/list/ListOfInterestSetsScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/interestSets/list/ListOfInterestSetsScreen.kt @@ -48,6 +48,7 @@ import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar +import com.vitorpamplona.amethyst.ui.navigation.bottombars.fabBottomBarPadding import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton @@ -82,7 +83,10 @@ fun ListOfInterestSetsScreen( } }, floatingActionButton = { - InterestSetFab(onAdd = { nav.nav(Route.InterestSetMetadataEdit()) }) + InterestSetFab( + onAdd = { nav.nav(Route.InterestSetMetadataEdit()) }, + modifier = Modifier.fabBottomBarPadding(nav), + ) }, ) { paddingValues -> Column( @@ -155,7 +159,10 @@ private fun EmptyInterestSets() { } @Composable -fun InterestSetFab(onAdd: () -> Unit) { +fun InterestSetFab( + onAdd: () -> Unit, + modifier: Modifier = Modifier, +) { ExtendedFloatingActionButton( text = { Text(text = stringRes(R.string.interest_set_create_btn_label)) @@ -169,5 +176,6 @@ fun InterestSetFab(onAdd: () -> Unit) { onClick = onAdd, shape = CircleShape, containerColor = MaterialTheme.colorScheme.primary, + modifier = modifier, ) }