Render drawer Navigate/You/Feeds sections from NavBarCatalog
Previously the drawer hand-coded label + icon + route for every item, duplicating what NavBarCatalog already stored. Adding a new screen meant updating both files (and forgetting the catalog silently broke the bottom-bar settings, as happened with Polls). - Add POLLS to the catalog (was missing). - Add three ordered id lists in NavBarItem.kt: DrawerNavigateItems, DrawerYouItems, DrawerFeedsItems. Each drawer section iterates its list and looks each id up in NavBarCatalog. - Add CatalogSection + CatalogNavigationRow helpers in DrawerContent that render a NavBarItemDef using the existing NavigationRow overloads (Drawable vs Vector icon). - Profile keeps its primary-color tint via a special case inside CatalogSection (the only item with a non-default tint). - Create (Share HLS Video / Chess) and System (IconRowRelays + Settings) stay hand-coded: they contain non-catalog items or custom composables. Net: DrawerContent.kt shrinks by ~160 lines; adding a new drawer screen is now a single catalog entry plus one list membership.
This commit is contained in:
+48
@@ -73,6 +73,7 @@ enum class NavBarItem {
|
|||||||
FOLLOW_PACKS,
|
FOLLOW_PACKS,
|
||||||
LIVE_STREAMS,
|
LIVE_STREAMS,
|
||||||
LONGS,
|
LONGS,
|
||||||
|
POLLS,
|
||||||
BADGES,
|
BADGES,
|
||||||
PRODUCTS,
|
PRODUCTS,
|
||||||
EMOJI_SETS,
|
EMOJI_SETS,
|
||||||
@@ -246,6 +247,13 @@ val NavBarCatalog: Map<NavBarItem, NavBarItemDef> =
|
|||||||
icon = NavBarIcon.Vector(Icons.Outlined.SmartDisplay),
|
icon = NavBarIcon.Vector(Icons.Outlined.SmartDisplay),
|
||||||
resolveRoute = { Route.Longs },
|
resolveRoute = { Route.Longs },
|
||||||
),
|
),
|
||||||
|
NavBarItem.POLLS to
|
||||||
|
NavBarItemDef(
|
||||||
|
id = NavBarItem.POLLS,
|
||||||
|
labelRes = R.string.polls,
|
||||||
|
icon = NavBarIcon.Drawable(R.drawable.ic_poll, reference = 1),
|
||||||
|
resolveRoute = { Route.Polls },
|
||||||
|
),
|
||||||
NavBarItem.BADGES to
|
NavBarItem.BADGES to
|
||||||
NavBarItemDef(
|
NavBarItemDef(
|
||||||
id = NavBarItem.BADGES,
|
id = NavBarItem.BADGES,
|
||||||
@@ -284,3 +292,43 @@ val DefaultBottomBarItems: List<NavBarItem> =
|
|||||||
NavBarItem.DISCOVER,
|
NavBarItem.DISCOVER,
|
||||||
NavBarItem.NOTIFICATIONS,
|
NavBarItem.NOTIFICATIONS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ordered membership lists for each drawer section. The drawer renders these by looking up
|
||||||
|
// each id in NavBarCatalog, so adding a new screen only requires editing the catalog + the
|
||||||
|
// matching section list below — not two separate files.
|
||||||
|
val DrawerNavigateItems: List<NavBarItem> =
|
||||||
|
listOf(
|
||||||
|
NavBarItem.HOME,
|
||||||
|
NavBarItem.MESSAGES,
|
||||||
|
NavBarItem.VIDEO,
|
||||||
|
NavBarItem.DISCOVER,
|
||||||
|
NavBarItem.NOTIFICATIONS,
|
||||||
|
)
|
||||||
|
|
||||||
|
val DrawerYouItems: List<NavBarItem> =
|
||||||
|
listOf(
|
||||||
|
NavBarItem.PROFILE,
|
||||||
|
NavBarItem.MY_LISTS,
|
||||||
|
NavBarItem.BOOKMARKS,
|
||||||
|
NavBarItem.WEB_BOOKMARKS,
|
||||||
|
NavBarItem.DRAFTS,
|
||||||
|
NavBarItem.INTEREST_SETS,
|
||||||
|
NavBarItem.EMOJI_PACKS,
|
||||||
|
NavBarItem.WALLET,
|
||||||
|
)
|
||||||
|
|
||||||
|
val DrawerFeedsItems: List<NavBarItem> =
|
||||||
|
listOf(
|
||||||
|
NavBarItem.COMMUNITIES,
|
||||||
|
NavBarItem.ARTICLES,
|
||||||
|
NavBarItem.PICTURES,
|
||||||
|
NavBarItem.SHORTS,
|
||||||
|
NavBarItem.PUBLIC_CHATS,
|
||||||
|
NavBarItem.FOLLOW_PACKS,
|
||||||
|
NavBarItem.LIVE_STREAMS,
|
||||||
|
NavBarItem.LONGS,
|
||||||
|
NavBarItem.POLLS,
|
||||||
|
NavBarItem.BADGES,
|
||||||
|
NavBarItem.PRODUCTS,
|
||||||
|
NavBarItem.EMOJI_SETS,
|
||||||
|
)
|
||||||
|
|||||||
+68
-233
@@ -50,30 +50,17 @@ import androidx.compose.foundation.text.KeyboardActions
|
|||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.FormatListBulleted
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.Send
|
import androidx.compose.material.icons.automirrored.filled.Send
|
||||||
import androidx.compose.material.icons.automirrored.outlined.Article
|
|
||||||
import androidx.compose.material.icons.automirrored.outlined.Chat
|
|
||||||
import androidx.compose.material.icons.filled.AccountCircle
|
import androidx.compose.material.icons.filled.AccountCircle
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material.icons.outlined.AccountBalanceWallet
|
|
||||||
import androidx.compose.material.icons.outlined.CollectionsBookmark
|
import androidx.compose.material.icons.outlined.CollectionsBookmark
|
||||||
import androidx.compose.material.icons.outlined.Drafts
|
import androidx.compose.material.icons.outlined.Drafts
|
||||||
import androidx.compose.material.icons.outlined.EmojiEmotions
|
|
||||||
import androidx.compose.material.icons.outlined.ExpandLess
|
import androidx.compose.material.icons.outlined.ExpandLess
|
||||||
import androidx.compose.material.icons.outlined.ExpandMore
|
import androidx.compose.material.icons.outlined.ExpandMore
|
||||||
import androidx.compose.material.icons.outlined.GroupAdd
|
import androidx.compose.material.icons.outlined.GroupAdd
|
||||||
import androidx.compose.material.icons.outlined.Groups
|
|
||||||
import androidx.compose.material.icons.outlined.Language
|
|
||||||
import androidx.compose.material.icons.outlined.MilitaryTech
|
|
||||||
import androidx.compose.material.icons.outlined.Photo
|
import androidx.compose.material.icons.outlined.Photo
|
||||||
import androidx.compose.material.icons.outlined.PlayCircle
|
|
||||||
import androidx.compose.material.icons.outlined.Sensors
|
|
||||||
import androidx.compose.material.icons.outlined.Settings
|
|
||||||
import androidx.compose.material.icons.outlined.SettingsInputAntenna
|
import androidx.compose.material.icons.outlined.SettingsInputAntenna
|
||||||
import androidx.compose.material.icons.outlined.SmartDisplay
|
import androidx.compose.material.icons.outlined.SmartDisplay
|
||||||
import androidx.compose.material.icons.outlined.Storefront
|
|
||||||
import androidx.compose.material.icons.outlined.Tag
|
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
@@ -122,6 +109,13 @@ import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUse
|
|||||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserStatuses
|
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserStatuses
|
||||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
||||||
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.bottombars.DrawerFeedsItems
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.bottombars.DrawerNavigateItems
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.bottombars.DrawerYouItems
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.bottombars.NavBarCatalog
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.bottombars.NavBarIcon
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.bottombars.NavBarItem
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.bottombars.NavBarItemDef
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
|
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||||
@@ -549,219 +543,9 @@ fun ListContent(
|
|||||||
nav: INav,
|
nav: INav,
|
||||||
) {
|
) {
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
CollapsibleSection(title = R.string.drawer_section_navigate) {
|
CatalogSection(R.string.drawer_section_navigate, DrawerNavigateItems, accountViewModel, nav)
|
||||||
NavigationRow(
|
CatalogSection(R.string.drawer_section_you, DrawerYouItems, accountViewModel, nav)
|
||||||
title = R.string.route_home,
|
CatalogSection(R.string.drawer_section_feeds, DrawerFeedsItems, accountViewModel, nav)
|
||||||
icon = R.drawable.ic_home,
|
|
||||||
iconReference = 0,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Home,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.route_messages,
|
|
||||||
icon = R.drawable.ic_dm,
|
|
||||||
iconReference = 0,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Message,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.route_video,
|
|
||||||
icon = R.drawable.ic_video,
|
|
||||||
iconReference = 0,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Video,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.route_discover,
|
|
||||||
icon = R.drawable.ic_sensors,
|
|
||||||
iconReference = 0,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Discover,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.route_notifications,
|
|
||||||
icon = R.drawable.ic_notifications,
|
|
||||||
iconReference = 0,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
computeRoute = { Route.Notification() },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
CollapsibleSection(title = R.string.drawer_section_you) {
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.profile,
|
|
||||||
icon = Icons.Default.AccountCircle,
|
|
||||||
tint = MaterialTheme.colorScheme.primary,
|
|
||||||
nav = nav,
|
|
||||||
computeRoute = {
|
|
||||||
Route.Profile(accountViewModel.userProfile().pubkeyHex)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.my_lists,
|
|
||||||
icon = Icons.AutoMirrored.Filled.FormatListBulleted,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Lists,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.bookmarks,
|
|
||||||
icon = Icons.Outlined.CollectionsBookmark,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.BookmarkGroups,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.web_bookmarks,
|
|
||||||
icon = Icons.Outlined.Language,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.WebBookmarks,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.drafts,
|
|
||||||
icon = Icons.Outlined.Drafts,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Drafts,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.interest_sets_title,
|
|
||||||
icon = Icons.Outlined.Tag,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.InterestSets,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.manage_emoji_packs,
|
|
||||||
icon = Icons.Outlined.EmojiEmotions,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.EmojiPacks,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.wallet,
|
|
||||||
icon = Icons.Outlined.AccountBalanceWallet,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Wallet,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
CollapsibleSection(title = R.string.drawer_section_feeds) {
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.communities,
|
|
||||||
icon = Icons.Outlined.Groups,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Communities,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.discover_reads,
|
|
||||||
icon = Icons.AutoMirrored.Outlined.Article,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Articles,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.pictures,
|
|
||||||
icon = Icons.Outlined.Photo,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Pictures,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.shorts,
|
|
||||||
icon = Icons.Outlined.PlayCircle,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Shorts,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.public_chats,
|
|
||||||
icon = Icons.AutoMirrored.Outlined.Chat,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.PublicChats,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.follow_packs,
|
|
||||||
icon = Icons.Outlined.CollectionsBookmark,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.FollowPacks,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.live_streams,
|
|
||||||
icon = Icons.Outlined.Sensors,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.LiveStreams,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.longs,
|
|
||||||
icon = Icons.Outlined.SmartDisplay,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Longs,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.polls,
|
|
||||||
icon = R.drawable.ic_poll,
|
|
||||||
iconReference = 1,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Polls,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.badges,
|
|
||||||
icon = Icons.Outlined.MilitaryTech,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Badges,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.discover_marketplace,
|
|
||||||
icon = Icons.Outlined.Storefront,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.Products,
|
|
||||||
)
|
|
||||||
|
|
||||||
NavigationRow(
|
|
||||||
title = R.string.emoji_sets,
|
|
||||||
icon = Icons.Outlined.EmojiEmotions,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.BrowseEmojiSets,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
CollapsibleSection(title = R.string.drawer_section_create) {
|
CollapsibleSection(title = R.string.drawer_section_create) {
|
||||||
NavigationRow(
|
NavigationRow(
|
||||||
@@ -793,13 +577,9 @@ fun ListContent(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
NavigationRow(
|
NavBarCatalog[NavBarItem.SETTINGS]?.let {
|
||||||
title = R.string.settings,
|
CatalogNavigationRow(it, MaterialTheme.colorScheme.onBackground, accountViewModel, nav)
|
||||||
icon = Icons.Outlined.Settings,
|
}
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
nav = nav,
|
|
||||||
route = Route.AllSettings,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
@@ -813,6 +593,61 @@ fun ListContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a drawer section by iterating [ids] and looking each one up in [NavBarCatalog].
|
||||||
|
* Profile gets the primary-colored tint; every other item uses onBackground.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun CatalogSection(
|
||||||
|
titleRes: Int,
|
||||||
|
ids: List<NavBarItem>,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val primary = MaterialTheme.colorScheme.primary
|
||||||
|
val onBackground = MaterialTheme.colorScheme.onBackground
|
||||||
|
|
||||||
|
CollapsibleSection(title = titleRes) {
|
||||||
|
ids.forEach { id ->
|
||||||
|
NavBarCatalog[id]?.let { def ->
|
||||||
|
val tint = if (def.id == NavBarItem.PROFILE) primary else onBackground
|
||||||
|
CatalogNavigationRow(def, tint, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CatalogNavigationRow(
|
||||||
|
def: NavBarItemDef,
|
||||||
|
tint: Color,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
when (val icon = def.icon) {
|
||||||
|
is NavBarIcon.Drawable -> {
|
||||||
|
NavigationRow(
|
||||||
|
title = def.labelRes,
|
||||||
|
icon = icon.resId,
|
||||||
|
iconReference = icon.reference,
|
||||||
|
tint = tint,
|
||||||
|
nav = nav,
|
||||||
|
computeRoute = { def.resolveRoute(accountViewModel) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is NavBarIcon.Vector -> {
|
||||||
|
NavigationRow(
|
||||||
|
title = def.labelRes,
|
||||||
|
icon = icon.vector,
|
||||||
|
tint = tint,
|
||||||
|
nav = nav,
|
||||||
|
computeRoute = { def.resolveRoute(accountViewModel) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CollapsibleSection(
|
fun CollapsibleSection(
|
||||||
title: Int,
|
title: Int,
|
||||||
|
|||||||
Reference in New Issue
Block a user