From 9a937e43631a30c40ed8db8f17de8c976c2c89ed Mon Sep 17 00:00:00 2001 From: Aleksandar Ilic Date: Thu, 8 Feb 2024 20:10:14 +0100 Subject: [PATCH] Polish btc txs UI --- .../android/wallet/WalletStaticColors.kt | 2 + .../primal/android/wallet/domain/TxState.kt | 3 + .../details/TransactionDetailsScreen.kt | 61 +++++++++++++++++-- .../transactions/list/TransactionListItem.kt | 11 ++-- app/src/main/res/values/strings.xml | 6 +- 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/wallet/WalletStaticColors.kt b/app/src/main/kotlin/net/primal/android/wallet/WalletStaticColors.kt index 65a648200..9297156b6 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/WalletStaticColors.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/WalletStaticColors.kt @@ -11,3 +11,5 @@ val walletSuccessContentColor = Color(0xFFFFFFFF) val walletDepositColor = walletSuccessColor val walletWithdrawColor = Color(0xFFCC331E) + +val walletTransactionIconBackgroundColor = Color(0xFF222222) diff --git a/app/src/main/kotlin/net/primal/android/wallet/domain/TxState.kt b/app/src/main/kotlin/net/primal/android/wallet/domain/TxState.kt index d77d1dc23..2ebd5be3c 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/domain/TxState.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/domain/TxState.kt @@ -6,4 +6,7 @@ enum class TxState(val id: Int) { SUCCEEDED(id = 101), FAILED(id = 102), CANCELED(id = 103), + ; + + fun isPending() = this == CREATED || this == PROCESSING } diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsScreen.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsScreen.kt index c8c303030..db0577855 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsScreen.kt @@ -1,6 +1,7 @@ package net.primal.android.wallet.transactions.details import androidx.compose.animation.animateContentSize +import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.Spring.StiffnessMediumLow import androidx.compose.animation.core.animateFloat @@ -9,9 +10,11 @@ import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -20,13 +23,16 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ExpandLess import androidx.compose.material.icons.filled.ExpandMore +import androidx.compose.material.icons.filled.Schedule import androidx.compose.material3.Card import androidx.compose.material3.CardColors import androidx.compose.material3.CardDefaults @@ -45,6 +51,8 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.vector.ImageVector @@ -90,6 +98,7 @@ import net.primal.android.wallet.transactions.details.TransactionDetailsContract import net.primal.android.wallet.transactions.list.TransactionIcon import net.primal.android.wallet.utils.CurrencyConversionUtils.toBtc import net.primal.android.wallet.walletDepositColor +import net.primal.android.wallet.walletTransactionIconBackgroundColor import net.primal.android.wallet.walletWithdrawColor import timber.log.Timber @@ -243,13 +252,23 @@ private fun TransactionDetailDataUi?.resolveTitle(): String { TxType.DEPOSIT -> if (isZap) { stringResource(id = R.string.wallet_transaction_details_title_zap_received) } else { - stringResource(id = R.string.wallet_transaction_details_title_payment_received) + when (txState) { + TxState.CREATED, TxState.PROCESSING -> stringResource( + id = R.string.wallet_transaction_details_title_payment_pending, + ) + else -> stringResource(id = R.string.wallet_transaction_details_title_payment_received) + } } TxType.WITHDRAW -> if (isZap) { stringResource(id = R.string.wallet_transaction_details_title_zap_sent) } else { - stringResource(id = R.string.wallet_transaction_details_title_payment_sent) + when (txState) { + TxState.CREATED, TxState.PROCESSING -> stringResource( + id = R.string.wallet_transaction_details_title_payment_pending, + ) + else -> stringResource(id = R.string.wallet_transaction_details_title_payment_received) + } } else -> "" @@ -321,6 +340,7 @@ private fun TransactionCard(txData: TransactionDetailDataUi, onProfileClick: (St } else { TxHeader( onChainAddress = txData.onChainAddress, + isPending = txData.txState.isPending(), otherUserLightningAddress = txData.otherUserLightningAddress, type = txData.typeToReadableString(), ) @@ -463,6 +483,7 @@ private fun NumberFormat.formatSafely(any: Any?): String? { @Composable private fun TxHeader( onChainAddress: String?, + isPending: Boolean, otherUserLightningAddress: String?, type: String, ) { @@ -472,9 +493,7 @@ private fun TxHeader( .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { - TransactionIcon( - background = Color(0xFF222222), - ) { + TransactionIcon(background = walletTransactionIconBackgroundColor) { Image( imageVector = when (onChainAddress != null) { true -> PrimalIcons.WalletBitcoinPayment @@ -483,6 +502,38 @@ private fun TxHeader( contentDescription = null, colorFilter = ColorFilter.tint(color = AppTheme.extraColorScheme.zapped), ) + + if (isPending) { + val infiniteTransition = rememberInfiniteTransition(label = "ClockRotation$onChainAddress") + val angle by infiniteTransition.animateFloat( + initialValue = 0.0f, + targetValue = 360.0f, + animationSpec = infiniteRepeatable( + animation = tween( + durationMillis = 3.seconds.inWholeMilliseconds.toInt(), + easing = LinearEasing, + ), + repeatMode = RepeatMode.Restart, + ), + label = "ClockPendingAngle$onChainAddress", + ) + + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.BottomEnd, + ) { + Image( + modifier = Modifier + .size(18.dp) + .clip(CircleShape) + .background(color = AppTheme.colorScheme.surfaceVariant) + .rotate(angle), + imageVector = Icons.Default.Schedule, + contentDescription = null, + colorFilter = ColorFilter.tint(color = AppTheme.extraColorScheme.onSurfaceVariantAlt1), + ) + } + } } Column( diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt index 71394ec14..95aded274 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt @@ -58,6 +58,7 @@ import net.primal.android.theme.PrimalTheme import net.primal.android.wallet.domain.TxState import net.primal.android.wallet.domain.TxType import net.primal.android.wallet.walletDepositColor +import net.primal.android.wallet.walletTransactionIconBackgroundColor import net.primal.android.wallet.walletWithdrawColor @Composable @@ -93,18 +94,14 @@ fun TransactionListItem( leadingContent = { TransactionLeadingContent( onChainPayment = data.isOnChainPayment, - isPending = data.txState == TxState.PROCESSING, + isPending = data.txState.isPending(), otherUserId = data.otherUserId, otherUserAvatarCdnImage = data.otherUserAvatarCdnImage, onAvatarClick = onAvatarClick, ) }, headlineContent = { - val suffix = data.txCompletedAt?.formatAsTime() ?: when (data.txState) { - TxState.CREATED -> stringResource(id = R.string.wallet_transactions_created) - TxState.PROCESSING -> stringResource(id = R.string.wallet_transactions_pending) - else -> "" - } + val suffix = data.txCompletedAt?.formatAsTime() ?: stringResource(id = R.string.wallet_transactions_pending) TransactionHeadlineContent( wrappedText = data.otherUserDisplayName ?: when (data.isOnChainPayment) { @@ -147,7 +144,7 @@ private fun TransactionLeadingContent( } else -> { - TransactionIcon { + TransactionIcon(background = walletTransactionIconBackgroundColor) { Image( imageVector = when (onChainPayment) { true -> PrimalIcons.WalletBitcoinPayment diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2c182f865..5bf4cd1ad 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -377,7 +377,6 @@ Incoming on-chain payment Today Yesterday - Sent Pending Purchase Now Pay @@ -419,7 +418,7 @@ Close Bitcoin Address Mining Fee - Try again + --- Alert Amount too small for an on-chain transaction. %1$s is minimal amount for %2$s tier. @@ -445,6 +444,7 @@ Zap Received Zap Sent + Payment Pending Payment Received Payment Sent Sent To @@ -466,7 +466,7 @@ On-chain Payment Lightning Payment View on Blockchain - Sent + Pending Pending Paid Confirmed