PM-19776: Change 'Move to Bitwarden' to 'Copy to Bitwarden vault' (#5435)

This commit is contained in:
David Perez 2025-06-27 11:50:14 -05:00 committed by GitHub
parent 288efb3611
commit 3ee74d3ec5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 32 additions and 26 deletions

View File

@ -119,7 +119,7 @@ class ItemListingViewModel @Inject constructor(
} }
is ItemListingAction.ItemClick -> { is ItemListingAction.ItemClick -> {
handleCopyItemClick(action.authCode) handleCopyCodeClick(action.authCode)
} }
is ItemListingAction.DialogDismiss -> { is ItemListingAction.DialogDismiss -> {
@ -164,7 +164,7 @@ class ItemListingViewModel @Inject constructor(
sendEvent(ItemListingEvent.NavigateToAppSettings) sendEvent(ItemListingEvent.NavigateToAppSettings)
} }
private fun handleCopyItemClick(authCode: String) { private fun handleCopyCodeClick(authCode: String) {
clipboardManager.setText(authCode) clipboardManager.setText(authCode)
} }
@ -172,7 +172,7 @@ class ItemListingViewModel @Inject constructor(
sendEvent(ItemListingEvent.NavigateToEditItem(itemId)) sendEvent(ItemListingEvent.NavigateToEditItem(itemId))
} }
private fun handleMoveToBitwardenClick(itemId: String) { private fun handleCopyToBitwardenClick(itemId: String) {
viewModelScope.launch { viewModelScope.launch {
val item = authenticatorRepository val item = authenticatorRepository
.getItemStateFlow(itemId) .getItemStateFlow(itemId)
@ -521,9 +521,9 @@ class ItemListingViewModel @Inject constructor(
private fun handleDropdownMenuClick(action: ItemListingAction.DropdownMenuClick) { private fun handleDropdownMenuClick(action: ItemListingAction.DropdownMenuClick) {
when (action.menuAction) { when (action.menuAction) {
VaultDropdownMenuAction.COPY -> handleCopyItemClick(action.item.authCode) VaultDropdownMenuAction.COPY_CODE -> handleCopyCodeClick(action.item.authCode)
VaultDropdownMenuAction.EDIT -> handleEditItemClick(action.item.id) VaultDropdownMenuAction.EDIT -> handleEditItemClick(action.item.id)
VaultDropdownMenuAction.MOVE -> handleMoveToBitwardenClick(action.item.id) VaultDropdownMenuAction.COPY_TO_BITWARDEN -> handleCopyToBitwardenClick(action.item.id)
VaultDropdownMenuAction.DELETE -> handleDeleteItemClick(action.item.id) VaultDropdownMenuAction.DELETE -> handleDeleteItemClick(action.item.id)
} }
} }

View File

@ -161,7 +161,7 @@ fun VaultVerificationCodeItem(
}, },
onClick = { onClick = {
shouldShowDropdownMenu = false shouldShowDropdownMenu = false
onDropdownMenuClick(VaultDropdownMenuAction.COPY) onDropdownMenuClick(VaultDropdownMenuAction.COPY_CODE)
}, },
leadingIcon = { leadingIcon = {
Icon( Icon(
@ -190,16 +190,18 @@ fun VaultVerificationCodeItem(
HorizontalDivider() HorizontalDivider()
DropdownMenuItem( DropdownMenuItem(
text = { text = {
Text(text = stringResource(id = R.string.move_to_bitwarden)) Text(text = stringResource(id = R.string.copy_to_bitwarden_vault))
}, },
onClick = { onClick = {
shouldShowDropdownMenu = false shouldShowDropdownMenu = false
onDropdownMenuClick(VaultDropdownMenuAction.MOVE) onDropdownMenuClick(VaultDropdownMenuAction.COPY_TO_BITWARDEN)
}, },
leadingIcon = { leadingIcon = {
Icon( Icon(
painter = painterResource(id = R.drawable.ic_arrow_right), painter = painterResource(id = R.drawable.ic_arrow_right),
contentDescription = stringResource(id = R.string.move_to_bitwarden), contentDescription = stringResource(
id = R.string.copy_to_bitwarden_vault,
),
) )
}, },
) )

View File

@ -4,8 +4,8 @@ package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model
* Enum representing the available actions in the Vault dropdown menu. * Enum representing the available actions in the Vault dropdown menu.
*/ */
enum class VaultDropdownMenuAction { enum class VaultDropdownMenuAction {
COPY, COPY_CODE,
COPY_TO_BITWARDEN,
EDIT, EDIT,
MOVE,
DELETE, DELETE,
} }

View File

@ -23,7 +23,7 @@ fun SharedVerificationCodesState.Success.toSharedCodesDisplayState(
it.toDisplayItem( it.toDisplayItem(
alertThresholdSeconds = alertThresholdSeconds, alertThresholdSeconds = alertThresholdSeconds,
// Always map based on Error state, because shared codes will never // Always map based on Error state, because shared codes will never
// show "Move to Bitwarden" action. // show "Copy to Bitwarden vault" action.
sharedVerificationCodesState = SharedVerificationCodesState.Error, sharedVerificationCodesState = SharedVerificationCodesState.Error,
), ),
) )

View File

@ -30,10 +30,10 @@ fun VerificationCodeItem.toDisplayItem(
}, },
favorite = (source as? AuthenticatorItem.Source.Local)?.isFavorite ?: false, favorite = (source as? AuthenticatorItem.Source.Local)?.isFavorite ?: false,
showMoveToBitwarden = when (source) { showMoveToBitwarden = when (source) {
// Shared items should never show Move to Bitwarden action: // Shared items should never show "Copy to Bitwarden vault" action:
is AuthenticatorItem.Source.Shared -> false is AuthenticatorItem.Source.Shared -> false
// Local items should only show Move to Bitwarden if we are successfully syncing: = // Local items should only show "Copy to Bitwarden vault" if we are successfully syncing: =
is AuthenticatorItem.Source.Local -> when (sharedVerificationCodesState) { is AuthenticatorItem.Source.Local -> when (sharedVerificationCodesState) {
SharedVerificationCodesState.AppNotInstalled, SharedVerificationCodesState.AppNotInstalled,
SharedVerificationCodesState.Error, SharedVerificationCodesState.Error,

View File

@ -124,7 +124,7 @@
<string name="take_me_to_app_settings">Take me to the app settings</string> <string name="take_me_to_app_settings">Take me to the app settings</string>
<string name="something_went_wrong">Something went wrong</string> <string name="something_went_wrong">Something went wrong</string>
<string name="please_try_again">Please try again</string> <string name="please_try_again">Please try again</string>
<string name="move_to_bitwarden">Move to Bitwarden</string> <string name="copy_to_bitwarden_vault">Copy to Bitwarden vault</string>
<string name="default_save_option">Default save option</string> <string name="default_save_option">Default save option</string>
<string name="save_to_bitwarden">Save to Bitwarden</string> <string name="save_to_bitwarden">Save to Bitwarden</string>
<string name="save_here">Save here</string> <string name="save_here">Save here</string>

View File

@ -346,7 +346,7 @@ class ItemListingScreenTest : AuthenticatorComposeTest() {
} }
@Test @Test
fun `clicking Move to Bitwarden should send MoveToBitwardenClick`() { fun `clicking Copy to Bitwarden vault should send DropdownMenuClick with COPY_TO_BITWARDEN`() {
mutableStateFlow.value = DEFAULT_STATE.copy( mutableStateFlow.value = DEFAULT_STATE.copy(
viewState = ItemListingState.ViewState.Content( viewState = ItemListingState.ViewState.Content(
actionCard = ItemListingState.ActionCardState.None, actionCard = ItemListingState.ActionCardState.None,
@ -360,21 +360,22 @@ class ItemListingScreenTest : AuthenticatorComposeTest() {
.performTouchInput { longClick() } .performTouchInput { longClick() }
composeTestRule composeTestRule
.onNodeWithText("Move to Bitwarden") .onNodeWithText(text = "Copy to Bitwarden vault")
.performClick() .performClick()
verify { verify {
viewModel.trySendAction( viewModel.trySendAction(
ItemListingAction.DropdownMenuClick( ItemListingAction.DropdownMenuClick(
menuAction = VaultDropdownMenuAction.MOVE, menuAction = VaultDropdownMenuAction.COPY_TO_BITWARDEN,
item = LOCAL_CODE, item = LOCAL_CODE,
), ),
) )
} }
} }
@Suppress("MaxLineLength")
@Test @Test
fun `Move to Bitwarden long press action should not show when showMoveToBitwarden is false`() { fun `Copy to Bitwarden vault long press action should not show when showMoveToBitwarden is false`() {
mutableStateFlow.value = DEFAULT_STATE.copy( mutableStateFlow.value = DEFAULT_STATE.copy(
viewState = ItemListingState.ViewState.Content( viewState = ItemListingState.ViewState.Content(
actionCard = ItemListingState.ActionCardState.None, actionCard = ItemListingState.ActionCardState.None,
@ -388,7 +389,7 @@ class ItemListingScreenTest : AuthenticatorComposeTest() {
.performTouchInput { longClick() } .performTouchInput { longClick() }
composeTestRule composeTestRule
.onNodeWithText("Move to Bitwarden") .onNodeWithText(text = "Copy to Bitwarden vault")
.assertDoesNotExist() .assertDoesNotExist()
} }

View File

@ -378,7 +378,7 @@ class ItemListingViewModelTest : BaseViewModelTest() {
} }
@Test @Test
fun `on MoveToBitwardenClick receive should call startAddTotpLoginItemFlow`() { fun `on CopyToBitwardenClick receive should call startAddTotpLoginItemFlow`() {
val expectedUriString = "expectedUriString" val expectedUriString = "expectedUriString"
val entity: AuthenticatorItemEntity = mockk { val entity: AuthenticatorItemEntity = mockk {
every { toOtpAuthUriString() } returns expectedUriString every { toOtpAuthUriString() } returns expectedUriString
@ -394,7 +394,7 @@ class ItemListingViewModelTest : BaseViewModelTest() {
viewModel.trySendAction( viewModel.trySendAction(
ItemListingAction.DropdownMenuClick( ItemListingAction.DropdownMenuClick(
menuAction = VaultDropdownMenuAction.MOVE, menuAction = VaultDropdownMenuAction.COPY_TO_BITWARDEN,
item = LOCAL_CODE, item = LOCAL_CODE,
), ),
) )
@ -403,7 +403,7 @@ class ItemListingViewModelTest : BaseViewModelTest() {
@Test @Test
@Suppress("MaxLineLength") @Suppress("MaxLineLength")
fun `on MoveToBitwardenClick should show error dialog when startAddTotpLoginItemFlow returns false`() { fun `on CopyToBitwardenClick should show error dialog when startAddTotpLoginItemFlow returns false`() {
val expectedState = DEFAULT_STATE.copy( val expectedState = DEFAULT_STATE.copy(
dialog = ItemListingState.DialogState.Error( dialog = ItemListingState.DialogState.Error(
title = R.string.something_went_wrong.asText(), title = R.string.something_went_wrong.asText(),
@ -423,7 +423,10 @@ class ItemListingViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel() val viewModel = createViewModel()
viewModel.trySendAction( viewModel.trySendAction(
ItemListingAction.DropdownMenuClick(VaultDropdownMenuAction.MOVE, LOCAL_CODE), ItemListingAction.DropdownMenuClick(
menuAction = VaultDropdownMenuAction.COPY_TO_BITWARDEN,
item = LOCAL_CODE,
),
) )
assertEquals( assertEquals(
expectedState, expectedState,
@ -442,7 +445,7 @@ class ItemListingViewModelTest : BaseViewModelTest() {
} }
@Test @Test
fun `should copy text to clipboard when DropdownMenuClick COPY is triggered`() = runTest { fun `should copy text to clipboard when DropdownMenuClick COPY_CODE is triggered`() = runTest {
val viewModel = createViewModel() val viewModel = createViewModel()
every { clipboardManager.setText(text = LOCAL_CODE.authCode) } just runs every { clipboardManager.setText(text = LOCAL_CODE.authCode) } just runs
@ -450,7 +453,7 @@ class ItemListingViewModelTest : BaseViewModelTest() {
viewModel.eventFlow.test { viewModel.eventFlow.test {
viewModel.trySendAction( viewModel.trySendAction(
ItemListingAction.DropdownMenuClick( ItemListingAction.DropdownMenuClick(
menuAction = VaultDropdownMenuAction.COPY, menuAction = VaultDropdownMenuAction.COPY_CODE,
item = LOCAL_CODE, item = LOCAL_CODE,
), ),
) )