mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
PM-8522: Fix vault tab nav bar title when logging in (#3710)
Some checks failed
Crowdin Push / Crowdin Push (push) Waiting to run
Scan / Check PR run (push) Failing after 0s
Scan / SAST scan (push) Has been skipped
Scan / Quality scan (push) Has been skipped
Test / Check PR run (push) Failing after 0s
Test / Test (push) Has been skipped
Some checks failed
Crowdin Push / Crowdin Push (push) Waiting to run
Scan / Check PR run (push) Failing after 0s
Scan / SAST scan (push) Has been skipped
Scan / Quality scan (push) Has been skipped
Test / Check PR run (push) Failing after 0s
Test / Test (push) Has been skipped
This commit is contained in:
parent
551f948644
commit
e3371b7620
2 changed files with 99 additions and 44 deletions
|
@ -1,12 +1,17 @@
|
|||
package com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.update
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -14,25 +19,22 @@ import javax.inject.Inject
|
|||
*/
|
||||
@HiltViewModel
|
||||
class VaultUnlockedNavBarViewModel @Inject constructor(
|
||||
private val authRepository: AuthRepository,
|
||||
authRepository: AuthRepository,
|
||||
specialCircumstancesManager: SpecialCircumstanceManager,
|
||||
) : BaseViewModel<VaultUnlockedNavBarState, VaultUnlockedNavBarEvent, VaultUnlockedNavBarAction>(
|
||||
initialState = run {
|
||||
val hasOrganization = authRepository
|
||||
.userStateFlow
|
||||
.value
|
||||
?.activeAccount
|
||||
?.organizations
|
||||
?.isNotEmpty()
|
||||
?: false
|
||||
val vaultRes = if (hasOrganization) R.string.vaults else R.string.my_vault
|
||||
VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = vaultRes,
|
||||
vaultNavBarContentDescriptionRes = vaultRes,
|
||||
)
|
||||
},
|
||||
initialState = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = R.string.my_vault,
|
||||
vaultNavBarContentDescriptionRes = R.string.my_vault,
|
||||
),
|
||||
) {
|
||||
init {
|
||||
authRepository
|
||||
.userStateFlow
|
||||
.onEach {
|
||||
sendAction(VaultUnlockedNavBarAction.Internal.UserStateUpdateReceive(it))
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
when (specialCircumstancesManager.specialCircumstance) {
|
||||
SpecialCircumstance.GeneratorShortcut -> {
|
||||
sendEvent(VaultUnlockedNavBarEvent.NavigateToGeneratorScreen)
|
||||
|
@ -54,6 +56,15 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
|
|||
VaultUnlockedNavBarAction.SendTabClick -> handleSendTabClicked()
|
||||
VaultUnlockedNavBarAction.SettingsTabClick -> handleSettingsTabClicked()
|
||||
VaultUnlockedNavBarAction.VaultTabClick -> handleVaultTabClicked()
|
||||
is VaultUnlockedNavBarAction.Internal -> handleInternalAction(action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleInternalAction(action: VaultUnlockedNavBarAction.Internal) {
|
||||
when (action) {
|
||||
is VaultUnlockedNavBarAction.Internal.UserStateUpdateReceive -> {
|
||||
handleUserStateUpdateReceive(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
// #region BottomTabViewModel Action Handlers
|
||||
|
@ -84,6 +95,27 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
|
|||
private fun handleSettingsTabClicked() {
|
||||
sendEvent(VaultUnlockedNavBarEvent.NavigateToSettingsScreen)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the nav bar title according to whether the user is part of any organizations or not.
|
||||
*/
|
||||
private fun handleUserStateUpdateReceive(
|
||||
action: VaultUnlockedNavBarAction.Internal.UserStateUpdateReceive,
|
||||
) {
|
||||
val hasOrganizations = action
|
||||
.userState
|
||||
?.activeAccount
|
||||
?.organizations
|
||||
?.isNotEmpty()
|
||||
?: false
|
||||
val vaultRes = if (hasOrganizations) R.string.vaults else R.string.my_vault
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
vaultNavBarLabelRes = vaultRes,
|
||||
vaultNavBarContentDescriptionRes = vaultRes,
|
||||
)
|
||||
}
|
||||
}
|
||||
// #endregion BottomTabViewModel Action Handlers
|
||||
}
|
||||
|
||||
|
@ -100,24 +132,36 @@ data class VaultUnlockedNavBarState(
|
|||
*/
|
||||
sealed class VaultUnlockedNavBarAction {
|
||||
/**
|
||||
* click Generator tab.
|
||||
* Click Generator tab.
|
||||
*/
|
||||
data object GeneratorTabClick : VaultUnlockedNavBarAction()
|
||||
|
||||
/**
|
||||
* click Send tab.
|
||||
* Click Send tab.
|
||||
*/
|
||||
data object SendTabClick : VaultUnlockedNavBarAction()
|
||||
|
||||
/**
|
||||
* click Vault tab.
|
||||
* Click Vault tab.
|
||||
*/
|
||||
data object VaultTabClick : VaultUnlockedNavBarAction()
|
||||
|
||||
/**
|
||||
* click Settings tab.
|
||||
* Click Settings tab.
|
||||
*/
|
||||
data object SettingsTabClick : VaultUnlockedNavBarAction()
|
||||
|
||||
/**
|
||||
* Models actions that the [VaultUnlockedNavBarViewModel] itself might send.
|
||||
*/
|
||||
sealed class Internal : VaultUnlockedNavBarAction() {
|
||||
/**
|
||||
* Indicates a change in user state has been received.
|
||||
*/
|
||||
data class UserStateUpdateReceive(
|
||||
val userState: UserState?,
|
||||
) : Internal()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -83,41 +83,52 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `on init with no organizations should set correct vault label res`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
val expected = VaultUnlockedNavBarState(
|
||||
fun `new user state should update vault nav bar title`() = runTest {
|
||||
val activeUserId = "activeUserId"
|
||||
val accountWithOrganizations: UserState.Account = mockk {
|
||||
every { userId } returns activeUserId
|
||||
every { organizations } returns listOf(mockk())
|
||||
}
|
||||
val expectedWithOrganizations = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = R.string.vaults,
|
||||
vaultNavBarContentDescriptionRes = R.string.vaults,
|
||||
)
|
||||
val accountWithoutOrganizations: UserState.Account = mockk {
|
||||
every { userId } returns activeUserId
|
||||
every { organizations } returns emptyList()
|
||||
}
|
||||
val expectedWithoutOrganizations = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = R.string.my_vault,
|
||||
vaultNavBarContentDescriptionRes = R.string.my_vault,
|
||||
)
|
||||
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(
|
||||
expected,
|
||||
expectedWithoutOrganizations,
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on init with organizations should set correct vault label res`() = runTest {
|
||||
val activeUserId = "activeUserId"
|
||||
val account: UserState.Account = mockk {
|
||||
every { userId } returns activeUserId
|
||||
every { organizations } returns listOf(mockk())
|
||||
}
|
||||
mutableUserStateFlow.value = UserState(
|
||||
mutableUserStateFlow.tryEmit(
|
||||
UserState(
|
||||
activeUserId = activeUserId,
|
||||
accounts = listOf(account),
|
||||
accounts = listOf(accountWithOrganizations),
|
||||
),
|
||||
)
|
||||
val viewModel = createViewModel()
|
||||
val expected = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = R.string.vaults,
|
||||
vaultNavBarContentDescriptionRes = R.string.vaults,
|
||||
assertEquals(
|
||||
expectedWithOrganizations,
|
||||
awaitItem(),
|
||||
)
|
||||
|
||||
viewModel.stateFlow.test {
|
||||
mutableUserStateFlow.tryEmit(
|
||||
UserState(
|
||||
activeUserId = activeUserId,
|
||||
accounts = listOf(accountWithoutOrganizations),
|
||||
),
|
||||
)
|
||||
assertEquals(
|
||||
expected,
|
||||
expectedWithoutOrganizations,
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue