diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt
index 0e051cd090..2ca2bf1043 100644
--- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt
+++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt
@@ -53,6 +53,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.bitwarden.authenticator.R
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.ItemListingExpandableFabAction
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
+import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
+import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.platform.base.util.EventsEffect
import com.bitwarden.authenticator.ui.platform.base.util.asText
import com.bitwarden.authenticator.ui.platform.components.appbar.BitwardenMediumTopAppBar
@@ -211,17 +213,13 @@ fun ItemListingScreen(
)
}
},
- onEditItemClick = remember(viewModel) {
- {
+ onDropdownMenuClick = remember(viewModel) {
+ { action, item ->
viewModel.trySendAction(
- ItemListingAction.EditItemClick(it),
- )
- }
- },
- onDeleteItemClick = remember(viewModel) {
- {
- viewModel.trySendAction(
- ItemListingAction.DeleteItemClick(it),
+ ItemListingAction.DropdownMenuClick(
+ menuAction = action,
+ item = item,
+ ),
)
}
},
@@ -245,11 +243,6 @@ fun ItemListingScreen(
viewModel.trySendAction(ItemListingAction.SyncWithBitwardenDismiss)
}
},
- onMoveToBitwardenClick = remember(viewModel) {
- {
- viewModel.trySendAction(ItemListingAction.MoveToBitwardenClick(it))
- }
- },
)
}
@@ -354,9 +347,7 @@ private fun ItemListingContent(
onScanQrCodeClick: () -> Unit,
onEnterSetupKeyClick: () -> Unit,
onItemClick: (String) -> Unit,
- onEditItemClick: (String) -> Unit,
- onDeleteItemClick: (String) -> Unit,
- onMoveToBitwardenClick: (String) -> Unit,
+ onDropdownMenuClick: (VaultDropdownMenuAction, VerificationCodeDisplayItem) -> Unit,
onDownloadBitwardenClick: () -> Unit,
onDismissDownloadBitwardenClick: () -> Unit,
onSyncWithBitwardenClick: () -> Unit,
@@ -467,9 +458,9 @@ private fun ItemListingContent(
alertThresholdSeconds = it.alertThresholdSeconds,
startIcon = it.startIcon,
onItemClick = { onItemClick(it.authCode) },
- onEditItemClick = { onEditItemClick(it.id) },
- onDeleteItemClick = { onDeleteItemClick(it.id) },
- onMoveToBitwardenClick = { onMoveToBitwardenClick(it.id) },
+ onDropdownMenuClick = { action ->
+ onDropdownMenuClick(action, it)
+ },
showMoveToBitwarden = it.showMoveToBitwarden,
allowLongPress = it.allowLongPressActions,
modifier = Modifier.fillMaxWidth(),
@@ -508,9 +499,9 @@ private fun ItemListingContent(
alertThresholdSeconds = it.alertThresholdSeconds,
startIcon = it.startIcon,
onItemClick = { onItemClick(it.authCode) },
- onEditItemClick = { onEditItemClick(it.id) },
- onDeleteItemClick = { onDeleteItemClick(it.id) },
- onMoveToBitwardenClick = { onMoveToBitwardenClick(it.id) },
+ onDropdownMenuClick = { action ->
+ onDropdownMenuClick(action, it)
+ },
showMoveToBitwarden = it.showMoveToBitwarden,
allowLongPress = it.allowLongPressActions,
modifier = Modifier.fillMaxWidth(),
@@ -544,9 +535,9 @@ private fun ItemListingContent(
alertThresholdSeconds = it.alertThresholdSeconds,
startIcon = it.startIcon,
onItemClick = { onItemClick(it.authCode) },
- onEditItemClick = { },
- onDeleteItemClick = { },
- onMoveToBitwardenClick = { },
+ onDropdownMenuClick = { action ->
+ onDropdownMenuClick(action, it)
+ },
showMoveToBitwarden = it.showMoveToBitwarden,
allowLongPress = it.allowLongPressActions,
modifier = Modifier.fillMaxWidth(),
diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt
index fa79362759..905abd5e8d 100644
--- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt
+++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt
@@ -21,6 +21,7 @@ import com.bitwarden.authenticator.data.platform.manager.imports.model.GoogleAut
import com.bitwarden.authenticator.data.platform.repository.SettingsRepository
import com.bitwarden.authenticator.data.platform.repository.model.DataState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
+import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util.toDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util.toSharedCodesDisplayState
@@ -62,7 +63,6 @@ class ItemListingViewModel @Inject constructor(
) {
init {
-
settingsRepository
.authenticatorAlertThresholdSecondsFlow
.map { ItemListingAction.Internal.AlertThresholdSecondsReceive(it) }
@@ -110,10 +110,6 @@ class ItemListingViewModel @Inject constructor(
sendEvent(ItemListingEvent.NavigateBack)
}
- is ItemListingAction.DeleteItemClick -> {
- handleDeleteItemClick(action)
- }
-
is ItemListingAction.ConfirmDeleteClick -> {
handleConfirmDeleteClick(action)
}
@@ -123,11 +119,7 @@ class ItemListingViewModel @Inject constructor(
}
is ItemListingAction.ItemClick -> {
- handleItemClick(action)
- }
-
- is ItemListingAction.EditItemClick -> {
- handleEditItemClick(action)
+ handleCopyItemClick(action.authCode)
}
is ItemListingAction.DialogDismiss -> {
@@ -142,6 +134,10 @@ class ItemListingViewModel @Inject constructor(
handleInternalAction(action)
}
+ is ItemListingAction.DropdownMenuClick -> {
+ handleDropdownMenuClick(action)
+ }
+
ItemListingAction.DownloadBitwardenClick -> {
handleDownloadBitwardenClick()
}
@@ -157,10 +153,6 @@ class ItemListingViewModel @Inject constructor(
ItemListingAction.SyncWithBitwardenDismiss -> {
handleSyncWithBitwardenDismiss()
}
-
- is ItemListingAction.MoveToBitwardenClick -> {
- handleMoveToBitwardenClick(action)
- }
}
}
@@ -168,27 +160,22 @@ class ItemListingViewModel @Inject constructor(
sendEvent(ItemListingEvent.NavigateToAppSettings)
}
- private fun handleItemClick(action: ItemListingAction.ItemClick) {
- clipboardManager.setText(action.authCode)
- sendEvent(
- ItemListingEvent.ShowToast(
- message = R.string.value_has_been_copied.asText(action.authCode),
- ),
- )
+ private fun handleCopyItemClick(authCode: String) {
+ clipboardManager.setText(authCode)
}
- private fun handleEditItemClick(action: ItemListingAction.EditItemClick) {
- sendEvent(ItemListingEvent.NavigateToEditItem(action.itemId))
+ private fun handleEditItemClick(itemId: String) {
+ sendEvent(ItemListingEvent.NavigateToEditItem(itemId))
}
- private fun handleMoveToBitwardenClick(action: ItemListingAction.MoveToBitwardenClick) {
+ private fun handleMoveToBitwardenClick(itemId: String) {
viewModelScope.launch {
val item = authenticatorRepository
- .getItemStateFlow(action.entityId)
+ .getItemStateFlow(itemId)
.first { it.data != null }
val didLaunchAddTotpFlow = authenticatorBridgeManager.startAddTotpLoginItemFlow(
- totpUri = item.data!!.toOtpAuthUriString(),
+ totpUri = item.data?.toOtpAuthUriString().orEmpty(),
)
if (!didLaunchAddTotpFlow) {
mutableStateFlow.update {
@@ -203,12 +190,12 @@ class ItemListingViewModel @Inject constructor(
}
}
- private fun handleDeleteItemClick(action: ItemListingAction.DeleteItemClick) {
+ private fun handleDeleteItemClick(itemId: String) {
mutableStateFlow.update {
it.copy(
dialog = ItemListingState.DialogState.DeleteConfirmationPrompt(
message = R.string.do_you_really_want_to_permanently_delete_cipher.asText(),
- itemId = action.itemId,
+ itemId = itemId,
),
)
}
@@ -528,6 +515,15 @@ class ItemListingViewModel @Inject constructor(
sendEvent(ItemListingEvent.NavigateToBitwardenListing)
}
+ private fun handleDropdownMenuClick(action: ItemListingAction.DropdownMenuClick) {
+ when (action.menuAction) {
+ VaultDropdownMenuAction.COPY -> handleCopyItemClick(action.item.authCode)
+ VaultDropdownMenuAction.EDIT -> handleEditItemClick(action.item.id)
+ VaultDropdownMenuAction.MOVE -> handleMoveToBitwardenClick(action.item.id)
+ VaultDropdownMenuAction.DELETE -> handleDeleteItemClick(action.item.id)
+ }
+ }
+
private fun handleDownloadBitwardenDismiss() {
settingsRepository.hasUserDismissedDownloadBitwardenCard = true
mutableStateFlow.update {
@@ -663,7 +659,6 @@ data class ItemListingState(
val viewState: ViewState,
val dialog: DialogState?,
) : Parcelable {
-
/**
* Represents the different view states of the [ItemListingScreen].
*/
@@ -714,7 +709,6 @@ data class ItemListingState(
* Display an action card on the item [ItemListingScreen].
*/
sealed class ActionCardState : Parcelable {
-
/**
* Display no action card.
*/
@@ -738,7 +732,6 @@ data class ItemListingState(
* Display a dialog on the [ItemListingScreen].
*/
sealed class DialogState : Parcelable {
-
/**
* Displays the loading dialog to the user.
*/
@@ -769,7 +762,6 @@ data class ItemListingState(
* Represents a set of events related to viewing the item listing.
*/
sealed class ItemListingEvent {
-
/**
* Navigates to the Create Account screen.
*/
@@ -830,7 +822,6 @@ sealed class ItemListingEvent {
* Each subclass of this sealed class denotes a distinct action that can be taken.
*/
sealed class ItemListingAction {
-
/**
* The user clicked the back button.
*/
@@ -856,11 +847,6 @@ sealed class ItemListingAction {
*/
data class ItemClick(val authCode: String) : ItemListingAction()
- /**
- * The user clicked edit item.
- */
- data class EditItemClick(val itemId: String) : ItemListingAction()
-
/**
* The user dismissed the dialog.
*/
@@ -892,15 +878,25 @@ sealed class ItemListingAction {
data object SyncWithBitwardenDismiss : ItemListingAction()
/**
- * The user clicked the "Move to Bitwarden" action on a local verification item.
+ * The user clicked confirm when prompted to delete an item.
*/
- data class MoveToBitwardenClick(val entityId: String) : ItemListingAction()
+ data class ConfirmDeleteClick(val itemId: String) : ItemListingAction()
+
+ /**
+ * Represents an action triggered when the user clicks an item in the dropdown menu.
+ *
+ * @param menuAction The action selected from the dropdown menu.
+ * @param id The identifier of the item on which the action is being performed.
+ */
+ data class DropdownMenuClick(
+ val menuAction: VaultDropdownMenuAction,
+ val item: VerificationCodeDisplayItem,
+ ) : ItemListingAction()
/**
* Models actions that [ItemListingScreen] itself may send.
*/
sealed class Internal : ItemListingAction() {
-
/**
* Indicates verification items have been received.
*/
@@ -941,14 +937,4 @@ sealed class ItemListingAction {
*/
data object FirstTimeUserSyncReceive : Internal()
}
-
- /**
- * The user clicked Delete.
- */
- data class DeleteItemClick(val itemId: String) : ItemListingAction()
-
- /**
- * The user clicked confirm when prompted to delete an item.
- */
- data class ConfirmDeleteClick(val itemId: String) : ItemListingAction()
}
diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt
index c322350e90..0ac68978ac 100644
--- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt
+++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt
@@ -33,6 +33,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.bitwarden.authenticator.R
+import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
import com.bitwarden.authenticator.ui.platform.components.icon.BitwardenIcon
import com.bitwarden.authenticator.ui.platform.components.indicator.BitwardenCircularCountdownIndicator
import com.bitwarden.authenticator.ui.platform.components.model.IconData
@@ -46,8 +47,12 @@ import com.bitwarden.authenticator.ui.platform.theme.AuthenticatorTheme
* @param secondaryLabel The supporting label for the item. Represents the OTP account name.
* @param periodSeconds The times span where the code is valid.
* @param timeLeftSeconds The seconds remaining until a new code is needed.
+ * @param alertThresholdSeconds The time threshold in seconds to display an expiration warning.
* @param startIcon The leading icon for the item.
* @param onItemClick The lambda function to be invoked when the item is clicked.
+ * @param onDropdownMenuClick A lambda function invoked when a dropdown menu action is clicked.
+ * @param allowLongPress Whether long-press interactions are enabled for the item.
+ * @param showMoveToBitwarden Whether the option to move the item to Bitwarden is displayed.
* @param modifier The modifier for the item.
*/
@OptIn(ExperimentalFoundationApi::class)
@@ -62,9 +67,7 @@ fun VaultVerificationCodeItem(
alertThresholdSeconds: Int,
startIcon: IconData,
onItemClick: () -> Unit,
- onEditItemClick: () -> Unit,
- onDeleteItemClick: () -> Unit,
- onMoveToBitwardenClick: () -> Unit,
+ onDropdownMenuClick: (VaultDropdownMenuAction) -> Unit,
allowLongPress: Boolean,
showMoveToBitwarden: Boolean,
modifier: Modifier = Modifier,
@@ -155,13 +158,29 @@ fun VaultVerificationCodeItem(
expanded = shouldShowDropdownMenu,
onDismissRequest = { shouldShowDropdownMenu = false },
) {
+ DropdownMenuItem(
+ text = {
+ Text(text = stringResource(id = R.string.copy))
+ },
+ onClick = {
+ shouldShowDropdownMenu = false
+ onDropdownMenuClick(VaultDropdownMenuAction.COPY)
+ },
+ leadingIcon = {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_copy),
+ contentDescription = stringResource(id = R.string.copy),
+ )
+ },
+ )
+ HorizontalDivider()
DropdownMenuItem(
text = {
Text(text = stringResource(id = R.string.edit_item))
},
onClick = {
shouldShowDropdownMenu = false
- onEditItemClick()
+ onDropdownMenuClick(VaultDropdownMenuAction.EDIT)
},
leadingIcon = {
Icon(
@@ -174,16 +193,16 @@ fun VaultVerificationCodeItem(
HorizontalDivider()
DropdownMenuItem(
text = {
- Text(text = stringResource(id = R.string.copy_to_bitwarden))
+ Text(text = stringResource(id = R.string.move_to_bitwarden))
},
onClick = {
shouldShowDropdownMenu = false
- onMoveToBitwardenClick()
+ onDropdownMenuClick(VaultDropdownMenuAction.MOVE)
},
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_arrow_right),
- contentDescription = stringResource(id = R.string.copy_to_bitwarden),
+ contentDescription = stringResource(id = R.string.move_to_bitwarden),
)
},
)
@@ -195,7 +214,7 @@ fun VaultVerificationCodeItem(
},
onClick = {
shouldShowDropdownMenu = false
- onDeleteItemClick()
+ onDropdownMenuClick(VaultDropdownMenuAction.DELETE)
},
leadingIcon = {
Icon(
@@ -222,9 +241,7 @@ private fun VerificationCodeItem_preview() {
alertThresholdSeconds = 7,
startIcon = IconData.Local(R.drawable.ic_login_item),
onItemClick = {},
- onEditItemClick = {},
- onDeleteItemClick = {},
- onMoveToBitwardenClick = {},
+ onDropdownMenuClick = {},
allowLongPress = true,
modifier = Modifier.padding(horizontal = 16.dp),
showMoveToBitwarden = true,
diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/model/VaultDropdownMenuAction.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/model/VaultDropdownMenuAction.kt
new file mode 100644
index 0000000000..0247844a10
--- /dev/null
+++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/model/VaultDropdownMenuAction.kt
@@ -0,0 +1,11 @@
+package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model
+
+/**
+ * Enum representing the available actions in the Vault dropdown menu.
+ */
+enum class VaultDropdownMenuAction {
+ COPY,
+ EDIT,
+ MOVE,
+ DELETE,
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f39c0c64cd..2830d56f1c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -132,7 +132,7 @@
Allow Authenticator app syncing in settings to view all of your verification codes here.
Something went wrong
Please try again
- Copy to Bitwarden
+ Move to Bitwarden
Default save option
Save to Bitwarden
Save here
diff --git a/app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreenTest.kt b/app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreenTest.kt
index 412c6d5e1e..ced58fe8f4 100644
--- a/app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreenTest.kt
+++ b/app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreenTest.kt
@@ -10,6 +10,7 @@ import androidx.compose.ui.test.performScrollTo
import androidx.compose.ui.test.performTouchInput
import com.bitwarden.authenticator.data.platform.repository.util.bufferedMutableSharedFlow
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
+import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.platform.base.BaseComposeTest
import com.bitwarden.authenticator.ui.platform.base.util.asText
@@ -202,7 +203,7 @@ class ItemListingScreenTest : BaseComposeTest() {
}
@Test
- fun `clicking Copy to Bitwarden should send MoveToBitwardenClick`() {
+ fun `clicking Move to Bitwarden should send MoveToBitwardenClick`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
viewState = ItemListingState.ViewState.Content(
actionCard = ItemListingState.ActionCardState.None,
@@ -216,10 +217,17 @@ class ItemListingScreenTest : BaseComposeTest() {
.performTouchInput { longClick() }
composeTestRule
- .onNodeWithText("Copy to Bitwarden")
+ .onNodeWithText("Move to Bitwarden")
.performClick()
- verify { viewModel.trySendAction(ItemListingAction.MoveToBitwardenClick("1")) }
+ verify {
+ viewModel.trySendAction(
+ ItemListingAction.DropdownMenuClick(
+ menuAction = VaultDropdownMenuAction.MOVE,
+ item = LOCAL_CODE,
+ ),
+ )
+ }
}
@Test
diff --git a/app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListViewModelTest.kt b/app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModelTest.kt
similarity index 89%
rename from app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListViewModelTest.kt
rename to app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModelTest.kt
index b484502e5c..318224bad7 100644
--- a/app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListViewModelTest.kt
+++ b/app/src/test/java/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModelTest.kt
@@ -12,6 +12,8 @@ import com.bitwarden.authenticator.data.platform.manager.clipboard.BitwardenClip
import com.bitwarden.authenticator.data.platform.repository.SettingsRepository
import com.bitwarden.authenticator.data.platform.repository.model.DataState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
+import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
+import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util.toDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util.toSharedCodesDisplayState
import com.bitwarden.authenticator.ui.platform.base.BaseViewModelTest
@@ -31,7 +33,7 @@ import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
-class ItemListViewModelTest : BaseViewModelTest() {
+class ItemListingViewModelTest : BaseViewModelTest() {
private val mutableAuthenticatorAlertThresholdFlow =
MutableStateFlow(AUTHENTICATOR_ALERT_SECONDS)
@@ -381,7 +383,12 @@ class ItemListViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
- viewModel.trySendAction(ItemListingAction.MoveToBitwardenClick(entityId = "1"))
+ viewModel.trySendAction(
+ ItemListingAction.DropdownMenuClick(
+ menuAction = VaultDropdownMenuAction.MOVE,
+ item = LOCAL_CODE,
+ ),
+ )
verify { authenticatorBridgeManager.startAddTotpLoginItemFlow(expectedUriString) }
}
@@ -406,7 +413,9 @@ class ItemListViewModelTest : BaseViewModelTest() {
} returns false
val viewModel = createViewModel()
- viewModel.trySendAction(ItemListingAction.MoveToBitwardenClick(entityId = "1"))
+ viewModel.trySendAction(
+ ItemListingAction.DropdownMenuClick(VaultDropdownMenuAction.MOVE, LOCAL_CODE),
+ )
assertEquals(
expectedState,
viewModel.stateFlow.value,
@@ -423,6 +432,66 @@ class ItemListViewModelTest : BaseViewModelTest() {
}
}
+ @Test
+ fun `should copy text to clipboard when DropdownMenuClick COPY is triggered`() = runTest {
+ val viewModel = createViewModel()
+
+ every { clipboardManager.setText(text = LOCAL_CODE.authCode) } just runs
+
+ viewModel.eventFlow.test {
+ viewModel.trySendAction(
+ ItemListingAction.DropdownMenuClick(
+ menuAction = VaultDropdownMenuAction.COPY,
+ item = LOCAL_CODE,
+ ),
+ )
+
+ verify(exactly = 1) {
+ clipboardManager.setText(text = LOCAL_CODE.authCode)
+ }
+ }
+ }
+
+ @Test
+ fun `should trigger edit action when DropdownMenuClick EDIT is triggered`() = runTest {
+ val viewModel = createViewModel()
+
+ viewModel.eventFlow.test {
+ viewModel.trySendAction(
+ ItemListingAction.DropdownMenuClick(VaultDropdownMenuAction.EDIT, LOCAL_CODE),
+ )
+
+ assertEquals(
+ ItemListingEvent.NavigateToEditItem(LOCAL_CODE.id),
+ awaitItem(),
+ )
+ }
+ }
+
+ @Test
+ fun `should trigger delete prompt when DropdownMenuClick DELETE is triggered`() = runTest {
+ val viewModel = createViewModel()
+
+ val expectedState = DEFAULT_STATE.copy(
+ dialog = ItemListingState.DialogState.DeleteConfirmationPrompt(
+ message = R.string.do_you_really_want_to_permanently_delete_cipher.asText(),
+ itemId = LOCAL_CODE.id,
+ ),
+ )
+
+ viewModel.trySendAction(
+ ItemListingAction.DropdownMenuClick(
+ menuAction = VaultDropdownMenuAction.DELETE,
+ item = LOCAL_CODE,
+ ),
+ )
+
+ assertEquals(
+ expectedState,
+ viewModel.stateFlow.value,
+ )
+ }
+
private fun createViewModel() = ItemListingViewModel(
authenticatorRepository = authenticatorRepository,
authenticatorBridgeManager = authenticatorBridgeManager,
@@ -441,6 +510,19 @@ private val DEFAULT_STATE = ItemListingState(
dialog = null,
)
+private val LOCAL_CODE = VerificationCodeDisplayItem(
+ id = "1",
+ title = "issuer",
+ subtitle = null,
+ timeLeftSeconds = 10,
+ periodSeconds = 30,
+ alertThresholdSeconds = 7,
+ authCode = "123456",
+ favorite = false,
+ allowLongPressActions = true,
+ showMoveToBitwarden = true,
+)
+
private val LOCAL_VERIFICATION_ITEMS = listOf(
VerificationCodeItem(
code = "123456",