PM-27703: Update Authenticator navigation (#6109)

This commit is contained in:
David Perez
2025-11-03 10:28:23 -06:00
committed by GitHub
parent b1195b5f46
commit 845a5dec22
27 changed files with 244 additions and 294 deletions

View File

@@ -10,24 +10,26 @@ import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import com.bitwarden.authenticator.data.platform.repository.SettingsRepository
import com.bitwarden.authenticator.ui.platform.composition.LocalManagerProvider
import com.bitwarden.authenticator.ui.platform.feature.debugmenu.debugMenuDestination
import com.bitwarden.authenticator.ui.platform.feature.debugmenu.manager.DebugMenuLaunchManager
import com.bitwarden.authenticator.ui.platform.feature.debugmenu.navigateToDebugMenuScreen
import com.bitwarden.authenticator.ui.platform.feature.rootnav.RootNavScreen
import com.bitwarden.authenticator.ui.platform.feature.rootnav.RootNavigationRoute
import com.bitwarden.authenticator.ui.platform.feature.rootnav.rootNavDestination
import com.bitwarden.ui.platform.base.util.EventsEffect
import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.bitwarden.ui.platform.util.setupEdgeToEdge
import com.bitwarden.ui.platform.util.validate
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
/**
@@ -61,20 +63,28 @@ class MainActivity : AppCompatActivity() {
AppCompatDelegate.setDefaultNightMode(settingsRepository.appTheme.osValue)
setupEdgeToEdge(appThemeFlow = mainViewModel.stateFlow.map { it.theme })
setContent {
val navController = rememberNavController()
SetupEventsEffect(navController = navController)
val state by mainViewModel.stateFlow.collectAsStateWithLifecycle()
updateScreenCapture(isScreenCaptureAllowed = state.isScreenCaptureAllowed)
val navController = rememberNavController()
observeViewModelEvents(navController)
LocalManagerProvider {
BitwardenTheme(
theme = state.theme,
dynamicColor = state.isDynamicColorsEnabled,
) {
RootNavScreen(
NavHost(
navController = navController,
onSplashScreenRemoved = { shouldShowSplashScreen = false },
onExitApplication = { finishAffinity() },
)
startDestination = RootNavigationRoute,
) {
// Both root navigation and debug menu exist at this top level.
// The debug menu can appear on top of the rest of the app without
// interacting with the state-based navigation used by RootNavScreen.
rootNavDestination { shouldShowSplashScreen = false }
debugMenuDestination(
onNavigateBack = { navController.popBackStack() },
onSplashScreenRemoved = { shouldShowSplashScreen = false },
)
}
}
}
}
@@ -92,18 +102,16 @@ class MainActivity : AppCompatActivity() {
mainViewModel.trySendAction(MainAction.ReceiveNewIntent(intent = newIntent))
}
private fun observeViewModelEvents(navController: NavHostController) {
mainViewModel
.eventFlow
.onEach { event ->
when (event) {
MainEvent.NavigateToDebugMenu -> navController.navigateToDebugMenuScreen()
is MainEvent.UpdateAppTheme -> {
AppCompatDelegate.setDefaultNightMode(event.osTheme)
}
@Composable
private fun SetupEventsEffect(navController: NavHostController) {
EventsEffect(viewModel = mainViewModel) { event ->
when (event) {
MainEvent.NavigateToDebugMenu -> navController.navigateToDebugMenuScreen()
is MainEvent.UpdateAppTheme -> {
AppCompatDelegate.setDefaultNightMode(event.osTheme)
}
}
.launchIn(lifecycleScope)
}
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean = debugLaunchManager

View File

@@ -1,19 +1,24 @@
@file:OmitFromCoverage
package com.bitwarden.authenticator.ui.authenticator.feature.authenticator
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.navigation
import com.bitwarden.annotation.OmitFromCoverage
import com.bitwarden.authenticator.ui.authenticator.feature.edititem.editItemDestination
import com.bitwarden.authenticator.ui.authenticator.feature.edititem.navigateToEditItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.itemListingGraph
import com.bitwarden.authenticator.ui.authenticator.feature.manualcodeentry.manualCodeEntryDestination
import com.bitwarden.authenticator.ui.authenticator.feature.manualcodeentry.navigateToManualCodeEntryScreen
import com.bitwarden.authenticator.ui.authenticator.feature.navbar.AuthenticatorNavbarRoute
import com.bitwarden.authenticator.ui.authenticator.feature.navbar.authenticatorNavBarDestination
import com.bitwarden.authenticator.ui.authenticator.feature.qrcodescan.navigateToQrCodeScanScreen
import com.bitwarden.authenticator.ui.authenticator.feature.qrcodescan.qrCodeScanDestination
import com.bitwarden.authenticator.ui.authenticator.feature.search.itemSearchDestination
import com.bitwarden.authenticator.ui.authenticator.feature.search.navigateToSearch
import com.bitwarden.authenticator.ui.platform.feature.settings.export.navigateToExport
import com.bitwarden.authenticator.ui.platform.feature.settings.importing.navigateToImporting
import com.bitwarden.authenticator.ui.platform.feature.tutorial.navigateToSettingsTutorial
import com.bitwarden.authenticator.ui.platform.feature.tutorial.tutorialSettingsDestination
import kotlinx.serialization.Serializable
/**
@@ -34,39 +39,41 @@ fun NavController.navigateToAuthenticatorGraph(navOptions: NavOptions? = null) {
*/
fun NavGraphBuilder.authenticatorGraph(
navController: NavController,
onNavigateBack: () -> Unit,
) {
navigation<AuthenticatorGraphRoute>(
startDestination = AuthenticatorNavbarRoute,
) {
authenticatorNavBarDestination(
onNavigateBack = onNavigateBack,
onNavigateBack = { navController.popBackStack() },
onNavigateToSearch = { navController.navigateToSearch() },
onNavigateToQrCodeScanner = { navController.navigateToQrCodeScanScreen() },
onNavigateToManualKeyEntry = { navController.navigateToManualCodeEntryScreen() },
onNavigateToEditItem = { navController.navigateToEditItem(itemId = it) },
onNavigateToExport = { navController.navigateToExport() },
onNavigateToImport = { navController.navigateToImporting() },
onNavigateToTutorial = { navController.navigateToSettingsTutorial() },
)
itemListingGraph(
navController = navController,
navigateBack = onNavigateBack,
navigateToSearch = {
navController.navigateToSearch()
},
navigateToQrCodeScanner = {
navController.navigateToQrCodeScanScreen()
},
navigateToManualKeyEntry = {
editItemDestination(
onNavigateBack = { navController.popBackStack() },
)
itemSearchDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToEdit = { navController.navigateToEditItem(itemId = it) },
)
qrCodeScanDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToManualCodeEntryScreen = {
navController.popBackStack()
navController.navigateToManualCodeEntryScreen()
},
navigateToEditItem = {
navController.navigateToEditItem(itemId = it)
)
manualCodeEntryDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToQrCodeScreen = {
navController.popBackStack()
navController.navigateToQrCodeScanScreen()
},
navigateToExport = { navController.navigateToExport() },
navigateToImport = { navController.navigateToImporting() },
navigateToTutorial = { navController.navigateToSettingsTutorial() },
)
tutorialSettingsDestination(
onTutorialFinished = { navController.popBackStack() },
)
}
}

View File

@@ -5,7 +5,7 @@ import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.toRoute
import com.bitwarden.ui.platform.base.util.composableWithPushTransitions
import com.bitwarden.ui.platform.base.util.composableWithSlideTransitions
import kotlinx.serialization.Serializable
/**
@@ -37,7 +37,7 @@ fun SavedStateHandle.toEditItemArgs(): EditItemArgs {
fun NavGraphBuilder.editItemDestination(
onNavigateBack: () -> Unit = { },
) {
composableWithPushTransitions<EditItemRoute> {
composableWithSlideTransitions<EditItemRoute> {
EditItemScreen(
onNavigateBack = onNavigateBack,
)

View File

@@ -4,13 +4,6 @@ import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.navigation
import com.bitwarden.authenticator.ui.authenticator.feature.edititem.editItemDestination
import com.bitwarden.authenticator.ui.authenticator.feature.manualcodeentry.manualCodeEntryDestination
import com.bitwarden.authenticator.ui.authenticator.feature.manualcodeentry.navigateToManualCodeEntryScreen
import com.bitwarden.authenticator.ui.authenticator.feature.qrcodescan.navigateToQrCodeScanScreen
import com.bitwarden.authenticator.ui.authenticator.feature.qrcodescan.qrCodeScanDestination
import com.bitwarden.authenticator.ui.authenticator.feature.search.itemSearchDestination
import com.bitwarden.authenticator.ui.platform.feature.settings.settingsGraph
import kotlinx.serialization.Serializable
/**
@@ -22,54 +15,22 @@ data object ItemListingGraphRoute
/**
* Add the item listing graph to the nav graph.
*/
@Suppress("LongParameterList")
fun NavGraphBuilder.itemListingGraph(
navController: NavController,
navigateBack: () -> Unit,
navigateToSearch: () -> Unit,
navigateToQrCodeScanner: () -> Unit,
navigateToManualKeyEntry: () -> Unit,
navigateToEditItem: (String) -> Unit,
navigateToExport: () -> Unit,
navigateToImport: () -> Unit,
navigateToTutorial: () -> Unit,
onNavigateBack: () -> Unit,
onNavigateToSearch: () -> Unit,
onNavigateToQrCodeScanner: () -> Unit,
onNavigateToManualKeyEntry: () -> Unit,
onNavigateToEditItem: (String) -> Unit,
) {
navigation<ItemListingGraphRoute>(
startDestination = ItemListingRoute,
) {
itemListingDestination(
onNavigateBack = navigateBack,
onNavigateToSearch = navigateToSearch,
onNavigateToQrCodeScanner = navigateToQrCodeScanner,
onNavigateToManualKeyEntry = navigateToManualKeyEntry,
onNavigateToEditItemScreen = navigateToEditItem,
)
editItemDestination(
onNavigateBack = { navController.popBackStack() },
)
itemSearchDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToEdit = navigateToEditItem,
)
qrCodeScanDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToManualCodeEntryScreen = {
navController.popBackStack()
navController.navigateToManualCodeEntryScreen()
},
)
manualCodeEntryDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToQrCodeScreen = {
navController.popBackStack()
navController.navigateToQrCodeScanScreen()
},
)
settingsGraph(
navController = navController,
onNavigateToExport = navigateToExport,
onNavigateToImport = navigateToImport,
onNavigateToTutorial = navigateToTutorial,
onNavigateBack = onNavigateBack,
onNavigateToSearch = onNavigateToSearch,
onNavigateToQrCodeScanner = onNavigateToQrCodeScanner,
onNavigateToManualKeyEntry = onNavigateToManualKeyEntry,
onNavigateToEditItemScreen = onNavigateToEditItem,
)
}
}

