mirror of
https://github.com/bitwarden/android.git
synced 2026-03-12 05:04:17 -05:00
Update the Navigation component library (#5130)
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
// TODO: Add tests for this (PM-21252)
|
||||
@file:OmitFromCoverage
|
||||
|
||||
package com.x8bit.bitwarden.ui.platform.feature.rootnav
|
||||
|
||||
import androidx.activity.compose.LocalActivity
|
||||
@@ -13,6 +16,7 @@ import androidx.navigation.NavDestination
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.navOptions
|
||||
import com.bitwarden.core.annotation.OmitFromCoverage
|
||||
import com.x8bit.bitwarden.ui.auth.feature.accountsetup.SETUP_AUTO_FILL_AS_ROOT_ROUTE
|
||||
import com.x8bit.bitwarden.ui.auth.feature.accountsetup.SETUP_COMPLETE_ROUTE
|
||||
import com.x8bit.bitwarden.ui.auth.feature.accountsetup.SETUP_UNLOCK_AS_ROOT_ROUTE
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// TODO: Add tests for this (PM-21252)
|
||||
@file:OmitFromCoverage
|
||||
|
||||
package com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar
|
||||
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
@@ -19,6 +22,7 @@ import androidx.navigation.NavOptions
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.navOptions
|
||||
import com.bitwarden.core.annotation.OmitFromCoverage
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.NavigationItem
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.ScaffoldNavigationData
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
package com.x8bit.bitwarden.ui.platform.feature.rootnav
|
||||
|
||||
import androidx.navigation.navOptions
|
||||
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
|
||||
import com.x8bit.bitwarden.ui.platform.base.FakeNavHostController
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.time.ZoneOffset
|
||||
|
||||
class RootNavScreenTest : BaseComposeTest() {
|
||||
private val fakeNavHostController = FakeNavHostController()
|
||||
private val rootNavStateFlow = MutableStateFlow<RootNavState>(RootNavState.Splash)
|
||||
private val viewModel = mockk<RootNavViewModel> {
|
||||
every { eventFlow } returns emptyFlow()
|
||||
every { stateFlow } returns rootNavStateFlow
|
||||
}
|
||||
|
||||
private val expectedNavOptions = navOptions {
|
||||
// When changing root navigation state, pop everything else off the back stack:
|
||||
popUpTo(fakeNavHostController.graphId) {
|
||||
inclusive = false
|
||||
saveState = false
|
||||
}
|
||||
launchSingleTop = true
|
||||
restoreState = false
|
||||
}
|
||||
|
||||
private var isSplashScreenRemoved: Boolean = false
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
setContent {
|
||||
RootNavScreen(
|
||||
viewModel = viewModel,
|
||||
navController = fakeNavHostController,
|
||||
onSplashScreenRemoved = { isSplashScreenRemoved = true },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `initial route should be splash`() {
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertCurrentRoute("splash")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when root nav destination changes, navigation should follow`() = runTest {
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertCurrentRoute("splash")
|
||||
}
|
||||
assertFalse(isSplashScreenRemoved)
|
||||
|
||||
// Make sure navigating to Auth works as expected:
|
||||
rootNavStateFlow.value = RootNavState.Auth
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "auth_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
assertTrue(isSplashScreenRemoved)
|
||||
|
||||
// Make sure navigating to Auth with the welcome route works as expected:
|
||||
rootNavStateFlow.value = RootNavState.AuthWithWelcome
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "welcome",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to complete registration route works as expected:
|
||||
rootNavStateFlow.value = RootNavState.CompleteOngoingRegistration(
|
||||
email = "example@email.com",
|
||||
verificationToken = "verificationToken",
|
||||
fromEmail = true,
|
||||
timestamp = FIXED_CLOCK.millis(),
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "complete_registration/example@email.com/verificationToken/true",
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to expired registration link route works as expected:
|
||||
rootNavStateFlow.value = RootNavState.ExpiredRegistrationLink
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "expired_registration_link",
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault locked works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultLocked
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_unlock/STANDARD",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to reset password works as expected:
|
||||
rootNavStateFlow.value = RootNavState.ResetPassword
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "reset_password",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to set password works as expected:
|
||||
rootNavStateFlow.value = RootNavState.SetPassword
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "set_password",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to set password works as expected:
|
||||
rootNavStateFlow.value = RootNavState.TrustedDevice
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "trusted_device_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault unlocked works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultUnlocked(activeUserId = "userId")
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_unlocked_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault unlocked for new totp works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultUnlockedForNewTotp(activeUserId = "userId")
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_item_listing_as_root/login",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault unlocked for new sends works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultUnlockedForNewSend
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "add_send_item/add",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault unlocked for autofill save works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultUnlockedForAutofillSave(
|
||||
autofillSaveItem = mockk(),
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_add_edit_item/add",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault unlocked for autofill works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultUnlockedForAutofillSelection(
|
||||
activeUserId = "userId",
|
||||
type = AutofillSelectionData.Type.LOGIN,
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_item_listing_as_root/login",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault unlocked for Fido2Save works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultUnlockedForFido2Save(
|
||||
activeUserId = "activeUserId",
|
||||
fido2CreateCredentialRequest = mockk(),
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_item_listing_as_root/login",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault unlocked for Fido2Assertion works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultUnlockedForFido2Assertion(
|
||||
activeUserId = "activeUserId",
|
||||
fido2CredentialAssertionRequest = mockk(),
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_item_listing_as_root/login",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to vault unlocked for Fido2GetCredentials works as expected:
|
||||
rootNavStateFlow.value = RootNavState.VaultUnlockedForFido2GetCredentials(
|
||||
activeUserId = "activeUserId",
|
||||
fido2GetCredentialsRequest = mockk(),
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_item_listing_as_root/login",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to account lock setup works as expected:
|
||||
rootNavStateFlow.value = RootNavState.OnboardingAccountLockSetup
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "setup_unlock_as_root/true",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to account autofill setup works as expected:
|
||||
rootNavStateFlow.value = RootNavState.OnboardingAutoFillSetup
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "setup_auto_fill_as_root/true",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure navigating to account setup complete works as expected:
|
||||
rootNavStateFlow.value = RootNavState.OnboardingStepsComplete
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "setup_complete",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val FIXED_CLOCK: Clock = Clock.fixed(
|
||||
Instant.parse("2023-10-27T12:00:00Z"),
|
||||
ZoneOffset.UTC,
|
||||
)
|
||||
@@ -1,250 +0,0 @@
|
||||
package com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar
|
||||
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.navigation.navOptions
|
||||
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
|
||||
import com.x8bit.bitwarden.ui.platform.base.FakeNavHostController
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
|
||||
private val fakeNavHostController = FakeNavHostController()
|
||||
private val mutableEventFlow = bufferedMutableSharedFlow<VaultUnlockedNavBarEvent>()
|
||||
private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE)
|
||||
val viewModel = mockk<VaultUnlockedNavBarViewModel>(relaxed = true) {
|
||||
every { eventFlow } returns mutableEventFlow
|
||||
every { stateFlow } returns mutableStateFlow
|
||||
}
|
||||
|
||||
private val expectedNavOptions = navOptions {
|
||||
// When changing root navigation state, pop everything else off the back stack:
|
||||
popUpTo(fakeNavHostController.graphId) {
|
||||
inclusive = false
|
||||
saveState = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
composeTestRule.apply {
|
||||
setContent {
|
||||
VaultUnlockedNavBarScreen(
|
||||
viewModel = viewModel,
|
||||
navController = fakeNavHostController,
|
||||
onNavigateToVaultAddItem = {},
|
||||
onNavigateToVaultItem = {},
|
||||
onNavigateToVaultEditItem = {},
|
||||
onNavigateToAddSend = {},
|
||||
onNavigateToEditSend = {},
|
||||
onNavigateToDeleteAccount = {},
|
||||
onNavigateToExportVault = {},
|
||||
onNavigateToFolders = {},
|
||||
onNavigateToPasswordHistory = {},
|
||||
onNavigateToPendingRequests = {},
|
||||
onNavigateToSearchVault = {},
|
||||
onNavigateToSearchSend = {},
|
||||
onNavigateToSetupAutoFillScreen = {},
|
||||
onNavigateToSetupUnlockScreen = {},
|
||||
onNavigateToImportLogins = {},
|
||||
onNavigateToAddFolderScreen = {},
|
||||
onNavigateToFlightRecorder = {},
|
||||
onNavigateToRecordedLogs = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `vault tab click should send VaultTabClick action`() {
|
||||
composeTestRule.onNodeWithText("My vault").performClick()
|
||||
verify { viewModel.trySendAction(VaultUnlockedNavBarAction.VaultTabClick) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NavigateToVaultScreen should navigate to VaultScreen`() {
|
||||
mutableEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSendScreen)
|
||||
composeTestRule.runOnIdle { fakeNavHostController.assertCurrentRoute("send_graph") }
|
||||
mutableEventFlow.tryEmit(
|
||||
VaultUnlockedNavBarEvent.NavigateToVaultScreen(
|
||||
labelRes = R.string.my_vault,
|
||||
contentDescRes = R.string.my_vault,
|
||||
),
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NavigateToVaultScreen shortcut event should navigate to VaultScreen`() {
|
||||
mutableEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSendScreen)
|
||||
composeTestRule.runOnIdle { fakeNavHostController.assertCurrentRoute("send_graph") }
|
||||
mutableEventFlow.tryEmit(
|
||||
VaultUnlockedNavBarEvent.Shortcut.NavigateToVaultScreen(
|
||||
labelRes = R.string.my_vault,
|
||||
contentDescRes = R.string.my_vault,
|
||||
),
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "vault_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NavigateToSettingsScreen shortcut event should navigate to SettingsScreen`() {
|
||||
mutableEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSendScreen)
|
||||
composeTestRule.runOnIdle { fakeNavHostController.assertCurrentRoute("send_graph") }
|
||||
mutableEventFlow.tryEmit(
|
||||
VaultUnlockedNavBarEvent.Shortcut.NavigateToSettingsScreen,
|
||||
)
|
||||
composeTestRule.runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "settings_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `send tab click should send SendTabClick action`() {
|
||||
composeTestRule.onNodeWithText("Send").performClick()
|
||||
verify { viewModel.trySendAction(VaultUnlockedNavBarAction.SendTabClick) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NavigateToSendScreen should navigate to SendScreen`() {
|
||||
composeTestRule.apply {
|
||||
runOnIdle { fakeNavHostController.assertCurrentRoute("vault_graph") }
|
||||
mutableEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSendScreen)
|
||||
runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "send_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `generator tab click should send GeneratorTabClick action`() {
|
||||
composeTestRule.onNodeWithText("Generator").performClick()
|
||||
verify { viewModel.trySendAction(VaultUnlockedNavBarAction.GeneratorTabClick) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NavigateToGeneratorScreen should navigate to GeneratorScreen`() {
|
||||
composeTestRule.apply {
|
||||
runOnIdle { fakeNavHostController.assertCurrentRoute("vault_graph") }
|
||||
mutableEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToGeneratorScreen)
|
||||
runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "generator_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NavigateToGeneratorScreen shortcut event should navigate to GeneratorScreen`() {
|
||||
composeTestRule.apply {
|
||||
runOnIdle { fakeNavHostController.assertCurrentRoute("vault_graph") }
|
||||
mutableEventFlow.tryEmit(VaultUnlockedNavBarEvent.Shortcut.NavigateToGeneratorScreen)
|
||||
runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "generator_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `settings tab click should send SendTabClick action`() {
|
||||
composeTestRule.onNodeWithText("Settings").performClick()
|
||||
verify { viewModel.trySendAction(VaultUnlockedNavBarAction.SettingsTabClick) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NavigateToSettingsScreen should navigate to SettingsScreen`() {
|
||||
composeTestRule.apply {
|
||||
runOnIdle { fakeNavHostController.assertCurrentRoute("vault_graph") }
|
||||
mutableEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSettingsScreen)
|
||||
runOnIdle {
|
||||
fakeNavHostController.assertLastNavigation(
|
||||
route = "settings_graph",
|
||||
navOptions = expectedNavOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `vault nav bar should update according to state`() {
|
||||
composeTestRule.onNodeWithText("My vault").assertExists()
|
||||
composeTestRule.onNodeWithText("Vaults").assertDoesNotExist()
|
||||
|
||||
mutableStateFlow.tryEmit(
|
||||
VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = R.string.vaults,
|
||||
vaultNavBarContentDescriptionRes = R.string.vaults,
|
||||
notificationState = VaultUnlockedNavBarNotificationState(
|
||||
settingsTabNotificationCount = 0,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
composeTestRule.onNodeWithText("My vault").assertDoesNotExist()
|
||||
composeTestRule.onNodeWithText("Vaults").assertExists()
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `settings tab notification count should update according to state and show correct count`() {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
notificationState = VaultUnlockedNavBarNotificationState(
|
||||
settingsTabNotificationCount = 1,
|
||||
),
|
||||
)
|
||||
}
|
||||
composeTestRule
|
||||
.onNodeWithText("1", useUnmergedTree = true)
|
||||
.assertExists()
|
||||
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
notificationState = VaultUnlockedNavBarNotificationState(
|
||||
settingsTabNotificationCount = 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
composeTestRule
|
||||
.onNodeWithText("1", useUnmergedTree = true)
|
||||
.assertDoesNotExist()
|
||||
}
|
||||
}
|
||||
|
||||
private val DEFAULT_STATE = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = R.string.my_vault,
|
||||
vaultNavBarContentDescriptionRes = R.string.my_vault,
|
||||
notificationState = VaultUnlockedNavBarNotificationState(
|
||||
settingsTabNotificationCount = 0,
|
||||
),
|
||||
)
|
||||
@@ -18,7 +18,7 @@ androidxCore = "1.16.0"
|
||||
androidxCredentials = "1.5.0"
|
||||
androidxHiltNavigationCompose = "1.2.0"
|
||||
androidxLifecycle = "2.8.7"
|
||||
androidxNavigation = "2.8.0"
|
||||
androidxNavigation = "2.8.9"
|
||||
androidxRoom = "2.7.1"
|
||||
androidXSecurityCrypto = "1.1.0-alpha06"
|
||||
androidxSplash = "1.1.0-rc01"
|
||||
|
||||
Reference in New Issue
Block a user