feat(nav): add bottom bar to remaining tab-eligible screens

The bottom-nav settings let users place any of these routes in the bar,
but the screens themselves never rendered AppBottomBar — so even when
configured as a tab, the bar was missing on Profile, Wallet, Lists,
BookmarkGroups, WebBookmarks, Drafts, InterestSets, EmojiPacks,
BrowseEmojiSets, and AllSettings.

AppBottomBar self-hides via nav.canPop(), so adding the bar is safe on
every entry: it appears only when the screen is the tab root, hidden
otherwise (drawer / deep link).

Same-tab tap scrolls the screen's main list to the top, mirroring the
existing tab behavior. State is hoisted as needed:
- WebBookmarks, Drafts, BrowseEmojiSets: feedState.sendToTop()
- Lists, BookmarkGroups, EmojiPacks: hoisted LazyListState/LazyGridState
  through the feed-view helper, animateScrollTo(0)
- Wallet, InterestSets: hoisted LazyListState locally
- AllSettings: hoisted ScrollState (verticalScroll column)
- Profile: wrapped in Scaffold, hoisted ScrollState from RenderSurface

https://claude.ai/code/session_01PrirRcL7g8iX7vTqqLTkBS
This commit is contained in:
Claude
2026-04-27 20:35:56 +00:00
parent 759fd67ef5
commit baaee94555
12 changed files with 198 additions and 30 deletions
@@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
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.material3.HorizontalDivider
@@ -67,11 +68,12 @@ fun ListOfBookmarkGroupsFeedView(
onItemDescriptionChange: (bookmarkGroup: LabeledBookmarkList) -> Unit,
onItemClone: (bookmarkGroup: LabeledBookmarkList, customName: String?, customDesc: String?) -> Unit,
onDeleteItem: (bookmarkGroup: LabeledBookmarkList) -> Unit,
listState: LazyListState = rememberLazyListState(),
) {
val bookmarkGroupFeedState by groupListFeedSource.collectAsStateWithLifecycle()
LazyColumn(
state = rememberLazyListState(),
state = listState,
contentPadding = FeedPadding,
) {
item {
@@ -23,12 +23,14 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarkgroups.list
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
@@ -37,6 +39,7 @@ import com.vitorpamplona.amethyst.model.nip51Lists.BookmarkListState
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.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
@@ -44,6 +47,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarkgroups.BookmarkType
import com.vitorpamplona.amethyst.ui.stringRes
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
@Composable
fun ListOfBookmarkGroupsScreen(
@@ -86,7 +90,8 @@ fun ListOfBookmarkGroupsScreen(
)
}
},
nav,
accountViewModel = accountViewModel,
nav = nav,
)
}
@@ -105,12 +110,25 @@ fun ListOfBookmarkGroupsFeed(
changeBookmarkGroupDescription: (bookmarkGroup: LabeledBookmarkList) -> Unit,
cloneBookmarkGroup: (bookmarkGroup: LabeledBookmarkList, customName: String?, customDesc: String?) -> Unit,
deleteBookmarkGroup: (bookmarkGroup: LabeledBookmarkList) -> Unit,
accountViewModel: AccountViewModel,
nav: INav,
) {
val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
topBar = {
TopBarWithBackButton(caption = stringRes(R.string.bookmark_lists), nav)
},
bottomBar = {
AppBottomBar(Route.BookmarkGroups, nav, accountViewModel) { route ->
if (route == Route.BookmarkGroups) {
coroutineScope.launch { listState.animateScrollToItem(0) }
} else {
nav.navBottomBar(route)
}
}
},
floatingActionButton = {
BookmarkGroupFab(onAddGroup = addBookmarkGroup)
},
@@ -135,6 +153,7 @@ fun ListOfBookmarkGroupsFeed(
onItemDescriptionChange = changeBookmarkGroupDescription,
onItemClone = cloneBookmarkGroup,
onDeleteItem = deleteBookmarkGroup,
listState = listState,
)
}
}
@@ -53,7 +53,9 @@ import com.vitorpamplona.amethyst.ui.feeds.ScrollStateKeys.DRAFTS
import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
import com.vitorpamplona.amethyst.ui.layouts.rememberFeedContentPadding
import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.navigation.topbars.ShorterTopAppBar
import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon
import com.vitorpamplona.amethyst.ui.note.NoteCompose
@@ -145,6 +147,15 @@ private fun RenderDraftListScreen(
},
)
},
bottomBar = {
AppBottomBar(Route.Drafts, nav, accountViewModel) { route ->
if (route == Route.Drafts) {
feedState.sendToTop()
} else {
nav.navBottomBar(route)
}
}
},
accountViewModel = accountViewModel,
) {
RefresheableBox(feedState) {
@@ -49,6 +49,7 @@ import com.vitorpamplona.amethyst.ui.feeds.WatchScrollToTop
import com.vitorpamplona.amethyst.ui.feeds.rememberForeverLazyGridState
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
import com.vitorpamplona.amethyst.ui.layouts.rememberFeedContentPadding
import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -84,6 +85,15 @@ fun BrowseEmojiSetsScreen(
topBar = {
BrowseEmojiSetsTopBar(accountViewModel, nav)
},
bottomBar = {
AppBottomBar(Route.BrowseEmojiSets, nav, accountViewModel) { route ->
if (route == Route.BrowseEmojiSets) {
feedContentState.sendToTop()
} else {
nav.navBottomBar(route)
}
}
},
accountViewModel = accountViewModel,
) {
RefresheableBox(feedContentState, true) {
@@ -30,6 +30,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
@@ -44,6 +45,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
@@ -59,6 +61,7 @@ import com.vitorpamplona.amethyst.ui.components.ClickableBox
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.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
@@ -70,6 +73,7 @@ import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.Size40Modifier
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
@Composable
fun ListOfEmojiPacksScreen(
@@ -88,7 +92,8 @@ fun ListOfEmojiPacksScreen(
accountViewModel.account.deleteOwnedEmojiPack(pack.identifier)
}
},
nav,
accountViewModel = accountViewModel,
nav = nav,
)
}
@@ -101,12 +106,25 @@ fun ListOfEmojiPacksFeed(
openEmojiPack: (OwnedEmojiPack) -> Unit,
editEmojiPack: (OwnedEmojiPack) -> Unit,
deleteEmojiPack: (OwnedEmojiPack) -> Unit,
accountViewModel: AccountViewModel,
nav: INav,
) {
val gridState = rememberLazyGridState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
topBar = {
TopBarWithBackButton(caption = stringRes(R.string.emoji_packs_title), nav)
},
bottomBar = {
AppBottomBar(Route.EmojiPacks, nav, accountViewModel) { route ->
if (route == Route.EmojiPacks) {
coroutineScope.launch { gridState.animateScrollToItem(0) }
} else {
nav.navBottomBar(route)
}
}
},
floatingActionButton = {
EmojiPackFab(onAddPack = addEmojiPack)
},
@@ -125,6 +143,7 @@ fun ListOfEmojiPacksFeed(
openItem = openEmojiPack,
editItem = editEmojiPack,
deleteItem = deleteEmojiPack,
gridState = gridState,
)
}
}
@@ -138,6 +157,7 @@ fun ListOfEmojiPacksFeedView(
openItem: (OwnedEmojiPack) -> Unit,
editItem: (OwnedEmojiPack) -> Unit,
deleteItem: (OwnedEmojiPack) -> Unit,
gridState: LazyGridState = rememberLazyGridState(),
) {
val feedState by listSource.collectAsStateWithLifecycle()
val selectedPacks by selectedPacksFlow.collectAsStateWithLifecycle()
@@ -158,7 +178,7 @@ fun ListOfEmojiPacksFeedView(
} else {
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 160.dp),
state = rememberLazyGridState(),
state = gridState,
modifier = Modifier.fillMaxSize(),
contentPadding =
androidx.compose.foundation.layout
@@ -29,6 +29,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.HorizontalDivider
@@ -37,6 +38,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
@@ -45,6 +47,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
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.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
@@ -52,6 +55,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
import kotlinx.coroutines.launch
@Composable
fun ListOfInterestSetsScreen(
@@ -61,10 +65,22 @@ fun ListOfInterestSetsScreen(
val sets by accountViewModel.account.interestSets.listFeedFlow
.collectAsStateWithLifecycle()
val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
topBar = {
TopBarWithBackButton(caption = stringRes(R.string.interest_sets_title), nav)
},
bottomBar = {
AppBottomBar(Route.InterestSets, nav, accountViewModel) { route ->
if (route == Route.InterestSets) {
coroutineScope.launch { listState.animateScrollToItem(0) }
} else {
nav.navBottomBar(route)
}
}
},
floatingActionButton = {
InterestSetFab(onAdd = { nav.nav(Route.InterestSetMetadataEdit()) })
},
@@ -80,6 +96,7 @@ fun ListOfInterestSetsScreen(
EmptyInterestSets()
} else {
LazyColumn(
state = listState,
modifier = Modifier.fillMaxSize(),
contentPadding = FeedPadding,
) {
@@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
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.material3.HorizontalDivider
@@ -53,13 +54,14 @@ import com.vitorpamplona.amethyst.ui.theme.grayText
fun AllPeopleListFeedView(
peopleListModel: PeopleListViewModel,
followPackModel: FollowPackViewModel,
listState: LazyListState = rememberLazyListState(),
nav: INav,
) {
val peopleListFeedState by peopleListModel.listFlow().collectAsStateWithLifecycle()
val followPackFeedState by followPackModel.listFlow().collectAsStateWithLifecycle()
LazyColumn(
state = rememberLazyListState(),
state = listState,
contentPadding = FeedPadding,
) {
stickyHeader {
@@ -24,21 +24,26 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.lifecycle.viewmodel.compose.viewModel
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.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.SpacedBy5dp
import kotlinx.coroutines.launch
@Composable
fun ListOfPeopleListsScreen(
@@ -51,19 +56,32 @@ fun ListOfPeopleListsScreen(
val pack: FollowPackViewModel = viewModel()
pack.init(accountViewModel)
ListOfPeopleListsScreen(list, pack, nav)
ListOfPeopleListsScreen(list, pack, accountViewModel, nav)
}
@Composable
fun ListOfPeopleListsScreen(
list: PeopleListViewModel,
pack: FollowPackViewModel,
accountViewModel: AccountViewModel,
nav: INav,
) {
val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
topBar = {
TopBarWithBackButton(stringRes(R.string.my_lists), nav)
},
bottomBar = {
AppBottomBar(Route.Lists, nav, accountViewModel) { route ->
if (route == Route.Lists) {
coroutineScope.launch { listState.animateScrollToItem(0) }
} else {
nav.navBottomBar(route)
}
}
},
) { paddingValues ->
Column(
Modifier
@@ -72,7 +90,7 @@ fun ListOfPeopleListsScreen(
bottom = paddingValues.calculateBottomPadding(),
).fillMaxHeight(),
) {
AllPeopleListFeedView(list, pack, nav)
AllPeopleListFeedView(list, pack, listState, nav)
}
}
}
@@ -20,6 +20,7 @@
*/
package com.vitorpamplona.amethyst.ui.screen.loggedIn.profile
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.gestures.scrollBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -28,6 +29,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
@@ -36,6 +38,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SecondaryScrollableTabRow
import androidx.compose.material3.Surface
import androidx.compose.material3.Tab
@@ -62,7 +65,9 @@ import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.account.observeAccountIsHiddenUser
import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel
import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar
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.screen.loggedIn.profile.bookmarks.BookmarkTabHeader
import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.bookmarks.TabBookmarks
@@ -291,31 +296,55 @@ fun ProfileScreen(
UserProfileFilterAssemblerSubscription(baseUser, accountViewModel.dataSources().profile)
RenderSurface { tabRowModifier: Modifier, pagerModifier: Modifier ->
RenderScreen(
baseUser,
tabRowModifier,
pagerModifier,
threadsViewModel,
repliesViewModel,
mutualViewModel,
appRecommendations,
externalIdentities,
followsFeedViewModel,
followersFeedViewModel,
zapFeedViewModel,
bookmarksFeedViewModel,
pinnedNotesFeedViewModel,
galleryFeedViewModel,
reportsFeedViewModel,
accountViewModel,
nav,
)
val scrollState = rememberScrollState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
bottomBar = {
AppBottomBar(
Route.Profile(accountViewModel.userProfile().pubkeyHex),
nav,
accountViewModel,
) { route ->
if (route is Route.Profile) {
coroutineScope.launch { scrollState.animateScrollTo(0) }
} else {
nav.navBottomBar(route)
}
}
},
) { padding ->
Box(modifier = Modifier.padding(padding)) {
RenderSurface(scrollState) { tabRowModifier: Modifier, pagerModifier: Modifier ->
RenderScreen(
baseUser,
tabRowModifier,
pagerModifier,
threadsViewModel,
repliesViewModel,
mutualViewModel,
appRecommendations,
externalIdentities,
followsFeedViewModel,
followersFeedViewModel,
zapFeedViewModel,
bookmarksFeedViewModel,
pinnedNotesFeedViewModel,
galleryFeedViewModel,
reportsFeedViewModel,
accountViewModel,
nav,
)
}
}
}
}
@Composable
private fun RenderSurface(content: @Composable (tabRowModifier: Modifier, pagerModifier: Modifier) -> Unit) {
private fun RenderSurface(
scrollState: ScrollState,
content: @Composable (tabRowModifier: Modifier, pagerModifier: Modifier) -> Unit,
) {
Surface(
modifier = Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.background,
@@ -330,7 +359,6 @@ private fun RenderSurface(content: @Composable (tabRowModifier: Modifier, pagerM
.onSizeChanged { columnSize = it },
) {
val coroutineScope = rememberCoroutineScope()
val scrollState = rememberScrollState()
val tabRowModifier = remember { Modifier.onSizeChanged { tabsSize = it } }
@@ -57,6 +57,7 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
@@ -90,13 +91,23 @@ fun AllSettingsScreen(
val scope = rememberCoroutineScope()
var showResetMarmotDialog by remember { mutableStateOf(false) }
var isResettingMarmot by remember { mutableStateOf(false) }
val scrollState = rememberScrollState()
Scaffold(
topBar = {
TopBarWithBackButton(stringRes(id = R.string.settings), nav)
},
bottomBar = {
AppBottomBar(Route.AllSettings, nav, accountViewModel) { route ->
if (route == Route.AllSettings) {
scope.launch { scrollState.animateScrollTo(0) }
} else {
nav.navBottomBar(route)
}
}
},
) { padding ->
Column(Modifier.padding(padding).verticalScroll(rememberScrollState())) {
Column(Modifier.padding(padding).verticalScroll(scrollState)) {
SettingsSectionHeader(R.string.account_settings)
SettingsNavigationRow(
title = R.string.relay_setup,
@@ -33,7 +33,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
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.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
@@ -55,6 +57,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -66,10 +69,12 @@ import androidx.lifecycle.viewmodel.compose.viewModel
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.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
import kotlinx.coroutines.launch
import java.text.NumberFormat
@OptIn(ExperimentalMaterial3Api::class)
@@ -82,6 +87,8 @@ fun WalletScreen(
walletViewModel.init(accountViewModel)
val hasWallet by walletViewModel.hasWalletSetup.collectAsState()
val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
topBar = {
@@ -107,6 +114,15 @@ fun WalletScreen(
},
)
},
bottomBar = {
AppBottomBar(Route.Wallet, nav, accountViewModel) { route ->
if (route == Route.Wallet) {
coroutineScope.launch { listState.animateScrollToItem(0) }
} else {
nav.navBottomBar(route)
}
}
},
) { padding ->
if (!hasWallet) {
NoWalletSetup(
@@ -117,6 +133,7 @@ fun WalletScreen(
MultiWalletHomeContent(
walletViewModel = walletViewModel,
modifier = Modifier.padding(padding),
listState = listState,
nav = nav,
)
}
@@ -161,6 +178,7 @@ private fun NoWalletSetup(
private fun MultiWalletHomeContent(
walletViewModel: WalletViewModel,
modifier: Modifier,
listState: LazyListState,
nav: INav,
) {
val walletInfoList by walletViewModel.walletInfoList.collectAsState()
@@ -173,6 +191,7 @@ private fun MultiWalletHomeContent(
}
LazyColumn(
state = listState,
modifier =
modifier
.fillMaxSize()
@@ -77,7 +77,9 @@ import com.vitorpamplona.amethyst.ui.feeds.ScrollStateKeys
import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
import com.vitorpamplona.amethyst.ui.layouts.rememberFeedContentPadding
import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.navigation.topbars.ShorterTopAppBar
import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon
import com.vitorpamplona.amethyst.ui.screen.SaveableFeedState
@@ -138,6 +140,15 @@ private fun RenderWebBookmarksScreen(
},
)
},
bottomBar = {
AppBottomBar(Route.WebBookmarks, nav, accountViewModel) { route ->
if (route == Route.WebBookmarks) {
feedState.sendToTop()
} else {
nav.navBottomBar(route)
}
}
},
floatingButton = {
FloatingActionButton(
onClick = { showAddDialog = true },