Add a reusable Navigation Bar Item (#3983)

This commit is contained in:
David Perez 2024-09-27 11:41:57 -05:00 committed by GitHub
parent 853f25bf57
commit b696964cb7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 92 additions and 61 deletions

View file

@ -0,0 +1,78 @@
package com.x8bit.bitwarden.ui.platform.components.navigation
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.RowScope
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import com.x8bit.bitwarden.ui.platform.components.badge.NotificationBadge
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
/**
* A custom Bitwarden-themed bottom app bar.
*
* @param labelRes The custom label for the navigation item.
* @param contentDescriptionRes The custom content description for the navigation item.
* @param selectedIconRes The icon to be displayed when the navigation item is selected.
* @param unselectedIconRes The icon to be displayed when the navigation item is not selected.
* @param isSelected Indicates that the navigation item is selected.
* @param onClick The lambda to be invoked when the navigation item is clicked.
* @param modifier A [Modifier] that you can use to apply custom modifications to the composable.
* @param notificationCount The notification count for the navigation item.
*/
@Composable
fun RowScope.BitwardenNavigationBarItem(
@StringRes labelRes: Int,
@StringRes contentDescriptionRes: Int,
@DrawableRes selectedIconRes: Int,
@DrawableRes unselectedIconRes: Int,
isSelected: Boolean,
onClick: () -> Unit,
modifier: Modifier = Modifier,
notificationCount: Int = 0,
) {
NavigationBarItem(
icon = {
BadgedBox(
badge = {
NotificationBadge(
notificationCount = notificationCount,
isVisible = notificationCount > 0,
)
},
) {
Icon(
painter = rememberVectorPainter(
id = if (isSelected) selectedIconRes else unselectedIconRes,
),
contentDescription = stringResource(id = contentDescriptionRes),
)
}
},
label = {
Text(
text = stringResource(id = labelRes),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
selected = isSelected,
onClick = onClick,
colors = NavigationBarItemDefaults.colors(
indicatorColor = MaterialTheme.colorScheme.secondaryContainer,
selectedIconColor = MaterialTheme.colorScheme.onSecondaryContainer,
unselectedIconColor = MaterialTheme.colorScheme.onSurface,
selectedTextColor = MaterialTheme.colorScheme.onSecondaryContainer,
unselectedTextColor = MaterialTheme.colorScheme.onSurface,
),
modifier = modifier,
)
}

View file

@ -1,7 +1,5 @@
package com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.consumeWindowInsets
@ -12,14 +10,9 @@ import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@ -29,8 +22,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavBackStackEntry
@ -47,10 +38,9 @@ import androidx.navigation.navOptions
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
import com.x8bit.bitwarden.ui.platform.base.util.max
import com.x8bit.bitwarden.ui.platform.base.util.toDp
import com.x8bit.bitwarden.ui.platform.components.badge.NotificationBadge
import com.x8bit.bitwarden.ui.platform.components.navigation.BitwardenNavigationBarItem
import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.x8bit.bitwarden.ui.platform.components.scrim.BitwardenAnimatedScrim
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.platform.feature.settings.navigateToSettingsGraph
import com.x8bit.bitwarden.ui.platform.feature.settings.settingsGraph
@ -249,7 +239,6 @@ private fun VaultUnlockedNavBarScaffold(
}
}
@Suppress("LongMethod")
@Composable
private fun VaultBottomAppBar(
state: VaultUnlockedNavBarState,
@ -277,56 +266,20 @@ private fun VaultBottomAppBar(
// below recompose when the navigation state changes to update the selected tab.
val navBackStackEntry by navController.currentBackStackEntryAsState()
destinations.forEach { destination ->
val isSelected = navBackStackEntry.isCurrentTab(destination)
NavigationBarItem(
icon = {
BadgedBox(
badge = {
NotificationBadge(
notificationCount = destination.notificationCount,
isVisible = destination.notificationCount > 0,
)
},
) {
Icon(
painter = rememberVectorPainter(
id = if (isSelected) {
destination.iconResSelected
} else {
destination.iconRes
},
),
contentDescription = stringResource(
id = destination.contentDescriptionRes,
),
)
}
BitwardenNavigationBarItem(
labelRes = destination.labelRes,
contentDescriptionRes = destination.contentDescriptionRes,
selectedIconRes = destination.iconResSelected,
unselectedIconRes = destination.iconRes,
notificationCount = destination.notificationCount,
isSelected = navBackStackEntry.isCurrentTab(tab = destination),
onClick = when (destination) {
is VaultUnlockedNavBarTab.Vault -> vaultTabClickedAction
VaultUnlockedNavBarTab.Send -> sendTabClickedAction
VaultUnlockedNavBarTab.Generator -> generatorTabClickedAction
is VaultUnlockedNavBarTab.Settings -> settingsTabClickedAction
},
label = {
Text(
text = stringResource(id = destination.labelRes),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
selected = isSelected,
onClick = {
when (destination) {
is VaultUnlockedNavBarTab.Vault -> vaultTabClickedAction()
VaultUnlockedNavBarTab.Send -> sendTabClickedAction()
VaultUnlockedNavBarTab.Generator -> generatorTabClickedAction()
is VaultUnlockedNavBarTab.Settings -> settingsTabClickedAction()
}
},
colors = NavigationBarItemDefaults.colors(
indicatorColor = MaterialTheme.colorScheme.secondaryContainer,
selectedIconColor = MaterialTheme.colorScheme.onSecondaryContainer,
unselectedIconColor = MaterialTheme.colorScheme.onSurface,
selectedTextColor = MaterialTheme.colorScheme.onSecondaryContainer,
unselectedTextColor = MaterialTheme.colorScheme.onSurface,
),
modifier = Modifier.testTag(destination.testTag),
modifier = Modifier.testTag(tag = destination.testTag),
)
}
}