View File

@@ -1,7 +1,7 @@
package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting
import androidx.navigation.NavGraphBuilder
import com.bitwarden.ui.platform.base.util.composableWithPushTransitions
import com.bitwarden.ui.platform.base.util.composableWithRootPushTransitions
import kotlinx.serialization.Serializable
/**
@@ -20,7 +20,7 @@ fun NavGraphBuilder.itemListingDestination(
onNavigateToManualKeyEntry: () -> Unit = { },
onNavigateToEditItemScreen: (id: String) -> Unit = { },
) {
composableWithPushTransitions<ItemListingRoute> {
composableWithRootPushTransitions<ItemListingRoute> {
ItemListingScreen(
onNavigateBack = onNavigateBack,
onNavigateToSearch = onNavigateToSearch,

View File

@@ -20,8 +20,6 @@ fun NavGraphBuilder.authenticatorNavBarDestination(
onNavigateToQrCodeScanner: () -> Unit,
onNavigateToManualKeyEntry: () -> Unit,
onNavigateToEditItem: (itemId: String) -> Unit,
onNavigateToExport: () -> Unit,
onNavigateToImport: () -> Unit,
onNavigateToTutorial: () -> Unit,
) {
composableWithStayTransitions<AuthenticatorNavbarRoute> {
@@ -31,8 +29,6 @@ fun NavGraphBuilder.authenticatorNavBarDestination(
onNavigateToQrCodeScanner = onNavigateToQrCodeScanner,
onNavigateToManualKeyEntry = onNavigateToManualKeyEntry,
onNavigateToEditItem = onNavigateToEditItem,
onNavigateToExport = onNavigateToExport,
onNavigateToImport = onNavigateToImport,
onNavigateToTutorial = onNavigateToTutorial,
)
}

View File

@@ -2,7 +2,6 @@ package com.bitwarden.authenticator.ui.authenticator.feature.navbar
import android.os.Parcelable
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
@@ -11,22 +10,20 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.NavOptions
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.ItemListingGraphRoute
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.ItemListingRoute
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.itemListingGraph
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.navigateToItemListGraph
import com.bitwarden.authenticator.ui.platform.feature.settings.SettingsGraphRoute
import com.bitwarden.authenticator.ui.platform.feature.settings.SettingsRoute
import com.bitwarden.authenticator.ui.platform.feature.settings.navigateToSettingsGraph
import com.bitwarden.authenticator.ui.platform.feature.settings.export.navigateToExport
import com.bitwarden.authenticator.ui.platform.feature.settings.importing.navigateToImporting
import com.bitwarden.authenticator.ui.platform.feature.settings.settingsGraph
import com.bitwarden.ui.platform.base.util.EventsEffect
import com.bitwarden.ui.platform.base.util.navigateToTabOrRoot
import com.bitwarden.ui.platform.components.navigation.model.NavigationItem
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.scaffold.model.ScaffoldNavigationData
@@ -52,23 +49,10 @@ fun AuthenticatorNavBarScreen(
onNavigateToQrCodeScanner: () -> Unit,
onNavigateToManualKeyEntry: () -> Unit,
onNavigateToEditItem: (itemId: String) -> Unit,
onNavigateToExport: () -> Unit,
onNavigateToImport: () -> Unit,
onNavigateToTutorial: () -> Unit,
) {
EventsEffect(viewModel = viewModel) { event ->
navController.apply {
val navOptions = navController.authenticatorNavBarScreenNavOptions()
when (event) {
AuthenticatorNavBarEvent.NavigateToSettings -> {
navigateToSettingsGraph(navOptions)
}
AuthenticatorNavBarEvent.NavigateToVerificationCodes -> {
navigateToItemListGraph(navOptions)
}
}
}
navController.navigateToTabOrRoot(target = event.tab)
}
LaunchedEffect(Unit) {
@@ -93,13 +77,10 @@ fun AuthenticatorNavBarScreen(
navigateToQrCodeScanner = onNavigateToQrCodeScanner,
navigateToManualKeyEntry = onNavigateToManualKeyEntry,
navigateToEditItem = onNavigateToEditItem,
navigateToExport = onNavigateToExport,
navigateToImport = onNavigateToImport,
navigateToTutorial = onNavigateToTutorial,
onNavigateToTutorial = onNavigateToTutorial,
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun AuthenticatorNavBarScaffold(
navController: NavHostController,
@@ -110,9 +91,7 @@ private fun AuthenticatorNavBarScaffold(
navigateToQrCodeScanner: () -> Unit,
navigateToManualKeyEntry: () -> Unit,
navigateToEditItem: (itemId: String) -> Unit,
navigateToExport: () -> Unit,
navigateToImport: () -> Unit,
navigateToTutorial: () -> Unit,
onNavigateToTutorial: () -> Unit,
) {
var shouldDimNavBar by rememberSaveable { mutableStateOf(value = false) }
@@ -144,15 +123,17 @@ private fun AuthenticatorNavBarScaffold(
popExitTransition = RootTransitionProviders.Exit.fadeOut,
) {
itemListingGraph(
navController = navController,
navigateBack = navigateBack,
navigateToSearch = navigateToSearch,
navigateToQrCodeScanner = navigateToQrCodeScanner,
navigateToManualKeyEntry = navigateToManualKeyEntry,
navigateToEditItem = navigateToEditItem,
navigateToExport = navigateToExport,
navigateToImport = navigateToImport,
navigateToTutorial = navigateToTutorial,
onNavigateBack = navigateBack,
onNavigateToSearch = navigateToSearch,
onNavigateToQrCodeScanner = navigateToQrCodeScanner,
onNavigateToManualKeyEntry = navigateToManualKeyEntry,
onNavigateToEditItem = navigateToEditItem,
)
settingsGraph(
onNavigateBack = { navController.popBackStack() },
onNavigateToTutorial = onNavigateToTutorial,
onNavigateToExport = { navController.navigateToExport() },
onNavigateToImport = { navController.navigateToImporting() },
)
}
}
@@ -171,8 +152,9 @@ private fun AuthenticatorNavBarScaffold(
* @property iconResSelected The resource ID for the icon representing the tab when it's selected.
*/
@Parcelize
private sealed class AuthenticatorNavBarTab : NavigationItem, Parcelable {
sealed class AuthenticatorNavBarTab : NavigationItem, Parcelable {
@Suppress("UndocumentedPublicClass")
companion object {
/**
* The list of navigation tabs available in the authenticator.
@@ -214,18 +196,6 @@ private sealed class AuthenticatorNavBarTab : NavigationItem, Parcelable {
}
}
/**
* Helper function to generate [NavOptions] for [AuthenticatorNavBarScreen].
*/
private fun NavController.authenticatorNavBarScreenNavOptions(): NavOptions =
navOptions {
popUpTo(graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
/**
* Determine if the current destination is the same as the given tab.
*/

View File

@@ -46,15 +46,25 @@ class AuthenticatorNavBarViewModel @Inject constructor(
* Models events for the [AuthenticatorNavBarViewModel].
*/
sealed class AuthenticatorNavBarEvent {
/**
* The [AuthenticatorNavBarTab] to be associated with the event.
*/
abstract val tab: AuthenticatorNavBarTab
/**
* Navigate to the verification codes screen.
*/
data object NavigateToVerificationCodes : AuthenticatorNavBarEvent()
data object NavigateToVerificationCodes : AuthenticatorNavBarEvent() {
override val tab: AuthenticatorNavBarTab = AuthenticatorNavBarTab.VerificationCodes
}
/**
* Navigate to the settings screen.
*/
data object NavigateToSettings : AuthenticatorNavBarEvent()
data object NavigateToSettings : AuthenticatorNavBarEvent() {
override val tab: AuthenticatorNavBarTab = AuthenticatorNavBarTab.Settings
}
}
/**

View File

@@ -23,10 +23,13 @@ fun NavController.navigateToDebugMenuScreen() {
/**
* Add the setup unlock screen to the nav graph.
*/
fun NavGraphBuilder.setupDebugMenuDestination(
fun NavGraphBuilder.debugMenuDestination(
onNavigateBack: () -> Unit,
onSplashScreenRemoved: () -> Unit,
) {
composableWithPushTransitions<DebugRoute> {
DebugMenuScreen(onNavigateBack = onNavigateBack)
// If we are displaying the debug screen, then we can just hide the splash screen.
onSplashScreenRemoved()
}
}

View File

@@ -0,0 +1,25 @@
@file:OmitFromCoverage
package com.bitwarden.authenticator.ui.platform.feature.rootnav
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import com.bitwarden.annotation.OmitFromCoverage
import kotlinx.serialization.Serializable
/**
* The type-safe route for the root navigation screen.
*/
@Serializable
data object RootNavigationRoute
/**
* Add the root navigation screen to the nav graph.
*/
fun NavGraphBuilder.rootNavDestination(
onSplashScreenRemoved: () -> Unit,
) {
composable<RootNavigationRoute> {
RootNavScreen(onSplashScreenRemoved = onSplashScreenRemoved)
}
}

View File

@@ -19,7 +19,6 @@ import com.bitwarden.authenticator.ui.auth.unlock.unlockDestination
import com.bitwarden.authenticator.ui.authenticator.feature.authenticator.AuthenticatorGraphRoute
import com.bitwarden.authenticator.ui.authenticator.feature.authenticator.authenticatorGraph
import com.bitwarden.authenticator.ui.authenticator.feature.authenticator.navigateToAuthenticatorGraph
import com.bitwarden.authenticator.ui.platform.feature.debugmenu.setupDebugMenuDestination
import com.bitwarden.authenticator.ui.platform.feature.splash.SplashRoute
import com.bitwarden.authenticator.ui.platform.feature.splash.navigateToSplash
import com.bitwarden.authenticator.ui.platform.feature.splash.splashDestination
@@ -42,8 +41,7 @@ import java.util.concurrent.atomic.AtomicReference
fun RootNavScreen(
viewModel: RootNavViewModel = hiltViewModel(),
navController: NavHostController = rememberNavController(),
onSplashScreenRemoved: () -> Unit = {},
onExitApplication: () -> Unit,
onSplashScreenRemoved: () -> Unit,
) {
val state by viewModel.stateFlow.collectAsState()
val previousStateReference = remember { AtomicReference(state) }
@@ -82,15 +80,7 @@ fun RootNavScreen(
viewModel.trySendAction(RootNavAction.Internal.AppUnlocked)
},
)
setupDebugMenuDestination(
onNavigateBack = {
navController.popBackStack()
},
)
authenticatorGraph(
navController = navController,
onNavigateBack = onExitApplication,
)
authenticatorGraph(navController = navController)
}
val targetRoute = when (state.navState) {

View File

@@ -6,7 +6,6 @@ import androidx.navigation.NavOptions
import androidx.navigation.navigation
import com.bitwarden.authenticator.ui.platform.feature.settings.export.exportDestination
import com.bitwarden.authenticator.ui.platform.feature.settings.importing.importingDestination
import com.bitwarden.authenticator.ui.platform.feature.tutorial.tutorialSettingsDestination
import com.bitwarden.ui.platform.base.util.composableWithRootPushTransitions
import kotlinx.serialization.Serializable
@@ -23,32 +22,44 @@ data object SettingsGraphRoute
data object SettingsRoute
/**
* Add settings graph to the nav graph.
* Add settings destination to the nav graph.
*/
fun NavGraphBuilder.settingsGraph(
navController: NavController,
fun NavGraphBuilder.settingsDestination(
onNavigateToExport: () -> Unit,
onNavigateToImport: () -> Unit,
onNavigateToTutorial: () -> Unit,
) {
composableWithRootPushTransitions<SettingsRoute> {
SettingsScreen(
onNavigateToTutorial = onNavigateToTutorial,
onNavigateToExport = onNavigateToExport,
onNavigateToImport = onNavigateToImport,
)
}
}
/**
* Add settings graph to the nav graph.
*/
fun NavGraphBuilder.settingsGraph(
onNavigateBack: () -> Unit,
onNavigateToTutorial: () -> Unit,
onNavigateToExport: () -> Unit,
onNavigateToImport: () -> Unit,
) {
navigation<SettingsGraphRoute>(
startDestination = SettingsRoute,
) {
composableWithRootPushTransitions<SettingsRoute> {
SettingsScreen(
onNavigateToTutorial = onNavigateToTutorial,
onNavigateToExport = onNavigateToExport,
onNavigateToImport = onNavigateToImport,
)
}
tutorialSettingsDestination(
onTutorialFinished = { navController.popBackStack() },
settingsDestination(
onNavigateToTutorial = onNavigateToTutorial,
onNavigateToExport = onNavigateToExport,
onNavigateToImport = onNavigateToImport,
)
exportDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateBack = onNavigateBack,
)
importingDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateBack = onNavigateBack,
)
}
}

View File

@@ -57,6 +57,7 @@ import com.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow
import com.bitwarden.ui.platform.components.row.BitwardenPushRow
import com.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch
@@ -333,37 +334,21 @@ private fun ColumnScope.VaultSettings(
label = stringResource(id = BitwardenString.data),
)
Spacer(modifier = Modifier.height(height = 8.dp))
BitwardenTextRow(
BitwardenPushRow(
text = stringResource(id = BitwardenString.import_vault),
onClick = onImportClick,
cardStyle = CardStyle.Top(),
modifier = Modifier
.standardHorizontalMargin()
.testTag("Import"),
cardStyle = CardStyle.Top(),
content = {
Icon(
modifier = Modifier.mirrorIfRtl(),
painter = painterResource(id = BitwardenDrawable.ic_chevron_right),
contentDescription = null,
tint = BitwardenTheme.colorScheme.icon.primary,
)
},
)
BitwardenTextRow(
BitwardenPushRow(
text = stringResource(id = BitwardenString.export),
onClick = onExportClick,
cardStyle = CardStyle.Middle(),
modifier = Modifier
.standardHorizontalMargin()
.testTag("Export"),
cardStyle = CardStyle.Middle(),
content = {
Icon(
modifier = Modifier.mirrorIfRtl(),
painter = painterResource(id = BitwardenDrawable.ic_chevron_right),
contentDescription = null,
tint = BitwardenTheme.colorScheme.icon.primary,
)
},
)
BitwardenExternalLinkRow(
text = stringResource(BitwardenString.backup),

View File

@@ -3,7 +3,7 @@ package com.bitwarden.authenticator.ui.platform.feature.settings.export
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import com.bitwarden.ui.platform.base.util.composableWithSlideTransitions
import com.bitwarden.ui.platform.base.util.composableWithPushTransitions
import kotlinx.serialization.Serializable
/**
@@ -18,7 +18,7 @@ data object ExportRoute
fun NavGraphBuilder.exportDestination(
onNavigateBack: () -> Unit,
) {
composableWithSlideTransitions<ExportRoute> {
composableWithPushTransitions<ExportRoute> {
ExportScreen(
onNavigateBack = onNavigateBack,
)

View File

@@ -139,8 +139,8 @@ fun ExportScreen(
BitwardenTopAppBar(
title = stringResource(id = BitwardenString.export),
scrollBehavior = scrollBehavior,
navigationIcon = painterResource(id = BitwardenDrawable.ic_close),
navigationIconContentDescription = stringResource(id = BitwardenString.close),
navigationIcon = painterResource(id = BitwardenDrawable.ic_back),
navigationIconContentDescription = stringResource(id = BitwardenString.back),
onNavigationIconClick = remember(viewModel) {
{
viewModel.trySendAction(ExportAction.CloseButtonClick)

View File

@@ -3,7 +3,7 @@ package com.bitwarden.authenticator.ui.platform.feature.settings.importing
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import com.bitwarden.ui.platform.base.util.composableWithSlideTransitions
import com.bitwarden.ui.platform.base.util.composableWithPushTransitions
import kotlinx.serialization.Serializable
/**
@@ -18,7 +18,7 @@ data object ImportRoute
fun NavGraphBuilder.importingDestination(
onNavigateBack: () -> Unit,
) {
composableWithSlideTransitions<ImportRoute> {
composableWithPushTransitions<ImportRoute> {
ImportingScreen(
onNavigateBack = onNavigateBack,
)

View File

@@ -123,8 +123,8 @@ fun ImportingScreen(
BitwardenTopAppBar(
title = stringResource(id = BitwardenString.import_vault),
scrollBehavior = scrollBehavior,
navigationIcon = painterResource(id = BitwardenDrawable.ic_close),
navigationIconContentDescription = stringResource(id = BitwardenString.close),
navigationIcon = painterResource(id = BitwardenDrawable.ic_back),
navigationIconContentDescription = stringResource(id = BitwardenString.back),
onNavigationIconClick = remember(viewModel) {
{
viewModel.trySendAction(ImportAction.CloseButtonClick)

View File

@@ -3,7 +3,8 @@ package com.bitwarden.authenticator.ui.platform.feature.tutorial
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.bitwarden.ui.platform.base.util.composableWithSlideTransitions
import com.bitwarden.ui.platform.base.util.composableWithStayTransitions
import kotlinx.serialization.Serializable
/**
@@ -22,7 +23,7 @@ data object SettingsTutorialRoute
* Add the top level Tutorial screen to the nav graph.
*/
fun NavGraphBuilder.tutorialDestination(onTutorialFinished: () -> Unit) {
composable<TutorialRoute> {
composableWithStayTransitions<TutorialRoute> {
TutorialScreen(
onTutorialFinished = onTutorialFinished,
)
@@ -33,7 +34,7 @@ fun NavGraphBuilder.tutorialDestination(onTutorialFinished: () -> Unit) {
* Add the Settings Tutorial screen to the nav graph.
*/
fun NavGraphBuilder.tutorialSettingsDestination(onTutorialFinished: () -> Unit) {
composable<SettingsTutorialRoute> {
composableWithSlideTransitions<SettingsTutorialRoute> {
TutorialScreen(
onTutorialFinished = onTutorialFinished,
)

View File

@@ -7,6 +7,8 @@
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionModeOverlay">true</item>
<item name="android:windowLayoutInDisplayCutoutMode">default</item>
<item name="android:backgroundDimAmount">@dimen/dialogDimBackgroundAmount</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<!-- Launch theme (for auto dark/light based on system) -->