fix(nav): hide bottom bar on screens reached via non-tab-root entries

Bottom-nav screens (Notifications, Discover, etc.) used to render the
bottom bar unconditionally. When reached as a non-tab-root entry —
drawer, deep link, in-app navigation that pushed a fresh copy with
different args — the bar should disappear, matching the back-arrow and
slide-animation rules.

AppBottomBar now takes an INav and returns early when nav.canPop() is
true. The check covers two valid cases for showing the bar:
  - Tab-root entry (carries BOTTOM_NAV_ROOT_KEY, canPop is false).
  - Graph start destination Home (no previous entry, canPop is false).

All 19 callers updated to pass nav; the existing click callback param
is renamed onClick to free up the nav name.

https://claude.ai/code/session_01PrirRcL7g8iX7vTqqLTkBS
This commit is contained in:
Claude
2026-04-27 20:00:28 +00:00
parent 41aa908fbe
commit 759fd67ef5
20 changed files with 27 additions and 21 deletions
@@ -44,6 +44,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
@@ -56,9 +57,14 @@ import com.vitorpamplona.amethyst.ui.theme.Size27dp
@Composable
fun AppBottomBar(
selectedRoute: Route?,
nav: INav,
accountViewModel: AccountViewModel,
nav: (Route) -> Unit,
onClick: (Route) -> Unit,
) {
// Hide the bar on entries that aren't a tab root (drawer or in-app
// pushes). Mirrors the back-arrow rule in canPop().
if (nav.canPop()) return
val items by accountViewModel.settings.uiSettingsFlow.bottomBarItems
.collectAsStateWithLifecycle()
if (items.isEmpty()) {
@@ -73,7 +79,7 @@ fun AppBottomBar(
}
val isKeyboardState by keyboardAsState()
if (isKeyboardState == KeyboardState.Closed) {
RenderBottomMenu(items, selectedRoute, accountViewModel, nav)
RenderBottomMenu(items, selectedRoute, accountViewModel, onClick)
}
}
@@ -65,7 +65,7 @@ fun ArticlesScreen(
ArticlesTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Articles, accountViewModel) { route ->
AppBottomBar(Route.Articles, nav, accountViewModel) { route ->
if (route == Route.Articles) {
articlesFeedContentState.sendToTop()
} else {
@@ -65,7 +65,7 @@ fun AudioRoomsScreen(
AudioRoomsTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.AudioRooms, accountViewModel) { route ->
AppBottomBar(Route.AudioRooms, nav, accountViewModel) { route ->
if (route == Route.AudioRooms) {
audioRoomsFeedContentState.sendToTop()
} else {
@@ -65,7 +65,7 @@ fun BadgesScreen(
BadgesTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Badges, accountViewModel) { route ->
AppBottomBar(Route.Badges, nav, accountViewModel) { route ->
if (route == Route.Badges) {
feedContentState.sendToTop()
} else {
@@ -82,7 +82,7 @@ fun MessagesSinglePane(
}
},
bottomBar = {
AppBottomBar(Route.Message, accountViewModel) { route ->
AppBottomBar(Route.Message, nav, accountViewModel) { route ->
if (route == Route.Message) {
tabs[pagerState.currentPage].feedContentState.sendToTop()
} else {
@@ -79,7 +79,7 @@ fun MessagesTwoPane(
UserDrawerSearchTopBar(accountViewModel, nav) { AmethystClickableIcon() }
},
bottomBar = {
AppBottomBar(Route.Message, accountViewModel) { route ->
AppBottomBar(Route.Message, nav, accountViewModel) { route ->
if (route == Route.Message) {
knownFeedContentState.sendToTop()
newFeedContentState.sendToTop()
@@ -82,7 +82,7 @@ fun CommunitiesScreen(
CommunitiesTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Communities, accountViewModel) { route ->
AppBottomBar(Route.Communities, nav, accountViewModel) { route ->
if (route == Route.Communities) {
feedContentState.sendToTop()
} else {
@@ -239,7 +239,7 @@ private fun DiscoverPages(
}
},
bottomBar = {
AppBottomBar(Route.Discover, accountViewModel) { route ->
AppBottomBar(Route.Discover, nav, accountViewModel) { route ->
if (route == Route.Discover) {
val currentPage = pagerState.currentPage
if (currentPage >= 0 && currentPage < feedTabs.size) {
@@ -65,7 +65,7 @@ fun FollowPacksScreen(
FollowPacksTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.FollowPacks, accountViewModel) { route ->
AppBottomBar(Route.FollowPacks, nav, accountViewModel) { route ->
if (route == Route.FollowPacks) {
followPacksFeedContentState.sendToTop()
} else {
@@ -199,7 +199,7 @@ private fun HomePages(
}
},
bottomBar = {
AppBottomBar(Route.Home, accountViewModel) { route ->
AppBottomBar(Route.Home, nav, accountViewModel) { route ->
if (route == Route.Home) {
tabs[pagerState.currentPage].feedState.sendToTop()
} else {
@@ -65,7 +65,7 @@ fun LiveStreamsScreen(
LiveStreamsTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.LiveStreams, accountViewModel) { route ->
AppBottomBar(Route.LiveStreams, nav, accountViewModel) { route ->
if (route == Route.LiveStreams) {
liveStreamsFeedContentState.sendToTop()
} else {
@@ -65,7 +65,7 @@ fun LongsScreen(
LongsTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Longs, accountViewModel) { route ->
AppBottomBar(Route.Longs, nav, accountViewModel) { route ->
if (route == Route.Longs) {
longsFeedContentState.sendToTop()
} else {
@@ -79,7 +79,7 @@ fun NotificationScreen(
}
},
bottomBar = {
AppBottomBar(Route.Notification(), accountViewModel) { route ->
AppBottomBar(Route.Notification(), nav, accountViewModel) { route ->
if (route is Route.Notification) {
notifFeedContentState.invalidateDataAndSendToTop(true)
} else {
@@ -65,7 +65,7 @@ fun PicturesScreen(
PicturesTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Pictures, accountViewModel) { route ->
AppBottomBar(Route.Pictures, nav, accountViewModel) { route ->
if (route == Route.Pictures) {
picturesFeedContentState.sendToTop()
} else {
@@ -147,7 +147,7 @@ private fun PollsPages(
}
},
bottomBar = {
AppBottomBar(Route.Polls, accountViewModel) { route ->
AppBottomBar(Route.Polls, nav, accountViewModel) { route ->
if (route == Route.Polls) {
tabs[pagerState.currentPage].feedState.sendToTop()
} else {
@@ -64,7 +64,7 @@ fun ProductsScreen(
ProductsTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Products, accountViewModel) { route ->
AppBottomBar(Route.Products, nav, accountViewModel) { route ->
if (route == Route.Products) {
productsFeedContentState.sendToTop()
} else {
@@ -65,7 +65,7 @@ fun PublicChatsScreen(
PublicChatsTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.PublicChats, accountViewModel) { route ->
AppBottomBar(Route.PublicChats, nav, accountViewModel) { route ->
if (route == Route.PublicChats) {
publicChatsFeedContentState.sendToTop()
} else {
@@ -142,7 +142,7 @@ fun SearchScreen(
SearchBar(searchBarViewModel, accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Search, accountViewModel) { route ->
AppBottomBar(Route.Search, nav, accountViewModel) { route ->
nav.navBottomBar(route)
}
},
@@ -65,7 +65,7 @@ fun ShortsScreen(
ShortsTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Shorts, accountViewModel) { route ->
AppBottomBar(Route.Shorts, nav, accountViewModel) { route ->
if (route == Route.Shorts) {
shortsFeedContentState.sendToTop()
} else {
@@ -82,7 +82,7 @@ fun VideoScreen(
StoriesTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.Video, accountViewModel) { route ->
AppBottomBar(Route.Video, nav, accountViewModel) { route ->
if (route == Route.Video) {
videoFeedContentState.sendToTop()
} else {