Add keys and animation to all content items

This commit is contained in:
Patrick Honkonen
2025-02-26 17:10:10 -05:00
parent 33c3fd28e9
commit 07d3849c4b
7 changed files with 245 additions and 155 deletions

View File

@@ -61,7 +61,7 @@ fun VaultItemCardContent(
onExpandClick = { isExpanded = !isExpanded },
)
cardState.cardholderName?.let { cardholderName ->
item {
item(key = "cardholderName") {
BitwardenTextField(
label = stringResource(id = R.string.cardholder_name),
value = cardholderName,
@@ -77,12 +77,13 @@ fun VaultItemCardContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
cardState.number?.let { numberData ->
item {
item(key = "cardNumber") {
BitwardenPasswordField(
label = stringResource(id = R.string.number),
value = numberData.number,
@@ -109,13 +110,14 @@ fun VaultItemCardContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
if (cardState.brand != null && cardState.brand != VaultCardBrand.SELECT) {
item {
item(key = "cardBrand") {
BitwardenTextField(
label = stringResource(id = R.string.brand),
value = cardState.brand.shortName(),
@@ -131,13 +133,14 @@ fun VaultItemCardContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
cardState.expiration?.let { expiration ->
item {
item(key = "expiration") {
BitwardenTextField(
label = stringResource(id = R.string.expiration),
value = expiration,
@@ -153,13 +156,14 @@ fun VaultItemCardContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
cardState.securityCode?.let { securityCodeData ->
item {
item(key = "securityCodeData_$securityCodeData") {
BitwardenPasswordField(
label = stringResource(id = R.string.security_code),
value = securityCodeData.code,
@@ -188,20 +192,22 @@ fun VaultItemCardContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.notes?.let { notes ->
item {
item(key = "notes") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.additional_options),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(8.dp))
BitwardenTextField(
@@ -222,58 +228,69 @@ fun VaultItemCardContent(
cardStyle = CardStyle.Full,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.customFields.takeUnless { it.isEmpty() }?.let { customFields ->
item {
item(key = "customFieldsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.custom_fields),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
}
items(customFields) { customField ->
itemsIndexed(
items = customFields,
key = { index, _ -> "customField_$index" },
) { _, customField ->
Spacer(modifier = Modifier.height(height = 8.dp))
CustomField(
customField = customField,
onCopyCustomHiddenField =
vaultCommonItemTypeHandlers.onCopyCustomHiddenField,
vaultCommonItemTypeHandlers.onCopyCustomHiddenField,
onCopyCustomTextField =
vaultCommonItemTypeHandlers.onCopyCustomTextField,
vaultCommonItemTypeHandlers.onCopyCustomTextField,
onShowHiddenFieldClick =
vaultCommonItemTypeHandlers.onShowHiddenFieldClick,
vaultCommonItemTypeHandlers.onShowHiddenFieldClick,
cardStyle = CardStyle.Full,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.attachments.takeUnless { it?.isEmpty() == true }?.let { attachments ->
item {
item(key = "attachmentsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.attachments),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
}
itemsIndexed(attachments) { index, attachmentItem ->
itemsIndexed(
items = attachments,
key = { index, _ -> "attachment_$index" },
) { index, attachmentItem ->
AttachmentItemContent(
modifier = Modifier
.testTag("CipherAttachment")
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
attachmentItem = attachmentItem,
onAttachmentDownloadClick = vaultCommonItemTypeHandlers
.onAttachmentDownloadClick,
@@ -282,7 +299,7 @@ fun VaultItemCardContent(
}
}
item {
item(key = "lastUpdated") {
Spacer(modifier = Modifier.height(height = 16.dp))
VaultItemUpdateText(
header = "${stringResource(id = R.string.date_updated)}: ",
@@ -290,7 +307,8 @@ fun VaultItemCardContent(
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 12.dp),
.padding(horizontal = 12.dp)
.animateItem(),
)
}
item {

View File

@@ -60,7 +60,7 @@ fun VaultItemIdentityContent(
onExpandClick = { isExpanded = !isExpanded },
)
identityState.identityName?.let { identityName ->
item {
item(key = "identityName") {
IdentityCopyField(
label = stringResource(id = R.string.identity_name),
value = identityName,
@@ -76,12 +76,13 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
identityState.username?.let { username ->
item {
item(key = "username") {
IdentityCopyField(
label = stringResource(id = R.string.username),
value = username,
@@ -97,12 +98,13 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
identityState.company?.let { company ->
item {
item(key = "company") {
IdentityCopyField(
label = stringResource(id = R.string.company),
value = company,
@@ -118,12 +120,13 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
identityState.ssn?.let { ssn ->
item {
item(key = "ssn") {
IdentityCopyField(
label = stringResource(id = R.string.ssn),
value = ssn,
@@ -139,12 +142,13 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
identityState.passportNumber?.let { passportNumber ->
item {
item(key = "passportNumber") {
IdentityCopyField(
label = stringResource(id = R.string.passport_number),
value = passportNumber,
@@ -160,12 +164,13 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
identityState.licenseNumber?.let { licenseNumber ->
item {
item(key = "licenseNumber") {
IdentityCopyField(
label = stringResource(id = R.string.license_number),
value = licenseNumber,
@@ -181,12 +186,13 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
identityState.email?.let { email ->
item {
item(key = "email") {
IdentityCopyField(
label = stringResource(id = R.string.email),
value = email,
@@ -202,12 +208,13 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
identityState.phone?.let { phone ->
item {
item(key = "phone") {
IdentityCopyField(
label = stringResource(id = R.string.phone),
value = phone,
@@ -223,12 +230,13 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
identityState.address?.let { address ->
item {
item(key = "address") {
IdentityCopyField(
label = stringResource(id = R.string.address),
value = address,
@@ -244,19 +252,21 @@ fun VaultItemIdentityContent(
),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.notes?.let { notes ->
item {
item(key = "notes") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.additional_options),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(8.dp))
IdentityCopyField(
@@ -269,23 +279,28 @@ fun VaultItemIdentityContent(
cardStyle = CardStyle.Full,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.customFields.takeUnless { it.isEmpty() }?.let { customFields ->
item {
item(key = "customFieldsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.custom_fields),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
}
items(customFields) { customField ->
items(
items = customFields,
key = { "customField_$it" },
) { customField ->
Spacer(modifier = Modifier.height(height = 8.dp))
CustomField(
customField = customField,
@@ -295,29 +310,35 @@ fun VaultItemIdentityContent(
cardStyle = CardStyle.Full,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.attachments.takeUnless { it?.isEmpty() == true }?.let { attachments ->
item {
item(key = "attachmentsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.attachments),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
}
itemsIndexed(attachments) { index, attachmentItem ->
itemsIndexed(
items = attachments,
key = { index, _ -> "attachment_$index" },
) { index, attachmentItem ->
AttachmentItemContent(
modifier = Modifier
.testTag("CipherAttachment")
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
attachmentItem = attachmentItem,
onAttachmentDownloadClick = vaultCommonItemTypeHandlers
.onAttachmentDownloadClick,
@@ -326,7 +347,7 @@ fun VaultItemIdentityContent(
}
}
item {
item(key = "lastUpdated") {
Spacer(modifier = Modifier.height(height = 16.dp))
VaultItemUpdateText(
header = "${stringResource(id = R.string.date_updated)}: ",
@@ -334,7 +355,8 @@ fun VaultItemIdentityContent(
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 12.dp),
.padding(horizontal = 12.dp)
.animateItem(),
)
}
item {

View File

@@ -72,21 +72,22 @@ fun VaultItemLoginContent(
onExpandClick = { isExpanded = !isExpanded },
)
if (loginItemState.hasLoginCredentials) {
item {
item(key = "loginCredentialsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.login_credentials),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
}
}
loginItemState.username?.let { username ->
item {
item(key = "username") {
UsernameField(
username = username,
onCopyUsernameClick = vaultLoginItemTypeHandlers.onCopyUsernameClick,
@@ -96,13 +97,14 @@ fun VaultItemLoginContent(
?: CardStyle.Full,
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
}
}
loginItemState.passwordData?.let { passwordData ->
item {
item(key = "passwordData") {
PasswordField(
passwordData = passwordData,
onShowPasswordClick = vaultLoginItemTypeHandlers.onShowPasswordClick,
@@ -114,25 +116,27 @@ fun VaultItemLoginContent(
?: CardStyle.Full,
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
}
}
loginItemState.fido2CredentialCreationDateText?.let { creationDate ->
item {
item(key = "creationDate") {
Spacer(modifier = Modifier.height(8.dp))
Fido2CredentialField(
creationDate = creationDate(),
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
}
}
loginItemState.totpCodeItemData?.let { totpCodeItemData ->
item {
item(key = "totpCode") {
Spacer(modifier = Modifier.height(8.dp))
TotpField(
totpCodeItemData = totpCodeItemData,
@@ -142,25 +146,30 @@ fun VaultItemLoginContent(
.onAuthenticatorHelpToolTipClick,
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
}
}
loginItemState.uris.takeUnless { it.isEmpty() }?.let { uris ->
item {
item(key = "urisHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.autofill_options),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
}
itemsIndexed(uris) { index, uriData ->
itemsIndexed(
items = uris,
key = { index, _ -> "uri_$index" },
) { index, uriData ->
UriField(
uriData = uriData,
onCopyUriClick = vaultLoginItemTypeHandlers.onCopyUriClick,
@@ -168,20 +177,22 @@ fun VaultItemLoginContent(
cardStyle = uris.toListItemCardStyle(index = index, dividerPadding = 0.dp),
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
}
}
commonState.notes?.let { notes ->
item {
item(key = "notes") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.additional_options),
modifier = Modifier
.standardHorizontalMargin()
.padding(horizontal = 16.dp)
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
Spacer(modifier = Modifier.height(8.dp))
NotesField(
@@ -189,57 +200,68 @@ fun VaultItemLoginContent(
onCopyAction = vaultCommonItemTypeHandlers.onCopyNotesClick,
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
}
}
commonState.customFields.takeUnless { it.isEmpty() }?.let { customFields ->
item {
item(key = "customFieldsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.custom_fields),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
}
items(customFields) { customField ->
itemsIndexed(
items = customFields,
key = { index, _ -> "customField_$index" },
) { _, customField ->
Spacer(modifier = Modifier.height(height = 8.dp))
CustomField(
customField = customField,
onCopyCustomHiddenField =
vaultCommonItemTypeHandlers.onCopyCustomHiddenField,
vaultCommonItemTypeHandlers.onCopyCustomHiddenField,
onCopyCustomTextField =
vaultCommonItemTypeHandlers.onCopyCustomTextField,
vaultCommonItemTypeHandlers.onCopyCustomTextField,
onShowHiddenFieldClick =
vaultCommonItemTypeHandlers.onShowHiddenFieldClick,
vaultCommonItemTypeHandlers.onShowHiddenFieldClick,
cardStyle = CardStyle.Full,
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
}
}
commonState.attachments.takeUnless { it?.isEmpty() == true }?.let { attachments ->
item {
item(key = "attachmentsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.attachments),
modifier = Modifier
.standardHorizontalMargin()
.padding(horizontal = 16.dp)
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
}
itemsIndexed(attachments) { index, attachmentItem ->
itemsIndexed(
items = attachments,
key = { index, _ -> "attachment_$index" },
) { index, attachmentItem ->
AttachmentItemContent(
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
attachmentItem = attachmentItem,
cardStyle = attachments.toListItemCardStyle(index = index),
onAttachmentDownloadClick = vaultCommonItemTypeHandlers
@@ -248,7 +270,7 @@ fun VaultItemLoginContent(
}
}
item {
item(key = "lastUpdated") {
Spacer(modifier = Modifier.height(16.dp))
VaultItemUpdateText(
header = "${stringResource(id = R.string.date_updated)}: ",
@@ -256,12 +278,13 @@ fun VaultItemLoginContent(
modifier = Modifier
.standardHorizontalMargin()
.padding(horizontal = 12.dp)
.fillMaxWidth(),
.fillMaxWidth()
.animateItem(),
)
}
loginItemState.passwordRevisionDate?.let { revisionDate ->
item {
item(key = "revisionDate") {
Spacer(modifier = Modifier.height(height = 4.dp))
VaultItemUpdateText(
header = "${stringResource(id = R.string.date_password_updated)}: ",
@@ -269,13 +292,14 @@ fun VaultItemLoginContent(
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 12.dp),
.padding(horizontal = 12.dp)
.animateItem(),
)
}
}
loginItemState.passwordHistoryCount?.let { passwordHistoryCount ->
item {
item(key = "passwordHistoryCount") {
Spacer(modifier = Modifier.height(height = 4.dp))
BitwardenHyperTextLink(
annotatedResId = R.string.password_history_count,
@@ -287,7 +311,8 @@ fun VaultItemLoginContent(
modifier = Modifier
.wrapContentWidth()
.standardHorizontalMargin()
.padding(horizontal = 12.dp),
.padding(horizontal = 12.dp)
.animateItem(),
)
}
}

View File

@@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -58,7 +57,7 @@ fun VaultItemSecureNoteContent(
onExpandClick = { isExpanded = !isExpanded },
)
commonState.notes?.let { notes ->
item {
item(key = "notes") {
Spacer(modifier = Modifier.height(8.dp))
BitwardenTextField(
label = stringResource(id = R.string.notes),
@@ -78,59 +77,70 @@ fun VaultItemSecureNoteContent(
cardStyle = CardStyle.Full,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.customFields.takeUnless { it.isEmpty() }?.let { customFields ->
item {
item(key = "customFieldsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.custom_fields),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
}
items(customFields) { customField ->
itemsIndexed(
items = customFields,
key = { index, _ -> "customField_$index" },
) { _, customField ->
Spacer(modifier = Modifier.height(height = 8.dp))
CustomField(
customField = customField,
onCopyCustomHiddenField =
vaultCommonItemTypeHandlers.onCopyCustomHiddenField,
vaultCommonItemTypeHandlers.onCopyCustomHiddenField,
onCopyCustomTextField =
vaultCommonItemTypeHandlers.onCopyCustomTextField,
vaultCommonItemTypeHandlers.onCopyCustomTextField,
onShowHiddenFieldClick =
vaultCommonItemTypeHandlers.onShowHiddenFieldClick,
vaultCommonItemTypeHandlers.onShowHiddenFieldClick,
cardStyle = CardStyle.Full,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.attachments.takeUnless { it?.isEmpty() == true }?.let { attachments ->
item {
item(key = "attachmentsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.attachments),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
}
itemsIndexed(attachments) { index, attachmentItem ->
itemsIndexed(
items = attachments,
key = { index, _ -> "attachment_$index" },
) { index, attachmentItem ->
AttachmentItemContent(
modifier = Modifier
.testTag("CipherAttachment")
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
attachmentItem = attachmentItem,
onAttachmentDownloadClick = vaultCommonItemTypeHandlers
.onAttachmentDownloadClick,
@@ -139,14 +149,15 @@ fun VaultItemSecureNoteContent(
}
}
item {
item(key = "lastUpdated") {
Spacer(modifier = Modifier.height(height = 16.dp))
Row(
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 12.dp)
.semantics(mergeDescendants = true) { },
.semantics(mergeDescendants = true) { }
.animateItem(),
) {
Text(
text = "${stringResource(id = R.string.date_updated)}: ",

View File

@@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -58,7 +57,7 @@ fun VaultItemSshKeyContent(
isExpanded = isExpanded,
onExpandClick = { isExpanded = !isExpanded },
)
item {
item(key = "publicKey") {
Spacer(modifier = Modifier.height(8.dp))
BitwardenTextField(
label = stringResource(id = R.string.public_key),
@@ -78,11 +77,12 @@ fun VaultItemSshKeyContent(
modifier = Modifier
.testTag("SshKeyItemPublicKeyEntry")
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
item {
item(key = "privateKey") {
BitwardenPasswordField(
label = stringResource(id = R.string.private_key),
value = sshKeyItemState.privateKey,
@@ -104,11 +104,12 @@ fun VaultItemSshKeyContent(
modifier = Modifier
.testTag("SshKeyItemPrivateKeyEntry")
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
item {
item(key = "fingerprint") {
BitwardenTextField(
label = stringResource(id = R.string.fingerprint),
value = sshKeyItemState.fingerprint,
@@ -127,19 +128,21 @@ fun VaultItemSshKeyContent(
modifier = Modifier
.testTag("SshKeyItemFingerprintEntry")
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
commonState.notes?.let { notes ->
item {
item(key = "notes") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.additional_options),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(8.dp))
BitwardenTextField(
@@ -160,57 +163,68 @@ fun VaultItemSshKeyContent(
cardStyle = CardStyle.Full,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.customFields.takeUnless { it.isEmpty() }?.let { customFields ->
item {
item(key = "customFieldsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.custom_fields),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
}
items(customFields) { customField ->
itemsIndexed(
items = customFields,
key = { index, _ -> "customField_$index" },
) { _, customField ->
Spacer(modifier = Modifier.height(height = 8.dp))
CustomField(
customField = customField,
onCopyCustomHiddenField =
vaultCommonItemTypeHandlers.onCopyCustomHiddenField,
vaultCommonItemTypeHandlers.onCopyCustomHiddenField,
onCopyCustomTextField =
vaultCommonItemTypeHandlers.onCopyCustomTextField,
vaultCommonItemTypeHandlers.onCopyCustomTextField,
onShowHiddenFieldClick =
vaultCommonItemTypeHandlers.onShowHiddenFieldClick,
vaultCommonItemTypeHandlers.onShowHiddenFieldClick,
cardStyle = CardStyle.Full,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
)
}
}
commonState.attachments.takeUnless { it?.isEmpty() == true }?.let { attachments ->
item {
item(key = "attachmentsHeader") {
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = R.string.attachments),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 16.dp),
.padding(horizontal = 16.dp)
.animateItem(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
}
itemsIndexed(attachments) { index, attachmentItem ->
itemsIndexed(
items = attachments,
key = { index, _ -> "attachment_$index" },
) { index, attachmentItem ->
AttachmentItemContent(
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin()
.animateItem(),
attachmentItem = attachmentItem,
onAttachmentDownloadClick = vaultCommonItemTypeHandlers
.onAttachmentDownloadClick,
@@ -219,7 +233,7 @@ fun VaultItemSshKeyContent(
}
}
item {
item(key = "lastUpdated") {
Spacer(modifier = Modifier.height(height = 16.dp))
VaultItemUpdateText(
header = "${stringResource(id = R.string.date_updated)}: ",
@@ -228,6 +242,7 @@ fun VaultItemSshKeyContent(
.fillMaxWidth()
.standardHorizontalMargin()
.padding(horizontal = 12.dp)
.animateItem()
.testTag("SshKeyItemLastUpdated"),
)
}

View File

@@ -46,7 +46,7 @@ private const val EXPANDABLE_THRESHOLD = 2
/**
* Reusable composable for displaying the cipher name, favorite status, and related locations.
*/
@Suppress("LongMethod")
@Suppress("LongMethod", "LongParameterList")
fun LazyListScope.itemHeader(
value: String,
isFavorite: Boolean,
@@ -256,9 +256,9 @@ private fun LazyItemScope.ItemLocationListItem(
}
//region Previews
//@Composable
//@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
//private fun ItemHeader_LocalIcon_Preview() {
// @Composable
// @Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
// private fun ItemHeader_LocalIcon_Preview() {
// BitwardenTheme {
// ItemHeader(
// value = "Login without favicon",
@@ -269,11 +269,11 @@ private fun LazyItemScope.ItemLocationListItem(
// relatedLocations = persistentListOf(),
// )
// }
//}
// }
//
//@Composable
//@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
//private fun ItemHeader_NetworkIcon_Preview() {
// @Composable
// @Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
// private fun ItemHeader_NetworkIcon_Preview() {
// BitwardenTheme {
// ItemHeader(
// value = "Login with favicon",
@@ -285,11 +285,11 @@ private fun LazyItemScope.ItemLocationListItem(
// relatedLocations = persistentListOf(),
// )
// }
//}
// }
//
//@Composable
//@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
//private fun ItemHeader_Organization_Preview() {
// @Composable
// @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
// private fun ItemHeader_Organization_Preview() {
// BitwardenTheme {
// ItemHeader(
// value = "Login without favicon",
@@ -302,11 +302,11 @@ private fun LazyItemScope.ItemLocationListItem(
// ),
// )
// }
//}
// }
//
//@Composable
//@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
//private fun ItemNameField_Org_SingleCollection_Preview() {
// @Composable
// @Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
// private fun ItemNameField_Org_SingleCollection_Preview() {
// BitwardenTheme {
// ItemHeader(
// value = "Login without favicon",
@@ -320,11 +320,11 @@ private fun LazyItemScope.ItemLocationListItem(
// ),
// )
// }
//}
// }
//
//@Composable
//@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
//private fun ItemNameField_Org_MultiCollection_Preview() {
// @Composable
// @Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
// private fun ItemNameField_Org_MultiCollection_Preview() {
// BitwardenTheme {
// ItemHeader(
// value = "Login without favicon",
@@ -339,11 +339,11 @@ private fun LazyItemScope.ItemLocationListItem(
// ),
// )
// }
//}
// }
//
//@Composable
//@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
//private fun ItemNameField_Org_SingleCollection_Folder_Preview() {
// @Composable
// @Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
// private fun ItemNameField_Org_SingleCollection_Folder_Preview() {
// BitwardenTheme {
// ItemHeader(
// value = "Note without favicon",
@@ -358,5 +358,5 @@ private fun LazyItemScope.ItemLocationListItem(
// ),
// )
// }
//}
// }
//endregion Previews

View File

@@ -3341,7 +3341,6 @@ class VaultItemViewModelTest : BaseViewModelTest() {
shouldManageResetPassword = false,
shouldUseKeyConnector = false,
role = OrganizationType.OWNER,
shouldManagePolicies = false,
),
),
),