From ece1122e14266fd043cffa213fbf158a12de2261 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 10 Jul 2026 13:08:08 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../entity/TangemPayTxHistoryDetailsUM.kt | 5 +- .../TangemPayTxHistoryDetailsConverterV2.kt | 15 ++-- .../tangempay/ui/TangempayTxDetailsUiV2.kt | 85 +++++++++++++------ .../TangemPayTxHistoryDetailsModelTest.kt | 14 ++- 4 files changed, 81 insertions(+), 38 deletions(-) diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayTxHistoryDetailsUM.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayTxHistoryDetailsUM.kt index bc07eaf7a6..3cddd9cadb 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayTxHistoryDetailsUM.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayTxHistoryDetailsUM.kt @@ -71,7 +71,10 @@ internal enum class TransactionStateType { @Immutable internal sealed interface TransactionDetailUM { data object Loading : TransactionDetailUM - data class Content(val card: TextReference) : TransactionDetailUM + data class Content( + val cardNumber: TextReference?, + val cardName: TextReference?, + ) : TransactionDetailUM data class Error(val onRefreshClick: () -> Unit) : TransactionDetailUM } diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverterV2.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverterV2.kt index 248b7fbcb6..ad8655ef42 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverterV2.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverterV2.kt @@ -297,19 +297,18 @@ internal object TangemPayTxHistoryDetailsConverterV2 : return when (transactionLoadState) { TransactionLoadState.Loading -> TransactionDetailUM.Loading TransactionLoadState.Error -> TransactionDetailUM.Error(onRefreshClick = onCardRefreshClick) - TransactionLoadState.Loaded -> spend.extractCardValue()?.let(TransactionDetailUM::Content) + TransactionLoadState.Loaded -> spend.extractCardDetail() } } - private fun TangemPayTxHistoryItem.Spend.extractCardValue(): TextReference? { + private fun TangemPayTxHistoryItem.Spend.extractCardDetail(): TransactionDetailUM.Content? { val name = cardName?.takeIf { it.isNotEmpty() } val last4 = cardNumberLast4?.takeIf { it.isNotEmpty() } - return when { - name != null && last4 != null -> stringReference("$name *$last4") - last4 != null -> stringReference("*$last4") - name != null -> stringReference(name) - else -> null - } + if (name == null && last4 == null) return null + return TransactionDetailUM.Content( + cardNumber = last4?.let { stringReference("*$it") }, + cardName = name?.let(::stringReference), + ) } private fun Input.extractButtonState(): ButtonState { diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUiV2.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUiV2.kt index 21269f238b..66fed29d1b 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUiV2.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUiV2.kt @@ -231,62 +231,58 @@ private fun TransactionDetailsBlock(state: TangemPayTxHistoryDetailsUMV2, modifi when (val detail = state.detail) { null -> Unit TransactionDetailUM.Loading -> CardRowShimmer() - is TransactionDetailUM.Content -> CardRow(value = detail.card) + is TransactionDetailUM.Content -> CardRow(content = detail) is TransactionDetailUM.Error -> CardRowError(onRefreshClick = detail.onRefreshClick) } TangemRow( divider = state.mcc != null, - contentLead = TangemRowContentLead.Start, + contentLead = TangemRowContentLead.End, titleSlot = { TangemRowText( text = resourceReference(R.string.tangem_pay_transaction_details_category), role = TangemRowTextRole.Title, ) }, - valueSlot = { - TangemRowText( - text = state.transactionCategory, - role = TangemRowTextRole.Value, - ) - }, + valueSlot = { DetailRowValue(text = state.transactionCategory) }, ) if (state.mcc != null) { TangemRow( - contentLead = TangemRowContentLead.Start, + contentLead = TangemRowContentLead.End, titleSlot = { TangemRowText( text = resourceReference(R.string.tangem_pay_transaction_details_mcc), role = TangemRowTextRole.Title, ) }, - valueSlot = { - TangemRowText( - text = state.mcc, - role = TangemRowTextRole.Value, - ) - }, + valueSlot = { DetailRowValue(text = state.mcc) }, ) } } } @Composable -private fun CardRow(value: TextReference, modifier: Modifier = Modifier) { +private fun CardRow(content: TransactionDetailUM.Content, modifier: Modifier = Modifier) { + val cardNumber = content.cardNumber + val cardName = content.cardName TangemRow( modifier = modifier, divider = true, - contentLead = TangemRowContentLead.Start, + contentLead = TangemRowContentLead.End, titleSlot = { TangemRowText( text = resourceReference(R.string.tangempay_common_card), role = TangemRowTextRole.Title, ) }, - valueSlot = { - TangemRowText( - text = value, - role = TangemRowTextRole.Value, - ) + valueSlot = if (cardNumber != null) { + { DetailRowValue(text = cardNumber) } + } else { + null + }, + subvalueSlot = if (cardName != null) { + { DetailRowSubvalue(text = cardName) } + } else { + null }, ) } @@ -296,7 +292,7 @@ private fun CardRowShimmer(modifier: Modifier = Modifier) { TangemRow( modifier = modifier, divider = true, - contentLead = TangemRowContentLead.Start, + contentLead = TangemRowContentLead.End, titleSlot = { TangemShimmer(style = TangemTheme.typography3.body.medium) }, @@ -308,7 +304,7 @@ private fun CardRowError(onRefreshClick: () -> Unit, modifier: Modifier = Modifi TangemRow( modifier = modifier, divider = true, - contentLead = TangemRowContentLead.Start, + contentLead = TangemRowContentLead.End, verticalAlignment = TangemRowVerticalAlignment.Center, titleSlot = { TangemRowText( @@ -343,6 +339,32 @@ private fun CardRowError(onRefreshClick: () -> Unit, modifier: Modifier = Modifi ) } +@Composable +private fun DetailRowValue(text: TextReference, modifier: Modifier = Modifier) { + Text( + modifier = modifier, + text = text.resolveReference(), + color = TangemTheme.colors3.text.secondary, + style = TangemTheme.typography3.body.medium, + textAlign = TextAlign.End, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) +} + +@Composable +private fun DetailRowSubvalue(text: TextReference, modifier: Modifier = Modifier) { + Text( + modifier = modifier, + text = text.resolveReference(), + color = TangemTheme.colors3.text.secondary, + style = TangemTheme.typography3.caption.medium, + textAlign = TextAlign.End, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) +} + @Preview(device = Devices.PIXEL_7_PRO) @Preview(device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable @@ -363,7 +385,10 @@ private class TangemPayTxHistoryDetailsUMProviderV2 : subtitle = stringReference("12 June 2026, 12:40"), iconState = TangemIconUM.Icon(iconRes = R.drawable.ic_category_24), transactionTitle = stringReference("Starbucks"), - detail = TransactionDetailUM.Content(stringReference("Basic card *9092")), + detail = TransactionDetailUM.Content( + cardNumber = stringReference("*9092"), + cardName = stringReference("Basic card"), + ), transactionCategory = stringReference("Food and drinks"), mcc = stringReference("5814"), transactionAmount = "-$5.86", @@ -385,7 +410,10 @@ private class TangemPayTxHistoryDetailsUMProviderV2 : subtitle = stringReference("12 June 2026, 12:40"), iconState = TangemIconUM.Icon(iconRes = R.drawable.ic_category_24), transactionTitle = stringReference("NuCaloric"), - detail = TransactionDetailUM.Content(stringReference("Basic card *9092")), + detail = TransactionDetailUM.Content( + cardNumber = stringReference("*9092"), + cardName = stringReference("Basic card"), + ), transactionCategory = stringReference("Groceries"), mcc = stringReference("0000"), transactionAmount = "-$820.52", @@ -408,7 +436,10 @@ private class TangemPayTxHistoryDetailsUMProviderV2 : subtitle = stringReference("12 June 2026, 12:40"), iconState = TangemIconUM.Icon(iconRes = R.drawable.ic_category_24), transactionTitle = stringReference("Starbucks"), - detail = TransactionDetailUM.Content(stringReference("Basic card *9092")), + detail = TransactionDetailUM.Content( + cardNumber = stringReference("*9092"), + cardName = stringReference("Basic card"), + ), transactionCategory = stringReference("Food and drinks"), mcc = null, transactionAmount = "-$5.86", diff --git a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModelTest.kt b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModelTest.kt index 95f151b1f1..e2d90be963 100644 --- a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModelTest.kt +++ b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModelTest.kt @@ -86,7 +86,12 @@ internal class TangemPayTxHistoryDetailsModelTest { // Assert assertThat(model.uiState.value.redesign.detail) - .isEqualTo(TransactionDetailUM.Content(stringReference("Loaded card *4321"))) + .isEqualTo( + TransactionDetailUM.Content( + cardNumber = stringReference("*4321"), + cardName = stringReference("Loaded card"), + ), + ) model.onDestroy() } @@ -140,7 +145,12 @@ internal class TangemPayTxHistoryDetailsModelTest { // Assert assertThat(model.uiState.value.redesign.detail) - .isEqualTo(TransactionDetailUM.Content(stringReference("Loaded card *4321"))) + .isEqualTo( + TransactionDetailUM.Content( + cardNumber = stringReference("*4321"), + cardName = stringReference("Loaded card"), + ), + ) coVerify(exactly = 2) { repository.getTransaction(any(), any()) } model.onDestroy() }