BIT-1899: Post root navigation calls to avoid visual defects on startup (#1009)

This commit is contained in:
Brian Yencho 2024-02-13 16:04:05 -06:00 committed by Álison Fernandes
parent 8cc25a57f0
commit 5bfa059cdb
2 changed files with 61 additions and 32 deletions

View file

@ -119,42 +119,50 @@ fun RootNavScreen(
restoreState = false
}
when (val currentState = state) {
RootNavState.Auth -> navController.navigateToAuthGraph(rootNavOptions)
RootNavState.ResetPassword -> navController.navigateToResetPasswordGraph(rootNavOptions)
RootNavState.Splash -> navController.navigateToSplash(rootNavOptions)
RootNavState.VaultLocked -> navController.navigateToVaultUnlock(rootNavOptions)
is RootNavState.VaultUnlocked -> navController.navigateToVaultUnlockedGraph(rootNavOptions)
RootNavState.VaultUnlockedForNewSend -> {
navController.navigateToVaultUnlock(rootNavOptions)
navController.navigateToAddSend(
sendAddType = AddSendType.AddItem,
navOptions = rootNavOptions,
// Use a LaunchedEffect to ensure we don't navigate too soon when the app first opens. This
// avoids a bug that first appeared in Compose Material3 1.2.0-rc01 that causes the initial
// transition to appear corrupted.
LaunchedEffect(state) {
when (val currentState = state) {
RootNavState.Auth -> navController.navigateToAuthGraph(rootNavOptions)
RootNavState.ResetPassword -> navController.navigateToResetPasswordGraph(rootNavOptions)
RootNavState.Splash -> navController.navigateToSplash(rootNavOptions)
RootNavState.VaultLocked -> navController.navigateToVaultUnlock(rootNavOptions)
is RootNavState.VaultUnlocked -> navController.navigateToVaultUnlockedGraph(
rootNavOptions,
)
}
is RootNavState.VaultUnlockedForAutofillSave -> {
navController.navigateToVaultUnlockedGraph(rootNavOptions)
navController.navigateToVaultAddEdit(
vaultAddEditType = VaultAddEditType.AddItem,
navOptions = rootNavOptions,
)
}
RootNavState.VaultUnlockedForNewSend -> {
navController.navigateToVaultUnlock(rootNavOptions)
navController.navigateToAddSend(
sendAddType = AddSendType.AddItem,
navOptions = rootNavOptions,
)
}
is RootNavState.VaultUnlockedForAutofillSelection -> {
navController.navigateToVaultUnlockedGraph(rootNavOptions)
navController.navigateToVaultItemListingAsRoot(
vaultItemListingType = currentState.type.toVaultItemListingType(),
navOptions = rootNavOptions,
)
}
is RootNavState.VaultUnlockedForAutofillSave -> {
navController.navigateToVaultUnlockedGraph(rootNavOptions)
navController.navigateToVaultAddEdit(
vaultAddEditType = VaultAddEditType.AddItem,
navOptions = rootNavOptions,
)
}
RootNavState.VaultUnlockedForAuthRequest -> {
navController.navigateToVaultUnlockedGraph(rootNavOptions)
navController.navigateToLoginApproval(
fingerprint = null,
navOptions = rootNavOptions,
)
is RootNavState.VaultUnlockedForAutofillSelection -> {
navController.navigateToVaultUnlockedGraph(rootNavOptions)
navController.navigateToVaultItemListingAsRoot(
vaultItemListingType = currentState.type.toVaultItemListingType(),
navOptions = rootNavOptions,
)
}
RootNavState.VaultUnlockedForAuthRequest -> {
navController.navigateToVaultUnlockedGraph(rootNavOptions)
navController.navigateToLoginApproval(
fingerprint = null,
navOptions = rootNavOptions,
)
}
}
}
}
@ -184,6 +192,8 @@ private fun AnimatedContentTransitionScope<NavBackStackEntry>.toEnterTransition(
when (targetState.destination.rootLevelRoute()) {
RESET_PASSWORD_ROUTE -> RootTransitionProviders.Enter.slideUp
else -> when (initialState.destination.rootLevelRoute()) {
// Disable transitions when coming from the splash screen
SPLASH_ROUTE -> RootTransitionProviders.Enter.none
// The RESET_PASSWORD_ROUTE animation should be stay but due to an issue when combining
// certain animations, we are just using a fadeIn instead.
RESET_PASSWORD_ROUTE -> RootTransitionProviders.Enter.fadeIn
@ -197,6 +207,8 @@ private fun AnimatedContentTransitionScope<NavBackStackEntry>.toEnterTransition(
@Suppress("MaxLineLength")
private fun AnimatedContentTransitionScope<NavBackStackEntry>.toExitTransition(): NonNullExitTransitionProvider =
when (initialState.destination.rootLevelRoute()) {
// Disable transitions when coming from the splash screen
SPLASH_ROUTE -> RootTransitionProviders.Exit.none
RESET_PASSWORD_ROUTE -> RootTransitionProviders.Exit.slideDown
else -> when (targetState.destination.rootLevelRoute()) {
RESET_PASSWORD_ROUTE -> RootTransitionProviders.Exit.stay

View file

@ -218,6 +218,13 @@ object RootTransitionProviders {
fadeIn(tween(DEFAULT_FADE_TRANSITION_TIME_MS))
}
/**
* There is no transition for the entering screen.
*/
val none: NonNullEnterTransitionProvider = {
EnterTransition.None
}
/**
* Slides the new screen in from the left of the screen.
*/
@ -284,6 +291,16 @@ object RootTransitionProviders {
fadeOut(tween(DEFAULT_FADE_TRANSITION_TIME_MS))
}
/**
* There is no transition for the exiting screen.
*
* Unlike the [stay] transition, this will immediately remove the outgoing screen even if
* there is an ongoing enter transition happening for the new screen.
*/
val none: NonNullExitTransitionProvider = {
ExitTransition.None
}
/**
* Slides the current screen out to the left of the screen.
*/