mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 20:07:59 -06:00
Add navigation chevron for Import Items button (#6020)
This commit is contained in:
parent
912eba14d6
commit
318307c377
@ -8,9 +8,11 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
@ -24,6 +26,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bitwarden.ui.platform.base.util.EventsEffect
|
||||
import com.bitwarden.ui.platform.base.util.mirrorIfRtl
|
||||
import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
|
||||
import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
|
||||
import com.bitwarden.ui.platform.components.badge.NotificationBadge
|
||||
@ -37,6 +40,7 @@ import com.bitwarden.ui.platform.components.snackbar.model.rememberBitwardenSnac
|
||||
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
|
||||
/**
|
||||
* Displays the vault settings screen.
|
||||
@ -160,7 +164,18 @@ fun VaultSettingsScreen(
|
||||
.testTag("ImportItemsLinkItemView")
|
||||
.standardHorizontalMargin()
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
) {
|
||||
if (state.showImportItemsChevron) {
|
||||
Icon(
|
||||
painter = rememberVectorPainter(id = BitwardenDrawable.ic_chevron_right),
|
||||
contentDescription = null,
|
||||
tint = BitwardenTheme.colorScheme.icon.primary,
|
||||
modifier = Modifier
|
||||
.mirrorIfRtl()
|
||||
.size(size = 16.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(height = 16.dp))
|
||||
Spacer(modifier = Modifier.navigationBarsPadding())
|
||||
}
|
||||
|
||||
@ -30,6 +30,9 @@ class VaultSettingsViewModel @Inject constructor(
|
||||
val firstTimeState = firstTimeActionManager.currentOrDefaultUserFirstTimeState
|
||||
VaultSettingsState(
|
||||
showImportActionCard = firstTimeState.showImportLoginsCardInSettings,
|
||||
showImportItemsChevron = featureFlagManager.getFeatureFlag(
|
||||
key = FlagKey.CredentialExchangeProtocolImport,
|
||||
),
|
||||
)
|
||||
},
|
||||
) {
|
||||
@ -49,6 +52,12 @@ class VaultSettingsViewModel @Inject constructor(
|
||||
.map { VaultSettingsAction.Internal.SnackbarDataReceived(it) }
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
featureFlagManager
|
||||
.getFeatureFlagFlow(key = FlagKey.CredentialExchangeProtocolImport)
|
||||
.map { VaultSettingsAction.Internal.ImportFeatureUpdated(it) }
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
override fun handleAction(action: VaultSettingsAction): Unit = when (action) {
|
||||
@ -70,6 +79,10 @@ class VaultSettingsViewModel @Inject constructor(
|
||||
is VaultSettingsAction.Internal.SnackbarDataReceived -> {
|
||||
handleSnackbarDataReceived(action)
|
||||
}
|
||||
|
||||
is VaultSettingsAction.Internal.ImportFeatureUpdated -> {
|
||||
handleImportFeatureUpdated(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,6 +92,12 @@ class VaultSettingsViewModel @Inject constructor(
|
||||
sendEvent(VaultSettingsEvent.ShowSnackbar(action.data))
|
||||
}
|
||||
|
||||
private fun handleImportFeatureUpdated(
|
||||
action: VaultSettingsAction.Internal.ImportFeatureUpdated,
|
||||
) {
|
||||
mutableStateFlow.update { it.copy(showImportItemsChevron = action.isEnabled) }
|
||||
}
|
||||
|
||||
private fun handleImportLoginsCardDismissClicked() {
|
||||
if (!state.showImportActionCard) return
|
||||
firstTimeActionManager.storeShowImportLoginsSettingsBadge(showBadge = false)
|
||||
@ -122,6 +141,7 @@ class VaultSettingsViewModel @Inject constructor(
|
||||
*/
|
||||
data class VaultSettingsState(
|
||||
val showImportActionCard: Boolean,
|
||||
val showImportItemsChevron: Boolean,
|
||||
)
|
||||
|
||||
/**
|
||||
@ -197,6 +217,13 @@ sealed class VaultSettingsAction {
|
||||
* Internal actions not performed by user interation
|
||||
*/
|
||||
sealed class Internal : VaultSettingsAction() {
|
||||
/**
|
||||
* Indicates that the import feature flag has been updated.
|
||||
*/
|
||||
data class ImportFeatureUpdated(
|
||||
val isEnabled: Boolean,
|
||||
) : Internal()
|
||||
|
||||
/**
|
||||
* Indicates user first time state has changed.
|
||||
*/
|
||||
|
||||
@ -29,11 +29,7 @@ class VaultSettingsScreenTest : BitwardenComposeTest() {
|
||||
private var onNavigateToExportVaultCalled = false
|
||||
private var onNavigateToFoldersCalled = false
|
||||
private val mutableEventFlow = bufferedMutableSharedFlow<VaultSettingsEvent>()
|
||||
private val mutableStateFlow = MutableStateFlow(
|
||||
VaultSettingsState(
|
||||
showImportActionCard = false,
|
||||
),
|
||||
)
|
||||
private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE)
|
||||
|
||||
val viewModel = mockk<VaultSettingsViewModel>(relaxed = true) {
|
||||
every { eventFlow } returns mutableEventFlow
|
||||
@ -158,3 +154,8 @@ class VaultSettingsScreenTest : BitwardenComposeTest() {
|
||||
.assertIsNotDisplayed()
|
||||
}
|
||||
}
|
||||
|
||||
private val DEFAULT_STATE: VaultSettingsState = VaultSettingsState(
|
||||
showImportActionCard = false,
|
||||
showImportItemsChevron = true,
|
||||
)
|
||||
|
||||
@ -31,7 +31,13 @@ class VaultSettingsViewModelTest : BaseViewModelTest() {
|
||||
every { firstTimeStateFlow } returns mutableFirstTimeStateFlow
|
||||
every { storeShowImportLoginsSettingsBadge(any()) } just runs
|
||||
}
|
||||
private val featureFlagManager = mockk<FeatureFlagManager>()
|
||||
private val mutableFeatureFlagFlow = bufferedMutableSharedFlow<Boolean>()
|
||||
private val featureFlagManager = mockk<FeatureFlagManager> {
|
||||
every { getFeatureFlag(FlagKey.CredentialExchangeProtocolImport) } returns true
|
||||
every {
|
||||
getFeatureFlagFlow(FlagKey.CredentialExchangeProtocolImport)
|
||||
} returns mutableFeatureFlagFlow
|
||||
}
|
||||
|
||||
private val mutableSnackbarSharedFlow = bufferedMutableSharedFlow<BitwardenSnackbarData>()
|
||||
private val snackbarRelayManager = mockk<SnackbarRelayManager> {
|
||||
@ -153,6 +159,25 @@ class VaultSettingsViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `CredentialExchangeProtocolImport flag changes should update state accordingly`() {
|
||||
val viewModel = createViewModel()
|
||||
assertEquals(
|
||||
viewModel.stateFlow.value,
|
||||
VaultSettingsState(showImportActionCard = true, showImportItemsChevron = true),
|
||||
)
|
||||
mutableFeatureFlagFlow.tryEmit(false)
|
||||
assertEquals(
|
||||
viewModel.stateFlow.value,
|
||||
VaultSettingsState(showImportActionCard = true, showImportItemsChevron = false),
|
||||
)
|
||||
mutableFeatureFlagFlow.tryEmit(true)
|
||||
assertEquals(
|
||||
viewModel.stateFlow.value,
|
||||
VaultSettingsState(showImportActionCard = true, showImportItemsChevron = true),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createViewModel(): VaultSettingsViewModel = VaultSettingsViewModel(
|
||||
firstTimeActionManager = firstTimeActionManager,
|
||||
snackbarRelayManager = snackbarRelayManager,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user