mirror of
https://github.com/bitwarden/android.git
synced 2026-05-08 04:16:40 -05:00
PM-33458: feat: Add speed bump when archiving item from a list (#6774)
This commit is contained in:
@@ -33,7 +33,7 @@ import kotlinx.collections.immutable.toPersistentList
|
||||
/**
|
||||
* The contents state for the search screen.
|
||||
*/
|
||||
@Suppress("LongMethod")
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@Composable
|
||||
fun SearchContent(
|
||||
viewState: SearchState.ViewState.Content,
|
||||
@@ -41,43 +41,28 @@ fun SearchContent(
|
||||
searchType: SearchTypeData,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var showConfirmationDialog: ListingItemOverflowAction? by rememberSaveable {
|
||||
var overflowSpeedBumpAction: ListingItemOverflowAction? by rememberSaveable {
|
||||
mutableStateOf(null)
|
||||
}
|
||||
when (val option = showConfirmationDialog) {
|
||||
is ListingItemOverflowAction.SendAction.DeleteClick -> {
|
||||
BitwardenTwoButtonDialog(
|
||||
title = stringResource(id = BitwardenString.delete),
|
||||
message = stringResource(id = BitwardenString.are_you_sure_delete_send),
|
||||
confirmButtonText = stringResource(id = BitwardenString.yes),
|
||||
dismissButtonText = stringResource(id = BitwardenString.cancel),
|
||||
onConfirmClick = {
|
||||
showConfirmationDialog = null
|
||||
searchHandlers.onOverflowItemClick(option)
|
||||
},
|
||||
onDismissClick = { showConfirmationDialog = null },
|
||||
onDismissRequest = { showConfirmationDialog = null },
|
||||
)
|
||||
}
|
||||
|
||||
is ListingItemOverflowAction.SendAction.CopyUrlClick,
|
||||
is ListingItemOverflowAction.SendAction.EditClick,
|
||||
is ListingItemOverflowAction.SendAction.RemovePasswordClick,
|
||||
is ListingItemOverflowAction.SendAction.ShareUrlClick,
|
||||
is ListingItemOverflowAction.SendAction.ViewClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyNoteClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyNumberClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyPasswordClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyTotpClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopySecurityCodeClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyUsernameClick,
|
||||
is ListingItemOverflowAction.VaultAction.EditClick,
|
||||
is ListingItemOverflowAction.VaultAction.LaunchClick,
|
||||
is ListingItemOverflowAction.VaultAction.ViewClick,
|
||||
is ListingItemOverflowAction.VaultAction.ArchiveClick,
|
||||
is ListingItemOverflowAction.VaultAction.UnarchiveClick,
|
||||
null,
|
||||
-> Unit
|
||||
overflowSpeedBumpAction?.let { action ->
|
||||
action
|
||||
.speedBump
|
||||
?.let { speedBump ->
|
||||
BitwardenTwoButtonDialog(
|
||||
twoButtonDialogData = speedBump,
|
||||
onConfirmClick = {
|
||||
overflowSpeedBumpAction = null
|
||||
searchHandlers.onOverflowItemClick(action)
|
||||
},
|
||||
onDismissClick = { overflowSpeedBumpAction = null },
|
||||
onDismissRequest = { overflowSpeedBumpAction = null },
|
||||
)
|
||||
}
|
||||
?: run {
|
||||
// If we somehow get here and there is no speed bump, then we should keep on going.
|
||||
overflowSpeedBumpAction = null
|
||||
searchHandlers.onOverflowItemClick(action)
|
||||
}
|
||||
}
|
||||
|
||||
var autofillSelectionOptionsItem by rememberSaveable {
|
||||
@@ -143,8 +128,12 @@ fun SearchContent(
|
||||
contentDescription = option.contentDescription(),
|
||||
onClick = {
|
||||
when (option) {
|
||||
is ListingItemOverflowAction.SendAction.DeleteClick -> {
|
||||
showConfirmationDialog = option
|
||||
is ListingItemOverflowAction.SendAction -> {
|
||||
if (option.speedBump != null) {
|
||||
overflowSpeedBumpAction = option
|
||||
} else {
|
||||
searchHandlers.onOverflowItemClick(option)
|
||||
}
|
||||
}
|
||||
|
||||
is ListingItemOverflowAction.VaultAction -> {
|
||||
@@ -155,12 +144,12 @@ fun SearchContent(
|
||||
MasterPasswordRepromptData.OverflowItem(
|
||||
action = option,
|
||||
)
|
||||
} else if (option.speedBump != null) {
|
||||
overflowSpeedBumpAction = option
|
||||
} else {
|
||||
searchHandlers.onOverflowItemClick(option)
|
||||
}
|
||||
}
|
||||
|
||||
else -> searchHandlers.onOverflowItemClick(option)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -31,7 +31,7 @@ import com.x8bit.bitwarden.ui.platform.components.listitem.BitwardenListItem
|
||||
import com.x8bit.bitwarden.ui.platform.components.listitem.SelectionItemData
|
||||
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.handlers.VaultItemListingHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.model.ListingItemOverflowAction
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
/**
|
||||
* Content view for the [VaultItemListingScreen].
|
||||
@@ -46,43 +46,29 @@ fun VaultItemListingContent(
|
||||
vaultItemListingHandlers: VaultItemListingHandlers,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var showConfirmationDialog: ListingItemOverflowAction? by rememberSaveable {
|
||||
var overflowSpeedBumpAction: ListingItemOverflowAction? by rememberSaveable {
|
||||
mutableStateOf(null)
|
||||
}
|
||||
when (val option = showConfirmationDialog) {
|
||||
is ListingItemOverflowAction.SendAction.DeleteClick -> {
|
||||
BitwardenTwoButtonDialog(
|
||||
title = stringResource(id = BitwardenString.delete),
|
||||
message = stringResource(id = BitwardenString.are_you_sure_delete_send),
|
||||
confirmButtonText = stringResource(id = BitwardenString.yes),
|
||||
dismissButtonText = stringResource(id = BitwardenString.cancel),
|
||||
onConfirmClick = {
|
||||
showConfirmationDialog = null
|
||||
vaultItemListingHandlers.overflowItemClick(option)
|
||||
},
|
||||
onDismissClick = { showConfirmationDialog = null },
|
||||
onDismissRequest = { showConfirmationDialog = null },
|
||||
)
|
||||
}
|
||||
|
||||
is ListingItemOverflowAction.SendAction.CopyUrlClick,
|
||||
is ListingItemOverflowAction.SendAction.EditClick,
|
||||
is ListingItemOverflowAction.SendAction.ViewClick,
|
||||
is ListingItemOverflowAction.SendAction.RemovePasswordClick,
|
||||
is ListingItemOverflowAction.SendAction.ShareUrlClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyNoteClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyNumberClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyPasswordClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopySecurityCodeClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyUsernameClick,
|
||||
is ListingItemOverflowAction.VaultAction.EditClick,
|
||||
is ListingItemOverflowAction.VaultAction.LaunchClick,
|
||||
is ListingItemOverflowAction.VaultAction.ViewClick,
|
||||
is ListingItemOverflowAction.VaultAction.CopyTotpClick,
|
||||
is ListingItemOverflowAction.VaultAction.ArchiveClick,
|
||||
is ListingItemOverflowAction.VaultAction.UnarchiveClick,
|
||||
null,
|
||||
-> Unit
|
||||
overflowSpeedBumpAction?.let { action ->
|
||||
action
|
||||
.speedBump
|
||||
?.let { speedBump ->
|
||||
BitwardenTwoButtonDialog(
|
||||
twoButtonDialogData = speedBump,
|
||||
onConfirmClick = {
|
||||
overflowSpeedBumpAction = null
|
||||
vaultItemListingHandlers.overflowItemClick(action)
|
||||
},
|
||||
onDismissClick = { overflowSpeedBumpAction = null },
|
||||
onDismissRequest = { overflowSpeedBumpAction = null },
|
||||
)
|
||||
}
|
||||
?: run {
|
||||
// If we somehow get here and there is no speed bump, then we should keep on going.
|
||||
overflowSpeedBumpAction = null
|
||||
vaultItemListingHandlers.overflowItemClick(action)
|
||||
}
|
||||
}
|
||||
|
||||
var masterPasswordRepromptData by remember { mutableStateOf<MasterPasswordRepromptData?>(null) }
|
||||
@@ -264,8 +250,12 @@ fun VaultItemListingContent(
|
||||
contentDescription = option.contentDescription(),
|
||||
onClick = {
|
||||
when (option) {
|
||||
is ListingItemOverflowAction.SendAction.DeleteClick -> {
|
||||
showConfirmationDialog = option
|
||||
is ListingItemOverflowAction.SendAction -> {
|
||||
if (option.speedBump != null) {
|
||||
overflowSpeedBumpAction = option
|
||||
} else {
|
||||
vaultItemListingHandlers.overflowItemClick(option)
|
||||
}
|
||||
}
|
||||
|
||||
is ListingItemOverflowAction.VaultAction -> {
|
||||
@@ -276,19 +266,19 @@ fun VaultItemListingContent(
|
||||
MasterPasswordRepromptData.OverflowItem(
|
||||
action = option,
|
||||
)
|
||||
} else if (option.speedBump != null) {
|
||||
overflowSpeedBumpAction = option
|
||||
} else {
|
||||
vaultItemListingHandlers.overflowItemClick(option)
|
||||
}
|
||||
}
|
||||
|
||||
else -> vaultItemListingHandlers.overflowItemClick(option)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
// Only show options if allowed
|
||||
.filter { !policyDisablesSend }
|
||||
.toPersistentList(),
|
||||
.toImmutableList(),
|
||||
cardStyle = state
|
||||
.displayItemList
|
||||
.toListItemCardStyle(index = index, dividerPadding = 56.dp),
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
@file:OmitFromCoverage
|
||||
|
||||
package com.x8bit.bitwarden.ui.vault.feature.itemlisting.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.bitwarden.annotation.OmitFromCoverage
|
||||
import com.bitwarden.send.SendType
|
||||
import com.bitwarden.ui.platform.components.dialog.model.BitwardenTwoButtonDialogData
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.Text
|
||||
import com.bitwarden.ui.util.asText
|
||||
@@ -23,6 +27,11 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
*/
|
||||
abstract val contentDescription: Text
|
||||
|
||||
/**
|
||||
* The data to be displayed for an optional speed bump dialog.
|
||||
*/
|
||||
abstract val speedBump: BitwardenTwoButtonDialogData?
|
||||
|
||||
/**
|
||||
* Represents the send actions.
|
||||
*/
|
||||
@@ -37,6 +46,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : SendAction() {
|
||||
override val title: Text get() = BitwardenString.view.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,6 +59,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : SendAction() {
|
||||
override val title: Text get() = BitwardenString.edit.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,6 +69,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
data class CopyUrlClick(val sendUrl: String) : SendAction() {
|
||||
override val title: Text get() = BitwardenString.copy_link.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,6 +80,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
override val title: Text get() = BitwardenString.share_link.asText()
|
||||
override val contentDescription: Text
|
||||
get() = BitwardenString.external_link_format.asText(title)
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,6 +90,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
data class RemovePasswordClick(val sendId: String) : SendAction() {
|
||||
override val title: Text get() = BitwardenString.remove_password.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,6 +100,13 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
data class DeleteClick(val sendId: String) : SendAction() {
|
||||
override val title: Text get() = BitwardenString.delete.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData?
|
||||
get() = BitwardenTwoButtonDialogData(
|
||||
title = BitwardenString.delete.asText(),
|
||||
message = BitwardenString.are_you_sure_delete_send.asText(),
|
||||
confirmButtonText = BitwardenString.yes.asText(),
|
||||
dismissButtonText = BitwardenString.cancel.asText(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +131,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : VaultAction() {
|
||||
override val title: Text get() = BitwardenString.view.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,6 +145,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : VaultAction() {
|
||||
override val title: Text get() = BitwardenString.edit.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,6 +156,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
override val title: Text get() = BitwardenString.copy_username.asText()
|
||||
override val requiresPasswordReprompt: Boolean get() = false
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,6 +169,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : VaultAction() {
|
||||
override val title: Text get() = BitwardenString.copy_password.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,6 +182,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : VaultAction() {
|
||||
override val title: Text get() = BitwardenString.copy_totp.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,6 +195,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : VaultAction() {
|
||||
override val title: Text get() = BitwardenString.copy_number.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,6 +208,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : VaultAction() {
|
||||
override val title: Text get() = BitwardenString.copy_security_code.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,6 +221,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
) : VaultAction() {
|
||||
override val title: Text get() = BitwardenString.copy_notes.asText()
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,6 +233,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
override val requiresPasswordReprompt: Boolean get() = false
|
||||
override val contentDescription: Text
|
||||
get() = BitwardenString.external_link_format.asText(title)
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,6 +244,13 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
override val title: Text get() = BitwardenString.archive_verb.asText()
|
||||
override val requiresPasswordReprompt: Boolean get() = true
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData?
|
||||
get() = BitwardenTwoButtonDialogData(
|
||||
title = BitwardenString.archive_item.asText(),
|
||||
message = BitwardenString.once_archived_this_item_will_be_excluded.asText(),
|
||||
confirmButtonText = BitwardenString.archive_verb.asText(),
|
||||
dismissButtonText = BitwardenString.cancel.asText(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,6 +261,7 @@ sealed class ListingItemOverflowAction : Parcelable {
|
||||
override val title: Text get() = BitwardenString.unarchive.asText()
|
||||
override val requiresPasswordReprompt: Boolean get() = true
|
||||
override val contentDescription: Text get() = title
|
||||
override val speedBump: BitwardenTwoButtonDialogData? get() = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
@@ -20,6 +20,7 @@ import androidx.compose.ui.unit.dp
|
||||
import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
|
||||
import com.bitwarden.ui.platform.base.util.toListItemCardStyle
|
||||
import com.bitwarden.ui.platform.components.card.BitwardenActionCard
|
||||
import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
|
||||
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
|
||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||
import com.bitwarden.ui.platform.components.model.CardStyle
|
||||
@@ -48,7 +49,7 @@ fun VaultContent(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
// Handles the master password prompt for the row click
|
||||
var masterPasswordRepromptItem by remember {
|
||||
var masterPasswordRepromptItem by rememberSaveable {
|
||||
mutableStateOf<VaultState.ViewState.VaultItem?>(value = null)
|
||||
}
|
||||
masterPasswordRepromptItem?.let { action ->
|
||||
@@ -61,7 +62,7 @@ fun VaultContent(
|
||||
)
|
||||
}
|
||||
// Handles the master password prompt for the overflow clicks
|
||||
var overflowMasterPasswordRepromptAction by remember {
|
||||
var overflowMasterPasswordRepromptAction by rememberSaveable {
|
||||
mutableStateOf<ListingItemOverflowAction.VaultAction?>(value = null)
|
||||
}
|
||||
overflowMasterPasswordRepromptAction?.let { action ->
|
||||
@@ -73,6 +74,31 @@ fun VaultContent(
|
||||
onDismissRequest = { overflowMasterPasswordRepromptAction = null },
|
||||
)
|
||||
}
|
||||
|
||||
var overflowSpeedBumpAction: ListingItemOverflowAction.VaultAction? by rememberSaveable {
|
||||
mutableStateOf(value = null)
|
||||
}
|
||||
overflowSpeedBumpAction?.let { action ->
|
||||
action
|
||||
.speedBump
|
||||
?.let { speedBump ->
|
||||
BitwardenTwoButtonDialog(
|
||||
twoButtonDialogData = speedBump,
|
||||
onConfirmClick = {
|
||||
overflowSpeedBumpAction = null
|
||||
vaultHandlers.overflowOptionClick(action)
|
||||
},
|
||||
onDismissClick = { overflowSpeedBumpAction = null },
|
||||
onDismissRequest = { overflowSpeedBumpAction = null },
|
||||
)
|
||||
}
|
||||
?: run {
|
||||
// If we somehow get here and there is no speed bump, then we should keep on going.
|
||||
overflowSpeedBumpAction = null
|
||||
vaultHandlers.overflowOptionClick(action)
|
||||
}
|
||||
}
|
||||
|
||||
LazyColumn(
|
||||
modifier = modifier,
|
||||
) {
|
||||
@@ -162,6 +188,8 @@ fun VaultContent(
|
||||
action.requiresPasswordReprompt
|
||||
) {
|
||||
overflowMasterPasswordRepromptAction = action
|
||||
} else if (action.speedBump != null) {
|
||||
overflowSpeedBumpAction = action
|
||||
} else {
|
||||
vaultHandlers.overflowOptionClick(action)
|
||||
}
|
||||
@@ -364,6 +392,8 @@ fun VaultContent(
|
||||
action.requiresPasswordReprompt
|
||||
) {
|
||||
overflowMasterPasswordRepromptAction = action
|
||||
} else if (action.speedBump != null) {
|
||||
overflowSpeedBumpAction = action
|
||||
} else {
|
||||
vaultHandlers.overflowOptionClick(action)
|
||||
}
|
||||
|
||||
@@ -728,26 +728,6 @@ class SearchScreenTest : BitwardenComposeTest() {
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithContentDescription("More options")
|
||||
.assertIsDisplayed()
|
||||
.performClick()
|
||||
composeTestRule
|
||||
.onNodeWithText("Archive")
|
||||
.assert(hasAnyAncestor(isDialog()))
|
||||
.performScrollTo()
|
||||
.assertIsDisplayed()
|
||||
.performClick()
|
||||
verify(exactly = 1) {
|
||||
viewModel.trySendAction(
|
||||
SearchAction.OverflowOptionClick(
|
||||
overflowAction = ListingItemOverflowAction.VaultAction.ArchiveClick(
|
||||
cipherId = "mockId-1",
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule.assertNoDialogExists()
|
||||
}
|
||||
|
||||
@@ -959,7 +939,52 @@ class SearchScreenTest : BitwardenComposeTest() {
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on send item delete overflow option click should display delete confirmation dialog and emits DeleteSendConfirmClick on confirmation`() {
|
||||
fun `on vault item archive overflow option click should display archive confirmation dialog and emits ArchiveClick on confirmation`() {
|
||||
val itemId = "mockId-1"
|
||||
val title = "Archive item"
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
viewState = SearchState.ViewState.Content(
|
||||
displayItems = persistentListOf(createMockDisplayItemForCipher(number = 1)),
|
||||
),
|
||||
)
|
||||
}
|
||||
composeTestRule.onNode(isDialog()).assertDoesNotExist()
|
||||
composeTestRule.onNodeWithText(text = title).assertDoesNotExist()
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithContentDescription(label = "More options")
|
||||
.assertIsDisplayed()
|
||||
.performClick()
|
||||
composeTestRule
|
||||
.onNodeWithText(text = "Archive")
|
||||
.performScrollTo()
|
||||
.assert(hasAnyAncestor(isDialog()))
|
||||
.performClick()
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText(title)
|
||||
.assertIsDisplayed()
|
||||
.assert(hasAnyAncestor(isDialog()))
|
||||
composeTestRule
|
||||
.onNodeWithText(text = "Archive")
|
||||
.assert(hasAnyAncestor(isDialog()))
|
||||
.performClick()
|
||||
|
||||
verify(exactly = 1) {
|
||||
viewModel.trySendAction(
|
||||
SearchAction.OverflowOptionClick(
|
||||
overflowAction = ListingItemOverflowAction.VaultAction.ArchiveClick(
|
||||
cipherId = itemId,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on send item delete overflow option click should display delete confirmation dialog and emits DeleteClick on confirmation`() {
|
||||
val sendId = "mockId-1"
|
||||
val message = "Are you sure you want to delete this Send?"
|
||||
mutableStateFlow.update {
|
||||
|
||||
@@ -1450,6 +1450,55 @@ class VaultItemListingScreenTest : BitwardenComposeTest() {
|
||||
composeTestRule.assertNoDialogExists()
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on item archive overflow option click should display archive confirmation dialog and emits ArchiveClick on confirmation`() {
|
||||
val cipherId = "mockId-1"
|
||||
val archiveAction = ListingItemOverflowAction.VaultAction.ArchiveClick(cipherId = cipherId)
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
itemListingType = VaultItemListingState.ItemListingType.Vault.Login,
|
||||
viewState = VaultItemListingState.ViewState.Content(
|
||||
displayCollectionList = emptyList(),
|
||||
displayItemList = listOf(
|
||||
createCipherDisplayItem(number = 1).copy(
|
||||
overflowOptions = listOf(archiveAction),
|
||||
),
|
||||
),
|
||||
displayFolderList = emptyList(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText(text = "mockTitle-1")
|
||||
.onChildren()
|
||||
.filterToOne(hasContentDescription(value = "More options"))
|
||||
.assertIsDisplayed()
|
||||
.performClick()
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText(text = "Archive")
|
||||
.assert(hasAnyAncestor(isDialog()))
|
||||
.performClick()
|
||||
|
||||
composeTestRule
|
||||
.onAllNodesWithText(text = "Archive item")
|
||||
.filterToOne(hasAnyAncestor(isDialog()))
|
||||
.assertIsDisplayed()
|
||||
composeTestRule
|
||||
.onAllNodesWithText(text = "Archive")
|
||||
.filterToOne(hasAnyAncestor(isDialog()))
|
||||
.assertIsDisplayed()
|
||||
.performClick()
|
||||
|
||||
verify(exactly = 1) {
|
||||
viewModel.trySendAction(
|
||||
action = VaultItemListingsAction.OverflowOptionClick(action = archiveAction),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on cipher item overflow option click when reprompt is required should show the master password dialog`() {
|
||||
|
||||
@@ -1353,6 +1353,57 @@ class VaultScreenTest : BitwardenComposeTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on vault item archive overflow option click should display archive confirmation dialog and emits ArchiveClick on confirmation`() {
|
||||
val itemText = "Test Item"
|
||||
val userName = "Bitwarden"
|
||||
val cipherId = "12345"
|
||||
val archiveAction = ListingItemOverflowAction.VaultAction.ArchiveClick(cipherId = cipherId)
|
||||
val vaultItem = VaultState.ViewState.VaultItem.Login(
|
||||
id = cipherId,
|
||||
name = itemText.asText(),
|
||||
username = userName.asText(),
|
||||
overflowOptions = persistentListOf(archiveAction),
|
||||
shouldShowMasterPasswordReprompt = false,
|
||||
hasDecryptionError = false,
|
||||
)
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
viewState = DEFAULT_CONTENT_VIEW_STATE.copy(
|
||||
favoriteItems = listOf(vaultItem),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule.onNode(hasScrollToNodeAction()).performScrollToNode(hasText(itemText))
|
||||
composeTestRule
|
||||
.onNodeWithText(text = itemText)
|
||||
.onChildren()
|
||||
.filterToOne(hasContentDescription(value = "More options"))
|
||||
.assertIsDisplayed()
|
||||
.performClick()
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText(text = "Archive")
|
||||
.assert(hasAnyAncestor(isDialog()))
|
||||
.performClick()
|
||||
|
||||
composeTestRule
|
||||
.onAllNodesWithText(text = "Archive item")
|
||||
.filterToOne(hasAnyAncestor(isDialog()))
|
||||
.assertIsDisplayed()
|
||||
composeTestRule
|
||||
.onAllNodesWithText(text = "Archive")
|
||||
.filterToOne(hasAnyAncestor(isDialog()))
|
||||
.assertIsDisplayed()
|
||||
.performClick()
|
||||
|
||||
verify(exactly = 1) {
|
||||
viewModel.trySendAction(VaultAction.OverflowOptionClick(overflowAction = archiveAction))
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `clicking a favorite item overflow with password prompt should prompt for password before dismissing upon Cancel`() {
|
||||
|
||||
@@ -28,11 +28,51 @@ import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import com.bitwarden.ui.platform.base.util.toAnnotatedString
|
||||
import com.bitwarden.ui.platform.components.button.BitwardenTextButton
|
||||
import com.bitwarden.ui.platform.components.dialog.model.BitwardenTwoButtonDialogData
|
||||
import com.bitwarden.ui.platform.components.dialog.util.maxDialogHeight
|
||||
import com.bitwarden.ui.platform.components.dialog.util.maxDialogWidth
|
||||
import com.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
|
||||
/**
|
||||
* Represents a Bitwarden-styled dialog with two buttons.
|
||||
*
|
||||
* @param twoButtonDialogData The data to be displayed.
|
||||
* @param onConfirmClick Called when the confirm button is clicked.
|
||||
* @param onDismissClick Called when the dismiss button is clicked.
|
||||
* @param onDismissRequest Called when the user attempts to dismiss the dialog (for example by
|
||||
* tapping outside of it).
|
||||
* @param confirmTextColor The color of the confirm text.
|
||||
* @param dismissTextColor The color of the dismiss text.
|
||||
* @param dismissOnBackPress Indicates that the back button should dismiss the dialog.
|
||||
* @param dismissOnClickOutside Indicates that tapping outside the dialog should dismiss the dialog.
|
||||
*/
|
||||
@Composable
|
||||
fun BitwardenTwoButtonDialog(
|
||||
twoButtonDialogData: BitwardenTwoButtonDialogData,
|
||||
onConfirmClick: () -> Unit,
|
||||
onDismissClick: () -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
confirmTextColor: Color = BitwardenTheme.colorScheme.outlineButton.foreground,
|
||||
dismissTextColor: Color = BitwardenTheme.colorScheme.outlineButton.foreground,
|
||||
dismissOnBackPress: Boolean = true,
|
||||
dismissOnClickOutside: Boolean = true,
|
||||
) {
|
||||
BitwardenTwoButtonDialog(
|
||||
title = twoButtonDialogData.title?.invoke(),
|
||||
message = twoButtonDialogData.message(),
|
||||
confirmButtonText = twoButtonDialogData.confirmButtonText(),
|
||||
dismissButtonText = twoButtonDialogData.dismissButtonText(),
|
||||
onConfirmClick = onConfirmClick,
|
||||
onDismissClick = onDismissClick,
|
||||
onDismissRequest = onDismissRequest,
|
||||
confirmTextColor = confirmTextColor,
|
||||
dismissTextColor = dismissTextColor,
|
||||
dismissOnBackPress = dismissOnBackPress,
|
||||
dismissOnClickOutside = dismissOnClickOutside,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a Bitwarden-styled dialog with two buttons.
|
||||
*
|
||||
@@ -46,6 +86,8 @@ import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
* tapping outside of it).
|
||||
* @param confirmTextColor The color of the confirm text.
|
||||
* @param dismissTextColor The color of the dismiss text.
|
||||
* @param dismissOnBackPress Indicates that the back button should dismiss the dialog.
|
||||
* @param dismissOnClickOutside Indicates that tapping outside the dialog should dismiss the dialog.
|
||||
*/
|
||||
@Composable
|
||||
fun BitwardenTwoButtonDialog(
|
||||
@@ -89,6 +131,8 @@ fun BitwardenTwoButtonDialog(
|
||||
* tapping outside of it).
|
||||
* @param confirmTextColor The color of the confirm text.
|
||||
* @param dismissTextColor The color of the dismiss text.
|
||||
* @param dismissOnBackPress Indicates that the back button should dismiss the dialog.
|
||||
* @param dismissOnClickOutside Indicates that tapping outside the dialog should dismiss the dialog.
|
||||
*/
|
||||
@Composable
|
||||
@Suppress("LongMethod")
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.bitwarden.ui.platform.components.dialog.model
|
||||
|
||||
import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
|
||||
import com.bitwarden.ui.util.Text
|
||||
|
||||
/**
|
||||
* Contains the data for displaying a [BitwardenTwoButtonDialog].
|
||||
*
|
||||
* @property title The optional title to show.
|
||||
* @property message The message to show.
|
||||
* @property confirmButtonText The text to show on confirm button.
|
||||
* @property dismissButtonText The text to show on dismiss button.
|
||||
*/
|
||||
data class BitwardenTwoButtonDialogData(
|
||||
val title: Text?,
|
||||
val message: Text,
|
||||
val confirmButtonText: Text,
|
||||
val dismissButtonText: Text,
|
||||
)
|
||||
@@ -42,6 +42,8 @@
|
||||
<string name="avoid_logout_on_kdf_change">Avoid logout on KDF change</string>
|
||||
<string name="migrate_my_vault_to_my_items">Migrate My Vault to My Items</string>
|
||||
<string name="archive_items">Archive Items</string>
|
||||
<string name="archive_item">Archive item</string>
|
||||
<string name="once_archived_this_item_will_be_excluded">Once archived, this item will be excluded from search results and autofill suggestions.</string>
|
||||
<string name="send_email_verification">Send Email Verification</string>
|
||||
<string name="trigger_cookie_acquisition">Trigger cookie acquisition</string>
|
||||
<string name="clear_sso_cookies">Clear SSO cookies</string>
|
||||
|
||||
Reference in New Issue
Block a user