mirror of
https://github.com/bitwarden/android.git
synced 2026-05-20 19:11:33 -05:00
PM-37705: Hide Send navigation when DISABLE_SEND policy is enabled
This commit is contained in:
@@ -14,6 +14,7 @@ import androidx.navigation.NavDestination.Companion.hierarchy
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import com.bitwarden.core.util.persistentListOfNotNull
|
||||
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
|
||||
@@ -37,7 +38,6 @@ import com.x8bit.bitwarden.ui.vault.feature.importitems.navigateToImportItemsScr
|
||||
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.vaultGraph
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* Top level composable for the Vault Unlocked Screen.
|
||||
@@ -159,9 +159,9 @@ private fun VaultUnlockedNavBarScaffold(
|
||||
// This scaffold will host screens that contain top bars while not hosting one itself.
|
||||
// We need to ignore the all insets here and let the content screens handle it themselves.
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val navigationItems = persistentListOf<NavigationItem>(
|
||||
val navigationItems = persistentListOfNotNull<NavigationItem>(
|
||||
VaultUnlockedNavBarTab.Vault(labelRes = state.vaultNavBarLabelRes),
|
||||
VaultUnlockedNavBarTab.Send,
|
||||
VaultUnlockedNavBarTab.Send.takeUnless { state.areSendsDisabled },
|
||||
VaultUnlockedNavBarTab.Generator,
|
||||
VaultUnlockedNavBarTab.Settings(state.notificationState.settingsTabNotificationCount),
|
||||
)
|
||||
|
||||
@@ -2,17 +2,20 @@ package com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.bitwarden.network.model.PolicyTypeJson
|
||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.bitwarden.ui.platform.base.DeferredBackgroundEvent
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
||||
import com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar.model.VaultUnlockedNavBarTab
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.update
|
||||
import javax.inject.Inject
|
||||
@@ -25,12 +28,16 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
|
||||
authRepository: AuthRepository,
|
||||
specialCircumstancesManager: SpecialCircumstanceManager,
|
||||
firstTimeActionManager: FirstTimeActionManager,
|
||||
policyManager: PolicyManager,
|
||||
) : BaseViewModel<VaultUnlockedNavBarState, VaultUnlockedNavBarEvent, VaultUnlockedNavBarAction>(
|
||||
initialState = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = BitwardenString.my_vault,
|
||||
notificationState = VaultUnlockedNavBarNotificationState(
|
||||
settingsTabNotificationCount = firstTimeActionManager.allSettingsBadgeCountFlow.value,
|
||||
),
|
||||
areSendsDisabled = policyManager
|
||||
.getActivePolicies(type = PolicyTypeJson.DISABLE_SEND)
|
||||
.any(),
|
||||
),
|
||||
) {
|
||||
init {
|
||||
@@ -48,6 +55,12 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
policyManager
|
||||
.getActivePoliciesFlow(type = PolicyTypeJson.DISABLE_SEND)
|
||||
.map { VaultUnlockedNavBarAction.Internal.SendPolicyUpdateReceive(it.any()) }
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
when (specialCircumstancesManager.specialCircumstance) {
|
||||
SpecialCircumstance.GeneratorShortcut -> {
|
||||
sendEvent(VaultUnlockedNavBarEvent.Shortcut.NavigateToGeneratorScreen)
|
||||
@@ -111,6 +124,10 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
|
||||
is VaultUnlockedNavBarAction.Internal.SettingsNotificationCountUpdate -> {
|
||||
handleSettingsNotificationCountUpdate(action)
|
||||
}
|
||||
|
||||
is VaultUnlockedNavBarAction.Internal.SendPolicyUpdateReceive -> {
|
||||
handleSendPolicyUpdateReceive(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
// #region BottomTabViewModel Action Handlers
|
||||
@@ -175,6 +192,12 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSendPolicyUpdateReceive(
|
||||
action: VaultUnlockedNavBarAction.Internal.SendPolicyUpdateReceive,
|
||||
) {
|
||||
mutableStateFlow.update { it.copy(areSendsDisabled = action.hasPolicy) }
|
||||
}
|
||||
// #endregion BottomTabViewModel Action Handlers
|
||||
}
|
||||
|
||||
@@ -184,6 +207,7 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
|
||||
data class VaultUnlockedNavBarState(
|
||||
@field:StringRes val vaultNavBarLabelRes: Int,
|
||||
val notificationState: VaultUnlockedNavBarNotificationState,
|
||||
val areSendsDisabled: Boolean,
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -230,6 +254,11 @@ sealed class VaultUnlockedNavBarAction {
|
||||
* Indicates a change to the count of settings notifications to show
|
||||
*/
|
||||
data class SettingsNotificationCountUpdate(val count: Int) : Internal()
|
||||
|
||||
/**
|
||||
* Indicates a change to the count of settings notifications to show
|
||||
*/
|
||||
data class SendPolicyUpdateReceive(val hasPolicy: Boolean) : Internal()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,6 +193,7 @@ class VaultUnlockedNavBarScreenTest : BitwardenComposeTest() {
|
||||
notificationState = VaultUnlockedNavBarNotificationState(
|
||||
settingsTabNotificationCount = 0,
|
||||
),
|
||||
areSendsDisabled = false,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -200,6 +201,15 @@ class VaultUnlockedNavBarScreenTest : BitwardenComposeTest() {
|
||||
composeTestRule.onNodeWithText(text = "Vaults").assertExists()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `send tab should be hidden when areSendsDisabled is true`() {
|
||||
composeTestRule.onNodeWithText(text = "Send").assertExists()
|
||||
|
||||
mutableStateFlow.update { it.copy(areSendsDisabled = true) }
|
||||
|
||||
composeTestRule.onNodeWithText(text = "Send").assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `settings tab notification count should update according to state and show correct count`() {
|
||||
@@ -232,4 +242,5 @@ private val DEFAULT_STATE = VaultUnlockedNavBarState(
|
||||
notificationState = VaultUnlockedNavBarNotificationState(
|
||||
settingsTabNotificationCount = 0,
|
||||
),
|
||||
areSendsDisabled = false,
|
||||
)
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar
|
||||
|
||||
import app.cash.turbine.test
|
||||
import com.bitwarden.network.model.PolicyTypeJson
|
||||
import com.bitwarden.network.model.SyncResponseJson
|
||||
import com.bitwarden.network.model.createMockPolicy
|
||||
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
||||
import io.mockk.every
|
||||
@@ -32,6 +36,16 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
|
||||
private val firstTimeActionManager: FirstTimeActionManager = mockk {
|
||||
every { allSettingsBadgeCountFlow } returns mutableSettingsBadgeCountFlow
|
||||
}
|
||||
private val mutableDisableSendsPolicyFlow =
|
||||
MutableStateFlow<List<SyncResponseJson.Policy>>(emptyList())
|
||||
private val policyManager: PolicyManager = mockk {
|
||||
every {
|
||||
getActivePoliciesFlow(PolicyTypeJson.DISABLE_SEND)
|
||||
} returns mutableDisableSendsPolicyFlow
|
||||
every {
|
||||
getActivePolicies(PolicyTypeJson.DISABLE_SEND)
|
||||
} answers { mutableDisableSendsPolicyFlow.value }
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
@@ -127,6 +141,7 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
|
||||
val expectedWithOrganizations = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = BitwardenString.vaults,
|
||||
notificationState = DEFAULT_NOTIFICATION_STATE,
|
||||
areSendsDisabled = false,
|
||||
)
|
||||
val accountWithoutOrganizations: UserState.Account = mockk {
|
||||
every { userId } returns activeUserId
|
||||
@@ -135,6 +150,7 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
|
||||
val expectedWithoutOrganizations = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = BitwardenString.my_vault,
|
||||
notificationState = DEFAULT_NOTIFICATION_STATE,
|
||||
areSendsDisabled = false,
|
||||
)
|
||||
|
||||
val viewModel = createViewModel()
|
||||
@@ -311,11 +327,30 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `DISABLE_SEND policy flow update with disabled policy should set areSendsDisabled to false`() =
|
||||
runTest {
|
||||
val viewModel = createViewModel()
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(DEFAULT_STATE.copy(areSendsDisabled = false), awaitItem())
|
||||
|
||||
mutableDisableSendsPolicyFlow.emit(
|
||||
listOf(createMockPolicy(type = PolicyTypeJson.DISABLE_SEND)),
|
||||
)
|
||||
assertEquals(DEFAULT_STATE.copy(areSendsDisabled = true), awaitItem())
|
||||
|
||||
mutableDisableSendsPolicyFlow.emit(emptyList())
|
||||
assertEquals(DEFAULT_STATE.copy(areSendsDisabled = false), awaitItem())
|
||||
}
|
||||
}
|
||||
|
||||
private fun createViewModel() =
|
||||
VaultUnlockedNavBarViewModel(
|
||||
authRepository = authRepository,
|
||||
specialCircumstancesManager = specialCircumstancesManager,
|
||||
firstTimeActionManager = firstTimeActionManager,
|
||||
policyManager = policyManager,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -326,4 +361,5 @@ private val DEFAULT_NOTIFICATION_STATE = VaultUnlockedNavBarNotificationState(
|
||||
private val DEFAULT_STATE = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = BitwardenString.my_vault,
|
||||
notificationState = DEFAULT_NOTIFICATION_STATE,
|
||||
areSendsDisabled = false,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user