mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 00:06:22 -06:00
PM-27703: Update Authenticator navigation (#6109)
This commit is contained in:
parent
b1195b5f46
commit
845a5dec22
@ -36,7 +36,7 @@ import com.x8bit.bitwarden.ui.platform.composition.LocalManagerProvider
|
||||
import com.x8bit.bitwarden.ui.platform.feature.debugmenu.debugMenuDestination
|
||||
import com.x8bit.bitwarden.ui.platform.feature.debugmenu.manager.DebugMenuLaunchManager
|
||||
import com.x8bit.bitwarden.ui.platform.feature.debugmenu.navigateToDebugMenuScreen
|
||||
import com.x8bit.bitwarden.ui.platform.feature.rootnav.ROOT_ROUTE
|
||||
import com.x8bit.bitwarden.ui.platform.feature.rootnav.RootNavigationRoute
|
||||
import com.x8bit.bitwarden.ui.platform.feature.rootnav.rootNavDestination
|
||||
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage
|
||||
import com.x8bit.bitwarden.ui.platform.model.AuthTabLaunchers
|
||||
@ -119,11 +119,11 @@ class MainActivity : AppCompatActivity() {
|
||||
) {
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = ROOT_ROUTE,
|
||||
startDestination = RootNavigationRoute,
|
||||
) {
|
||||
// Nothing else should end up at this top level, we just want the ability
|
||||
// to have the debug menu appear on top of the rest of the app without
|
||||
// interacting with the state-based navigation used by the RootNavScreen.
|
||||
// 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() },
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
@file:OmitFromCoverage
|
||||
|
||||
package com.x8bit.bitwarden.ui.platform.feature.rootnav
|
||||
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
import com.bitwarden.annotation.OmitFromCoverage
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* The route for the root navigation screen.
|
||||
* The type-safe route for the root navigation screen.
|
||||
*/
|
||||
const val ROOT_ROUTE: String = "root"
|
||||
@Serializable
|
||||
data object RootNavigationRoute
|
||||
|
||||
/**
|
||||
* Add the root navigation screen to the nav graph.
|
||||
@ -14,7 +19,7 @@ const val ROOT_ROUTE: String = "root"
|
||||
fun NavGraphBuilder.rootNavDestination(
|
||||
onSplashScreenRemoved: () -> Unit,
|
||||
) {
|
||||
composable(route = ROOT_ROUTE) {
|
||||
composable<RootNavigationRoute> {
|
||||
RootNavScreen(onSplashScreenRemoved = onSplashScreenRemoved)
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,15 +11,12 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavBackStackEntry
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||
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.navOptions
|
||||
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
|
||||
@ -29,21 +26,17 @@ import com.x8bit.bitwarden.ui.platform.components.util.rememberBitwardenNavContr
|
||||
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
|
||||
import com.x8bit.bitwarden.ui.platform.feature.settings.about.navigateToAbout
|
||||
import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.navigateToAutoFill
|
||||
import com.x8bit.bitwarden.ui.platform.feature.settings.navigateToSettingsGraph
|
||||
import com.x8bit.bitwarden.ui.platform.feature.settings.navigateToSettingsGraphRoot
|
||||
import com.x8bit.bitwarden.ui.platform.feature.settings.settingsGraph
|
||||
import com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar.model.VaultUnlockedNavBarTab
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.generatorGraph
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.navigateToGeneratorGraph
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.navigateToSendGraph
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.sendGraph
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
|
||||
import com.x8bit.bitwarden.ui.vault.feature.importitems.navigateToImportItemsScreen
|
||||
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemArgs
|
||||
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultGraphRoute
|
||||
import com.x8bit.bitwarden.ui.vault.feature.vault.navigateToVaultGraph
|
||||
import com.x8bit.bitwarden.ui.vault.feature.vault.vaultGraph
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@ -81,41 +74,7 @@ fun VaultUnlockedNavBarScreen(
|
||||
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
|
||||
|
||||
EventsEffect(viewModel = viewModel) { event ->
|
||||
navController.apply {
|
||||
when (event) {
|
||||
is VaultUnlockedNavBarEvent.Shortcut.NavigateToVaultScreen,
|
||||
is VaultUnlockedNavBarEvent.NavigateToVaultScreen,
|
||||
-> {
|
||||
navigateToTabOrRoot(tabToNavigateTo = event.tab) {
|
||||
navigateToVaultGraph(navOptions = it)
|
||||
}
|
||||
}
|
||||
|
||||
VaultUnlockedNavBarEvent.Shortcut.NavigateToSendScreen,
|
||||
VaultUnlockedNavBarEvent.NavigateToSendScreen,
|
||||
-> {
|
||||
navigateToTabOrRoot(tabToNavigateTo = event.tab) {
|
||||
navigateToSendGraph(navOptions = it)
|
||||
}
|
||||
}
|
||||
|
||||
VaultUnlockedNavBarEvent.Shortcut.NavigateToGeneratorScreen,
|
||||
VaultUnlockedNavBarEvent.NavigateToGeneratorScreen,
|
||||
-> {
|
||||
navigateToTabOrRoot(tabToNavigateTo = event.tab) {
|
||||
navigateToGeneratorGraph(navOptions = it)
|
||||
}
|
||||
}
|
||||
|
||||
VaultUnlockedNavBarEvent.Shortcut.NavigateToSettingsScreen,
|
||||
VaultUnlockedNavBarEvent.NavigateToSettingsScreen,
|
||||
-> {
|
||||
navigateToTabOrRoot(tabToNavigateTo = event.tab) {
|
||||
navigateToSettingsGraph(navOptions = it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
navController.navigateToTabOrRoot(target = event.tab)
|
||||
}
|
||||
|
||||
VaultUnlockedNavBarScaffold(
|
||||
@ -279,37 +238,6 @@ private fun VaultUnlockedNavBarScaffold(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to determine how to navigate to a specified [VaultUnlockedNavBarTab].
|
||||
* If direct navigation is required, the [navigate] lambda will be invoked with the appropriate
|
||||
* [NavOptions].
|
||||
*/
|
||||
@Suppress("MaxLineLength")
|
||||
private fun NavController.navigateToTabOrRoot(
|
||||
tabToNavigateTo: VaultUnlockedNavBarTab,
|
||||
navigate: (NavOptions) -> Unit,
|
||||
) {
|
||||
if (tabToNavigateTo.startDestinationRoute.toObjectNavigationRoute() == currentDestination?.route) {
|
||||
// We are at the start destination already, so nothing to do.
|
||||
return
|
||||
} else if (currentDestination?.parent?.route == tabToNavigateTo.graphRoute.toObjectNavigationRoute()) {
|
||||
// We are not at the start destination but we are in the correct graph,
|
||||
// so lets pop up to the start destination.
|
||||
popBackStack(route = tabToNavigateTo.startDestinationRoute, inclusive = false)
|
||||
} else {
|
||||
// We are not in correct graph at all, so navigate there.
|
||||
navigate(
|
||||
navOptions {
|
||||
popUpTo(id = graph.findStartDestination().id) {
|
||||
saveState = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the current destination is the same as the given tab.
|
||||
*/
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="dialogDimBackgroundAmount" format="float">0.75</dimen>
|
||||
<color name="windowBackground">@android:color/transparent</color>
|
||||
</resources>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="dialogDimBackgroundAmount" format="float">0.55</dimen>
|
||||
<!-- default -->
|
||||
<integer name="displayCutoutMode">0</integer>
|
||||
<color name="windowBackground">@android:color/transparent</color>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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() },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
)
|
||||
|
||||
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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,
|
||||
)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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,
|
||||
)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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,
|
||||
)
|
||||
|
||||
@ -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) -->
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package com.bitwarden.ui.platform.base.util
|
||||
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.navOptions
|
||||
import com.bitwarden.ui.platform.components.navigation.model.NavigationItem
|
||||
import com.bitwarden.ui.platform.util.toObjectNavigationRoute
|
||||
|
||||
/**
|
||||
* A helper function to determine how to navigate to a specified [NavigationItem].
|
||||
*
|
||||
* This function intelligently handles navigation based on the current destination:
|
||||
* - If already at the target start destination, no action is taken.
|
||||
* - If in the correct graph but not at start, pops back to start destination of the graph.
|
||||
* - Otherwise, navigates to the target graph with appropriate [NavOptions].
|
||||
*
|
||||
* @param target The [NavigationItem] representing the desired navigation target
|
||||
*/
|
||||
fun NavController.navigateToTabOrRoot(target: NavigationItem) {
|
||||
if (target.startDestinationRoute.toObjectNavigationRoute() == currentDestination?.route) {
|
||||
// We are at the start destination already, so nothing to do.
|
||||
return
|
||||
} else if (target.graphRoute.toObjectNavigationRoute() == currentDestination?.parent?.route) {
|
||||
// We are not at the start destination but we are in the correct graph,
|
||||
// so lets pop up to the start destination.
|
||||
popBackStack(route = target.startDestinationRoute, inclusive = false)
|
||||
return
|
||||
} else {
|
||||
// We are not in correct graph at all, so navigate there.
|
||||
navigate(
|
||||
route = target.graphRoute,
|
||||
navOptions = navOptions {
|
||||
popUpTo(id = graph.findStartDestination().id) {
|
||||
saveState = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
4
ui/src/main/res/values-night/values.xml
Normal file
4
ui/src/main/res/values-night/values.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="dialogDimBackgroundAmount">0.75</dimen>
|
||||
</resources>
|
||||
4
ui/src/main/res/values/values.xml
Normal file
4
ui/src/main/res/values/values.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="dialogDimBackgroundAmount">0.55</dimen>
|
||||
</resources>
|
||||
Loading…
x
Reference in New Issue
Block a user