diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemCardContent.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemCardContent.kt index 565cd88e2a..c4a60ae9ba 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemCardContent.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemCardContent.kt @@ -57,6 +57,7 @@ fun VaultItemCardContent( itemHeader( value = commonState.name, isFavorite = commonState.favorite, + isArchived = commonState.archived, iconData = cardState.paymentCardBrandIconData ?: commonState.iconData, relatedLocations = commonState.relatedLocations, iconTestTag = "CardItemNameIcon", diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemIdentityContent.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemIdentityContent.kt index 1ccf7a47d0..22a7f6f3de 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemIdentityContent.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemIdentityContent.kt @@ -57,6 +57,7 @@ fun VaultItemIdentityContent( itemHeader( value = commonState.name, isFavorite = commonState.favorite, + isArchived = commonState.archived, iconData = commonState.iconData, relatedLocations = commonState.relatedLocations, iconTestTag = "IdentityItemNameIcon", diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt index 7811236f0e..714071eec0 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt @@ -65,6 +65,7 @@ fun VaultItemLoginContent( itemHeader( value = commonState.name, isFavorite = commonState.favorite, + isArchived = commonState.archived, iconData = commonState.iconData, relatedLocations = commonState.relatedLocations, iconTestTag = "LoginItemNameIcon", diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemSecureNoteContent.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemSecureNoteContent.kt index 3517632a07..4059d29a2f 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemSecureNoteContent.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemSecureNoteContent.kt @@ -51,6 +51,7 @@ fun VaultItemSecureNoteContent( itemHeader( value = commonState.name, isFavorite = commonState.favorite, + isArchived = commonState.archived, iconData = commonState.iconData, relatedLocations = commonState.relatedLocations, iconTestTag = "SecureNoteItemNameIcon", diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemSshKeyContent.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemSshKeyContent.kt index b60f0b4662..9ef73d2097 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemSshKeyContent.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemSshKeyContent.kt @@ -55,6 +55,7 @@ fun VaultItemSshKeyContent( itemHeader( value = commonState.name, isFavorite = commonState.favorite, + isArchived = commonState.archived, iconData = commonState.iconData, relatedLocations = commonState.relatedLocations, iconTestTag = "SshKeyItemNameIcon", diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt index 25e163b210..446c2bda99 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt @@ -1421,6 +1421,7 @@ data class VaultItemState( val canAssignToCollections: Boolean, val canEdit: Boolean, val favorite: Boolean, + val archived: Boolean, val passwordHistoryCount: Int?, val iconData: IconData, val relatedLocations: ImmutableList, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/component/ItemHeader.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/component/ItemHeader.kt index 54de336573..0075263bf0 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/component/ItemHeader.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/component/ItemHeader.kt @@ -52,6 +52,7 @@ import kotlinx.collections.immutable.persistentListOf * * @param value The name of the cipher. * @param isFavorite Whether the cipher is a favorite. + * @param isArchived Whether the cipher is archived. * @param relatedLocations The locations the cipher is assigned to. * @param iconData The icon to be displayed. * @param isExpanded Whether the related locations are expanded. @@ -64,6 +65,7 @@ import kotlinx.collections.immutable.persistentListOf fun LazyListScope.itemHeader( value: String, isFavorite: Boolean, + isArchived: Boolean, relatedLocations: ImmutableList, iconData: IconData, isExpanded: Boolean, @@ -132,6 +134,25 @@ fun LazyListScope.itemHeader( } } + if (isArchived) { + item(key = "archiveItem") { + ItemLocationListItem( + vectorPainter = rememberVectorPainter(id = BitwardenDrawable.ic_archive), + text = stringResource(id = BitwardenString.archived), + iconTestTag = "ArchiveIcon", + modifier = Modifier + .standardHorizontalMargin() + .fillMaxWidth() + .animateItem() + .cardStyle( + cardStyle = CardStyle.Middle(hasDivider = false), + paddingVertical = 0.dp, + paddingHorizontal = 16.dp, + ), + ) + } + } + // When the item does not belong to an Org and is not assigned to a collection or folder we // display the "No Folder" indicator. if (relatedLocations.isEmpty()) { @@ -183,7 +204,7 @@ fun LazyListScope.itemHeader( if (collectionLocations.size == 1 && folderLocations.size == 1) { itemsIndexed( items = collectionLocations + folderLocations, - key = { index, location -> "locations_$index" }, + key = { index, _ -> "locations_$index" }, ) { index, location -> ItemLocationListItem( vectorPainter = rememberVectorPainter(location.icon), @@ -263,7 +284,7 @@ fun LazyListScope.itemHeader( itemsIndexed( key = { index, _ -> "expandableLocations_$index" }, items = collectionLocations.drop(1) + folderLocations, - ) { index, location -> + ) { _, location -> ItemLocationListItem( vectorPainter = rememberVectorPainter(location.icon), text = location.name, @@ -364,7 +385,7 @@ private fun LazyItemScope.ItemLocationListItem( Text( text = text, style = BitwardenTheme.typography.bodyLarge, - color = BitwardenTheme.colorScheme.text.primary, + color = BitwardenTheme.colorScheme.text.secondary, modifier = Modifier .padding(start = 16.dp) .testTag("ItemLocationText"), @@ -382,6 +403,7 @@ private fun ItemHeaderWithLocalIcon_Preview() { itemHeader( value = "Login without favicon", isFavorite = true, + isArchived = false, iconData = IconData.Local( iconRes = BitwardenDrawable.ic_globe, ), @@ -403,6 +425,7 @@ private fun ItemHeaderWithNetworkIcon_Preview() { itemHeader( value = "Login with favicon", isFavorite = true, + isArchived = false, iconData = IconData.Network( uri = "mockuri", fallbackIconRes = BitwardenDrawable.ic_globe, @@ -425,6 +448,7 @@ private fun ItemHeaderWithOrganization_Preview() { itemHeader( value = "Login without favicon", isFavorite = true, + isArchived = true, iconData = IconData.Local( iconRes = BitwardenDrawable.ic_globe, ), @@ -448,6 +472,7 @@ private fun ItemHeaderWithOrgAndSingleCollection_Preview() { itemHeader( value = "Login without favicon", isFavorite = true, + isArchived = false, iconData = IconData.Local( iconRes = BitwardenDrawable.ic_globe, ), @@ -472,6 +497,7 @@ private fun ItemHeaderWithOrgAndMultiCollection_Preview() { itemHeader( value = "Login without favicon", isFavorite = true, + isArchived = false, iconData = IconData.Local( iconRes = BitwardenDrawable.ic_payment_card_brand_visa, ), @@ -497,6 +523,7 @@ private fun ItemHeaderWithOrgSingleCollectionAndFolder_Preview() { itemHeader( value = "Note without favicon", isFavorite = true, + isArchived = true, iconData = IconData.Local( iconRes = BitwardenDrawable.ic_note, ), @@ -522,6 +549,7 @@ private fun ItemHeaderFolderOnly_Preview() { itemHeader( value = "SSH key in a folder", isFavorite = true, + isArchived = true, iconData = IconData.Local( iconRes = BitwardenDrawable.ic_ssh_key, ), diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt index 60f48f6c1b..24aa34fba6 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt @@ -108,6 +108,7 @@ fun CipherView.toViewState( canAssignToCollections = canAssignToCollections, canEdit = canEdit, favorite = this.favorite, + archived = this.archivedDate != null, passwordHistoryCount = passwordHistory?.count(), iconData = this.toIconData( baseIconUrl = baseIconUrl, diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt index 5b1b1741a9..95b1c2d131 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt @@ -251,6 +251,35 @@ class VaultItemScreenTest : BitwardenComposeTest() { } } + @Test + fun `archived icon should be displayed according to state`() { + mutableStateFlow.update { + DEFAULT_STATE.copy( + viewState = DEFAULT_LOGIN_VIEW_STATE.copy( + common = DEFAULT_COMMON.copy( + archived = false, + ), + ), + ) + } + composeTestRule + .onNodeWithText(text = "Archived") + .assertDoesNotExist() + + mutableStateFlow.update { + DEFAULT_STATE.copy( + viewState = DEFAULT_LOGIN_VIEW_STATE.copy( + common = DEFAULT_COMMON.copy( + archived = true, + ), + ), + ) + } + composeTestRule + .onNodeWithText(text = "Archived") + .assertIsDisplayed() + } + @Test fun `favorite icon should be displayed according to state`() { mutableStateFlow.update { @@ -3222,6 +3251,7 @@ private val DEFAULT_COMMON: VaultItemState.ViewState.Content.Common = canAssignToCollections = true, canEdit = true, favorite = false, + archived = false, passwordHistoryCount = null, iconData = IconData.Local(iconRes = BitwardenDrawable.ic_globe), relatedLocations = persistentListOf(), @@ -3308,6 +3338,7 @@ private val EMPTY_COMMON: VaultItemState.ViewState.Content.Common = canAssignToCollections = true, canEdit = true, favorite = false, + archived = false, passwordHistoryCount = null, iconData = IconData.Local(iconRes = BitwardenDrawable.ic_globe), relatedLocations = persistentListOf(), diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt index dd7d43e334..9a19611b75 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt @@ -2709,6 +2709,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { canAssignToCollections = true, canEdit = true, favorite = false, + archived = false, passwordHistoryCount = 1, iconData = IconData.Local(BitwardenDrawable.ic_globe), relatedLocations = persistentListOf(), diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/util/VaultItemTestUtil.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/util/VaultItemTestUtil.kt index f8b4369979..c866a37269 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/util/VaultItemTestUtil.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/util/VaultItemTestUtil.kt @@ -182,6 +182,7 @@ fun createCommonContent( canAssignToCollections = true, canEdit = true, favorite = false, + archived = false, passwordHistoryCount = null, relatedLocations = persistentListOf(), iconData = IconData.Local(iconResId), @@ -246,6 +247,7 @@ fun createCommonContent( canAssignToCollections = true, canEdit = true, favorite = false, + archived = false, passwordHistoryCount = 1, relatedLocations = persistentListOf(), iconData = IconData.Local(iconResId), diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index beb1ba205c..fd6d35b2c4 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -1175,5 +1175,6 @@ Do you want to switch to this account? Failed to migrate items to %s Search archive Archive + Archived Hidden items