[#1162] Finish expandable trx item UI state

- Closes #1162
- Closes #1237
- Closes #1078
- This removes unused DangerousButton component and its related resources
- It fixes the Collapse button vector icon
- It brings send_failed and receive_failed states into the trx item UI
- It adds the fee part of the expandable item
- Its follow-up is #1047
- Changelog updated
This commit is contained in:
Honza Rychnovský 2024-04-03 09:18:46 +02:00 committed by GitHub
parent c8a14f0375
commit 2c45ab642b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 131 additions and 79 deletions

View File

@ -21,7 +21,7 @@ directly impact users rather than highlighting other key architectural updates.*
submission
### Changed
- The Transaction History UI has been incorporated into the Account screen and partly reworked according to the
- The Transaction History UI has been incorporated into the Account screen and completely reworked according to the
design guidelines
- Reworked Send screens flow and their look (e.g., Send Failure screen is now a modal dialog instead of a separate
screen)

View File

@ -57,7 +57,6 @@ private fun ButtonComposablePreview() {
TertiaryButton(onClick = { }, text = "Tertiary")
TertiaryButton(onClick = { }, text = "Tertiary", enabled = false)
NavigationButton(onClick = { }, text = "Navigation")
DangerousButton(onClick = { }, text = "Dangerous")
@Suppress("MagicNumber")
Row {
PrimaryButton(onClick = { }, text = "Button 1", modifier = Modifier.weight(0.5f))
@ -292,38 +291,6 @@ fun TertiaryButton(
}
}
@Composable
fun DangerousButton(
onClick: () -> Unit,
text: String,
modifier: Modifier = Modifier,
outerPaddingValues: PaddingValues =
PaddingValues(
horizontal = ZcashTheme.dimens.spacingNone,
vertical = ZcashTheme.dimens.spacingSmall
),
) {
Button(
shape = RectangleShape,
onClick = onClick,
modifier =
modifier.then(
Modifier
.fillMaxWidth()
.padding(outerPaddingValues)
.defaultMinSize(ZcashTheme.dimens.buttonWidth, ZcashTheme.dimens.buttonHeight)
),
colors = buttonColors(containerColor = ZcashTheme.colors.dangerous)
) {
Text(
style = MaterialTheme.typography.labelLarge,
textAlign = TextAlign.Center,
text = text,
color = ZcashTheme.colors.onDangerous
)
}
}
@Suppress("LongParameterList")
fun Modifier.shadow(
contentColor: Color = Color.Black,

View File

@ -3,6 +3,7 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
@ -232,9 +233,9 @@ fun Tiny(
@Suppress("LongParameterList")
fun TextWithIcon(
text: String,
imageVector: ImageVector,
iconVector: ImageVector,
modifier: Modifier = Modifier,
imageContentDescription: String? = null,
iconContentDescription: String? = null,
maxLines: Int = Int.MAX_VALUE,
overflow: TextOverflow = TextOverflow.Clip,
textAlign: TextAlign = TextAlign.Start,
@ -248,9 +249,9 @@ fun TextWithIcon(
.then(modifier),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = imageVector,
contentDescription = imageContentDescription
Image(
imageVector = iconVector,
contentDescription = iconContentDescription
)
Spacer(modifier = Modifier.padding(3.dp))

View File

@ -30,8 +30,6 @@ data class ExtendedColors(
val layoutStroke: Color,
val overlay: Color,
val highlight: Color,
val dangerous: Color,
val onDangerous: Color,
val reference: Color,
val disabledButtonColor: Color,
val disabledButtonTextColor: Color,
@ -47,7 +45,7 @@ data class ExtendedColors(
val radioButtonColor: Color,
val radioButtonTextColor: Color,
val historyBackgroundColor: Color,
val historySendColor: Color,
val historyRedColor: Color,
) {
@Composable
fun surfaceGradient() =

View File

@ -61,9 +61,6 @@ internal object Dark {
val overlay = Color(0x22000000)
val highlight = Color(0xFFFFD800)
val dangerous = Color(0xFFFF0B0B)
val onDangerous = Color(0xFFFFFFFF)
val reference = Color(0xFFFFFFFF)
val disabledButtonColor = Color(0xFFB7B7B7)
@ -72,7 +69,7 @@ internal object Dark {
val buttonShadowColor = Color(0xFFFFFFFF)
val historyBackgroundColor = Color(0xFFF6F6F6)
val historySendColor = Color(0xFFF40202)
val historyRedColor = Color(0xFFF40202)
}
internal object Light {
@ -122,9 +119,6 @@ internal object Light {
val overlay = Color(0x22000000)
val highlight = Color(0xFFFFD800)
val dangerous = Color(0xFFFF0B0B)
val onDangerous = Color(0xFFFFFFFF)
val reference = Color(0xFF000000)
val disabledButtonColor = Color(0xFFB7B7B7)
@ -132,7 +126,7 @@ internal object Light {
val buttonShadowColor = Color(0xFF000000)
val historyBackgroundColor = Color(0xFFF6F6F6)
val historySendColor = Color(0xFFF40202)
val historyRedColor = Color(0xFFF40202)
}
internal val DarkColorPalette =
@ -183,8 +177,6 @@ internal val DarkExtendedColorPalette =
layoutStroke = Dark.layoutStroke,
overlay = Dark.overlay,
highlight = Dark.highlight,
dangerous = Dark.dangerous,
onDangerous = Dark.onDangerous,
disabledButtonTextColor = Dark.disabledButtonTextColor,
disabledButtonColor = Dark.disabledButtonColor,
reference = Dark.reference,
@ -200,7 +192,7 @@ internal val DarkExtendedColorPalette =
radioButtonColor = Dark.radioButtonColor,
radioButtonTextColor = Dark.radioButtonTextColor,
historyBackgroundColor = Dark.historyBackgroundColor,
historySendColor = Dark.historySendColor,
historyRedColor = Dark.historyRedColor,
)
internal val LightExtendedColorPalette =
@ -227,8 +219,6 @@ internal val LightExtendedColorPalette =
layoutStroke = Light.layoutStroke,
overlay = Light.overlay,
highlight = Light.highlight,
dangerous = Light.dangerous,
onDangerous = Light.onDangerous,
disabledButtonTextColor = Light.disabledButtonTextColor,
disabledButtonColor = Light.disabledButtonColor,
reference = Light.reference,
@ -244,7 +234,7 @@ internal val LightExtendedColorPalette =
radioButtonColor = Light.radioButtonColor,
radioButtonTextColor = Light.radioButtonTextColor,
historyBackgroundColor = Light.historyBackgroundColor,
historySendColor = Light.historySendColor,
historyRedColor = Light.historyRedColor,
)
@Suppress("CompositionLocalAllowlist")
@ -273,8 +263,6 @@ internal val LocalExtendedColors =
layoutStroke = Color.Unspecified,
overlay = Color.Unspecified,
highlight = Color.Unspecified,
dangerous = Color.Unspecified,
onDangerous = Color.Unspecified,
disabledButtonTextColor = Color.Unspecified,
disabledButtonColor = Color.Unspecified,
reference = Color.Unspecified,
@ -290,6 +278,6 @@ internal val LocalExtendedColors =
radioButtonColor = Color.Unspecified,
radioButtonTextColor = Color.Unspecified,
historyBackgroundColor = Color.Unspecified,
historySendColor = Color.Unspecified,
historyRedColor = Color.Unspecified,
)
}

View File

@ -165,6 +165,9 @@ data class TransactionItemTextStyles(
val content: TextStyle,
val contentMedium: TextStyle,
val contentUnderline: TextStyle,
val contentLineThrough: TextStyle,
val feeFirstPart: TextStyle,
val feeSecondPart: TextStyle,
)
@Immutable
@ -342,6 +345,21 @@ val LocalExtendedTypography =
fontStyle = FontStyle.Italic,
textDecoration = TextDecoration.Underline
),
contentLineThrough =
PrimaryTypography.bodySmall.copy(
fontSize = 13.sp,
textDecoration = TextDecoration.LineThrough
),
feeFirstPart =
PrimaryTypography.bodySmall.copy(
fontSize = 13.sp,
fontWeight = FontWeight.SemiBold
),
feeSecondPart =
PrimaryTypography.bodySmall.copy(
fontSize = 8.sp,
fontWeight = FontWeight.SemiBold
),
),
)
}

View File

@ -42,6 +42,7 @@ import cash.z.ecc.android.sdk.model.FirstClassByteArray
import cash.z.ecc.android.sdk.model.TransactionOverview
import cash.z.ecc.android.sdk.model.TransactionRecipient
import cash.z.ecc.android.sdk.model.TransactionState
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.toZecString
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.CircularMidProgressIndicator
@ -55,6 +56,7 @@ import co.electriccoin.zcash.ui.screen.account.fixture.TransactionsFixture
import co.electriccoin.zcash.ui.screen.account.model.TransactionUi
import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
import co.electriccoin.zcash.ui.screen.account.model.TrxItemState
import co.electriccoin.zcash.ui.screen.send.view.DEFAULT_LESS_THAN_FEE
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList
import java.text.DateFormat
@ -214,7 +216,7 @@ private fun HistoryItem(
TransactionExtendedState.SEND_FAILED -> {
typeText = stringResource(id = R.string.account_history_item_send_failed)
typeIcon = ImageVector.vectorResource(R.drawable.ic_trx_send_icon)
textColor = ZcashTheme.colors.dangerous
textColor = ZcashTheme.colors.historyRedColor
textStyle = ZcashTheme.extendedTypography.transactionItemStyles.titleFailed
}
@ -233,7 +235,7 @@ private fun HistoryItem(
TransactionExtendedState.RECEIVE_FAILED -> {
typeText = stringResource(id = R.string.account_history_item_receive_failed)
typeIcon = ImageVector.vectorResource(R.drawable.ic_trx_receive_icon)
textColor = ZcashTheme.colors.dangerous
textColor = ZcashTheme.colors.historyRedColor
textStyle = ZcashTheme.extendedTypography.transactionItemStyles.titleFailed
}
}
@ -338,19 +340,31 @@ private fun HistoryItemCollapsedMainPart(
Spacer(modifier = Modifier.weight(1f))
val valueTextStyle: TextStyle
val valueTextColor: Color
if (transaction.overview.getExtendedState().isFailed()) {
valueTextStyle = ZcashTheme.extendedTypography.transactionItemStyles.contentLineThrough
valueTextColor = ZcashTheme.colors.historyRedColor
} else {
valueTextStyle = ZcashTheme.extendedTypography.transactionItemStyles.valueFirstPart
valueTextColor =
if (transaction.overview.isSentTransaction) {
ZcashTheme.colors.historyRedColor
} else {
ZcashTheme.colors.textCommon
}
}
// TODO [#1047]: Representing Zatoshi amount
// TODO [#1047]: https://github.com/Electric-Coin-Company/zashi-android/issues/1047
StyledBalance(
balanceString = transaction.overview.netValue.toZecString(),
textStyles =
Pair(
first = ZcashTheme.extendedTypography.transactionItemStyles.valueFirstPart,
first = valueTextStyle,
second = ZcashTheme.extendedTypography.transactionItemStyles.valueSecondPart
),
textColor =
if (transaction.overview.isSentTransaction) {
ZcashTheme.colors.historySendColor
} else {
ZcashTheme.colors.textCommon
},
textColor = valueTextColor,
prefix =
if (transaction.overview.isSentTransaction) {
stringResource(id = R.string.account_history_item_sent_prefix)
@ -446,7 +460,7 @@ private fun HistoryItemExpandedAddressPart(
text = stringResource(id = R.string.account_history_item_tap_to_copy),
style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textDescription,
imageVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
modifier =
Modifier
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
@ -488,7 +502,11 @@ private fun HistoryItemExpandedPart(
) {
Column(modifier = modifier) {
if (transaction.messages.containsValidMemo()) {
HistoryItemMessagePart(transaction.messages!!.toPersistentList(), onAction)
HistoryItemMessagePart(
messages = transaction.messages!!.toPersistentList(),
state = transaction.overview.getExtendedState(),
onAction = onAction
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
}
@ -500,11 +518,15 @@ private fun HistoryItemExpandedPart(
Spacer(modifier = (Modifier.height(ZcashTheme.dimens.spacingDefault)))
HistoryItemTransactionFeePart(fee = transaction.overview.feePaid)
Spacer(modifier = (Modifier.height(ZcashTheme.dimens.spacingLarge)))
TextWithIcon(
text = stringResource(id = R.string.account_history_item_collapse_transaction),
style = ZcashTheme.extendedTypography.transactionItemStyles.contentUnderline,
color = ZcashTheme.colors.textDescription,
imageVector = ImageVector.vectorResource(id = R.drawable.ic_trx_collapse),
iconVector = ImageVector.vectorResource(id = R.drawable.ic_trx_collapse),
modifier =
Modifier
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
@ -567,7 +589,7 @@ private fun HistoryItemTransactionIdPart(
text = stringResource(id = R.string.account_history_item_tap_to_copy),
style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textDescription,
imageVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
modifier =
Modifier
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
@ -618,13 +640,66 @@ private fun HistoryItemTransactionIdPart(
}
@Composable
private fun HistoryItemMessagePart(
messages: ImmutableList<String>,
onAction: (TrxItemAction) -> Unit,
private fun HistoryItemTransactionFeePart(
fee: Zatoshi?,
modifier: Modifier = Modifier
) {
Column(modifier = modifier) {
Text(
text = stringResource(id = R.string.account_history_item_transaction_fee),
style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textDescription,
)
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingSmall))
if (fee == null) {
Text(
text =
stringResource(
id = R.string.account_history_item_transaction_fee_typical,
Zatoshi(DEFAULT_LESS_THAN_FEE).toZecString()
),
style = ZcashTheme.extendedTypography.transactionItemStyles.feeFirstPart,
color = ZcashTheme.colors.textDescription,
)
} else {
// TODO [#1047]: Representing Zatoshi amount
// TODO [#1047]: https://github.com/Electric-Coin-Company/zashi-android/issues/1047
StyledBalance(
balanceString = fee.toZecString(),
textStyles =
Pair(
first = ZcashTheme.extendedTypography.transactionItemStyles.feeFirstPart,
second = ZcashTheme.extendedTypography.transactionItemStyles.feeSecondPart
),
textColor = ZcashTheme.colors.textDescription
)
}
}
}
@Composable
private fun HistoryItemMessagePart(
messages: ImmutableList<String>,
state: TransactionExtendedState,
onAction: (TrxItemAction) -> Unit,
modifier: Modifier = Modifier,
) {
// TODO [#1315]: Proper more messages in transaction displaying
// TODO [#1315]: https://github.com/Electric-Coin-Company/zashi-android/issues/1315
val composedMessage = messages.joinToString(separator = "\n\n")
val textStyle: TextStyle
val textColor: Color
if (state.isFailed()) {
textStyle = ZcashTheme.extendedTypography.transactionItemStyles.contentLineThrough
textColor = ZcashTheme.colors.historyRedColor
} else {
textStyle = ZcashTheme.extendedTypography.transactionItemStyles.content
textColor = ZcashTheme.colors.textCommon
}
Column(modifier = modifier.then(Modifier.fillMaxWidth())) {
Text(
text = stringResource(id = R.string.account_history_item_message),
@ -642,8 +717,8 @@ private fun HistoryItemMessagePart(
) {
Text(
text = composedMessage,
style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textCommon,
style = textStyle,
color = textColor,
modifier = Modifier.padding(all = ZcashTheme.dimens.spacingMid)
)
}
@ -654,7 +729,7 @@ private fun HistoryItemMessagePart(
text = stringResource(id = R.string.account_history_item_tap_to_copy),
style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textDescription,
imageVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
modifier =
Modifier
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
@ -683,7 +758,9 @@ internal enum class TransactionExtendedState {
SEND_FAILED,
RECEIVED,
RECEIVING,
RECEIVE_FAILED,
RECEIVE_FAILED;
fun isFailed(): Boolean = this == SEND_FAILED || this == RECEIVE_FAILED
}
private fun TransactionOverview.getExtendedState(): TransactionExtendedState {

View File

@ -15,6 +15,9 @@
<string name="account_history_item_message">Message</string>
<string name="account_history_item_collapse_transaction">Collapse transaction</string>
<string name="account_history_item_transaction_id">Transaction ID</string>
<string name="account_history_item_transaction_fee">Transaction Fee</string>
<string name="account_history_item_transaction_fee_typical">Typical Fee &lt; <xliff:g id="fee_amount"
example="0.001">%1$s</xliff:g></string>
<string name="account_history_memo_clipboard_tag">Transaction message</string>
<string name="account_history_id_clipboard_tag">Transaction ID</string>