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:
+3
-1
@@ -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 {
|
||||
|
||||
+20
-1
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -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) {
|
||||
|
||||
+10
@@ -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) {
|
||||
|
||||
+22
-2
@@ -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
|
||||
|
||||
+17
@@ -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,
|
||||
) {
|
||||
|
||||
+3
-1
@@ -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 {
|
||||
|
||||
+20
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+50
-22
@@ -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 } }
|
||||
|
||||
|
||||
+12
-1
@@ -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,
|
||||
|
||||
+19
@@ -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()
|
||||
|
||||
+11
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user