Add send icons to row items. (#496)

This commit is contained in:
David Perez
2024-01-04 20:18:41 -06:00
committed by Álison Fernandes
parent 10bad26c95
commit 02c8f4bfec
12 changed files with 186 additions and 20 deletions

View File

@@ -5,9 +5,11 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -23,22 +25,25 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.components.model.IconResource
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
/**
* A Composable function that displays a row item.
*
* @param label The primary text label to display for the item.
* @param supportingLabel An secondary text label to display beneath the label.
* @param startIcon The [Painter] object used to draw the icon at the start of the item.
* @param onClick The lambda to be invoked when the item is clicked.
* @param modifier An optional [Modifier] for this Composable, defaulting to an empty Modifier.
* This allows the caller to specify things like padding, size, etc.
* @param selectionDataList A list of all the selection items to be displayed in the overflow
* dialog.
* @param modifier An optional [Modifier] for this Composable, defaulting to an empty Modifier.
* This allows the caller to specify things like padding, size, etc.
* @param supportingLabel An optional secondary text label to display beneath the label.
* @param trailingLabelIcons An optional list of small icons to be displayed after the [label].
*/
@Suppress("LongMethod")
@Composable
@@ -49,6 +54,7 @@ fun BitwardenListItem(
selectionDataList: List<SelectionItemData>,
modifier: Modifier = Modifier,
supportingLabel: String? = null,
trailingLabelIcons: List<IconResource> = emptyList(),
) {
var shouldShowDialog by remember { mutableStateOf(false) }
Row(
@@ -72,11 +78,28 @@ fun BitwardenListItem(
)
Column(modifier = Modifier.weight(1f)) {
Text(
text = label,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurface,
)
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = label,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurface,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(weight = 1f, fill = false),
)
trailingLabelIcons.forEach {
Spacer(modifier = Modifier.width(8.dp))
Icon(
painter = it.iconPainter,
contentDescription = it.contentDescription,
tint = MaterialTheme.colorScheme.secondary,
modifier = Modifier.size(16.dp),
)
}
}
supportingLabel?.let {
Text(

View File

@@ -78,6 +78,7 @@ fun SendContent(
startIcon = painterResource(id = it.type.iconRes),
label = it.name,
supportingLabel = it.deletionDate,
trailingLabelIcons = it.iconList,
onClick = { sendHandlers.onSendClick(it) },
onCopyClick = { sendHandlers.onCopySendClick(it) },
onEditClick = { sendHandlers.onEditSendClick(it) },

View File

@@ -9,7 +9,9 @@ import androidx.compose.ui.tooling.preview.Preview
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.components.BitwardenListItem
import com.x8bit.bitwarden.ui.platform.components.SelectionItemData
import com.x8bit.bitwarden.ui.platform.components.model.IconResource
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendStatusIcon
/**
* A Composable function that displays a row send item.
@@ -30,6 +32,7 @@ fun SendListItem(
label: String,
supportingLabel: String,
startIcon: Painter,
trailingLabelIcons: List<SendStatusIcon>,
onClick: () -> Unit,
onEditClick: () -> Unit,
onCopyClick: () -> Unit,
@@ -40,6 +43,12 @@ fun SendListItem(
label = label,
supportingLabel = supportingLabel,
startIcon = startIcon,
trailingLabelIcons = trailingLabelIcons.map {
IconResource(
iconPainter = painterResource(it.iconRes),
contentDescription = it.contentDescription(),
)
},
onClick = onClick,
selectionDataList = listOf(
SelectionItemData(
@@ -67,6 +76,7 @@ private fun SendListItem_preview() {
label = "Sample Label",
supportingLabel = "Jan 3, 2024, 10:35 AM",
startIcon = painterResource(id = R.drawable.ic_send_text),
trailingLabelIcons = emptyList(),
onClick = {},
onCopyClick = {},
onEditClick = {},

View File

@@ -12,6 +12,7 @@ import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.base.util.concat
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendStatusIcon
import com.x8bit.bitwarden.ui.tools.feature.send.util.toViewState
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemScreen
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -201,6 +202,7 @@ data class SendState(
val name: String,
val deletionDate: String,
val type: Type,
val iconList: List<SendStatusIcon>,
) : Parcelable {
/**
* Indicates the type of send this, a text or file.

View File

@@ -0,0 +1,31 @@
package com.x8bit.bitwarden.ui.tools.feature.send.model
import androidx.annotation.DrawableRes
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.asText
/**
* Represents the types of icons to be displayed with the send.
*/
enum class SendStatusIcon(
@DrawableRes val iconRes: Int,
val contentDescription: Text,
) {
DISABLED(
iconRes = R.drawable.ic_send_disabled,
contentDescription = R.string.disabled.asText(),
),
PASSWORD(
iconRes = R.drawable.ic_send_password,
contentDescription = R.string.password.asText(),
),
EXPIRED(
iconRes = R.drawable.ic_send_expired,
contentDescription = R.string.expired.asText(),
),
MAX_ACCESS_COUNT_REACHED(
iconRes = R.drawable.ic_send_max_access_count_reached,
contentDescription = R.string.maximum_access_count_reached.asText(),
),
}

View File

@@ -5,6 +5,8 @@ import com.bitwarden.core.SendView
import com.x8bit.bitwarden.data.vault.repository.model.SendData
import com.x8bit.bitwarden.ui.tools.feature.generator.util.toFormattedPattern
import com.x8bit.bitwarden.ui.tools.feature.send.SendState
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendStatusIcon
import java.time.Instant
private const val DELETION_DATE_PATTERN: String = "MMM d, uuuu, hh:mm a"
@@ -22,16 +24,30 @@ private fun List<SendView>.toSendContent(): SendState.ViewState.Content {
return SendState.ViewState.Content(
textTypeCount = this.count { it.type == SendType.TEXT },
fileTypeCount = this.count { it.type == SendType.FILE },
sendItems = this.map {
SendState.ViewState.Content.SendItem(
id = requireNotNull(it.id),
name = it.name,
deletionDate = it.deletionDate.toFormattedPattern(DELETION_DATE_PATTERN),
type = when (it.type) {
SendType.TEXT -> SendState.ViewState.Content.SendItem.Type.TEXT
SendType.FILE -> SendState.ViewState.Content.SendItem.Type.FILE
},
)
},
sendItems = this
.map { sendView ->
SendState.ViewState.Content.SendItem(
id = requireNotNull(sendView.id),
name = sendView.name,
deletionDate = sendView.deletionDate.toFormattedPattern(DELETION_DATE_PATTERN),
type = when (sendView.type) {
SendType.TEXT -> SendState.ViewState.Content.SendItem.Type.TEXT
SendType.FILE -> SendState.ViewState.Content.SendItem.Type.FILE
},
iconList = listOfNotNull(
SendStatusIcon.EXPIRED.takeIf {
sendView.expirationDate?.isBefore(Instant.now()) == true
},
sendView.password?.let { SendStatusIcon.PASSWORD },
SendStatusIcon.MAX_ACCESS_COUNT_REACHED.takeIf {
sendView.maxAccessCount?.let { maxCount ->
sendView.accessCount >= maxCount
} == true
},
SendStatusIcon.DISABLED.takeIf { sendView.disabled },
),
)
}
.sortedBy { it.name },
)
}