From 699807e1bd42ccd2a0b5ff7ed5fa01cc71ec2a34 Mon Sep 17 00:00:00 2001 From: Kayos Date: Sun, 29 Mar 2026 06:57:12 -0700 Subject: [PATCH] feat(wallet): add recipient address to payment card UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhanced the payment timeline card to display the recipient/sender address: - Added truncatedToAddress and truncatedFromAddress to TimelineItemPaymentContent - New truncateAddress() helper (first 8 + last 6 chars) - Payment card now shows "To: addr_tes...ytjqp" for sent payments - And "From: addr_tes...pd0hq" for received payments - Updated wrapper to expose new properties The card now displays: - Amount in ADA (large, bold) - Sent/Received indicator with Cardano icon - Truncated recipient/sender address - Status chip (Pending/Confirmed/Failed with icons) - Truncated tx hash (tappable to CardanoScan) - Testnet badge when applicable - "View on CardanoScan →" link for confirmed transactions --- .../TimelineItemPaymentContentWrapper.kt | 2 ++ .../timeline/TimelineItemPaymentContent.kt | 23 +++++++++++++++ .../impl/timeline/TimelineItemPaymentView.kt | 28 +++++++++++++++++-- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPaymentContentWrapper.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPaymentContentWrapper.kt index 70c0c48d08..d0af0290e3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPaymentContentWrapper.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPaymentContentWrapper.kt @@ -35,5 +35,7 @@ data class TimelineItemPaymentContentWrapper( val amountAda: String get() = paymentContent.amountAda val isTestnet: Boolean get() = paymentContent.isTestnet val truncatedTxHash: String? get() = paymentContent.truncatedTxHash + val truncatedToAddress: String get() = paymentContent.truncatedToAddress + val truncatedFromAddress: String get() = paymentContent.truncatedFromAddress val explorerUrl: String? get() = paymentContent.explorerUrl } diff --git a/features/wallet/api/src/main/kotlin/io/element/android/features/wallet/api/timeline/TimelineItemPaymentContent.kt b/features/wallet/api/src/main/kotlin/io/element/android/features/wallet/api/timeline/TimelineItemPaymentContent.kt index 05282b982b..6a3eeebc29 100644 --- a/features/wallet/api/src/main/kotlin/io/element/android/features/wallet/api/timeline/TimelineItemPaymentContent.kt +++ b/features/wallet/api/src/main/kotlin/io/element/android/features/wallet/api/timeline/TimelineItemPaymentContent.kt @@ -64,6 +64,18 @@ data class TimelineItemPaymentContent( } } + /** + * Truncated recipient address for display (first 8 + last 6 chars). + */ + val truncatedToAddress: String + get() = truncateAddress(toAddress) + + /** + * Truncated sender address for display (first 8 + last 6 chars). + */ + val truncatedFromAddress: String + get() = truncateAddress(fromAddress) + /** * CardanoScan URL for viewing the transaction. */ @@ -93,5 +105,16 @@ data class TimelineItemPaymentContent( "$formatted ADA" } } + + /** + * Truncate a Cardano address for display (first 8 + last 6 chars). + */ + fun truncateAddress(address: String): String { + return if (address.length > 18) { + "${address.take(8)}...${address.takeLast(6)}" + } else { + address + } + } } } diff --git a/features/wallet/impl/src/main/kotlin/io/element/android/features/wallet/impl/timeline/TimelineItemPaymentView.kt b/features/wallet/impl/src/main/kotlin/io/element/android/features/wallet/impl/timeline/TimelineItemPaymentView.kt index 9d883e51ca..4d4b8f0f4f 100644 --- a/features/wallet/impl/src/main/kotlin/io/element/android/features/wallet/impl/timeline/TimelineItemPaymentView.kt +++ b/features/wallet/impl/src/main/kotlin/io/element/android/features/wallet/impl/timeline/TimelineItemPaymentView.kt @@ -51,6 +51,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight * * The card displays: * - ADA icon and amount + * - Recipient/sender address (truncated) * - Status indicator (spinner for pending, checkmark for confirmed, X for failed) * - Truncated transaction hash (tappable to open CardanoScan) * - Testnet badge when applicable @@ -113,7 +114,7 @@ fun TimelineItemPaymentView( Spacer(modifier = Modifier.height(12.dp)) - // Amount + // Amount - large and prominent Text( text = content.amountAda, style = MaterialTheme.typography.headlineMedium, @@ -121,9 +122,30 @@ fun TimelineItemPaymentView( color = contentColor, ) + Spacer(modifier = Modifier.height(8.dp)) + + // Recipient/sender address + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = if (content.isSentByMe) "To: " else "From: ", + style = MaterialTheme.typography.bodySmall, + color = contentColor.copy(alpha = 0.6f), + ) + Text( + text = if (content.isSentByMe) content.truncatedToAddress else content.truncatedFromAddress, + style = MaterialTheme.typography.bodySmall, + fontWeight = FontWeight.Medium, + color = contentColor.copy(alpha = 0.8f), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + Spacer(modifier = Modifier.height(12.dp)) - // Status row + // Status row with tx hash Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, @@ -151,7 +173,7 @@ fun TimelineItemPaymentView( } } - // View on explorer link (only for confirmed) + // View on explorer link (only for confirmed with tx hash) if (content.status == PaymentCardStatus.CONFIRMED && content.explorerUrl != null) { Spacer(modifier = Modifier.height(8.dp)) Text(