From a19b9c01b53cdc7af32b9c5d8e0eadeec9f92e6a Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 8 Dec 2023 14:51:11 +0300 Subject: [PATCH] Updated on 2026-08-14 --- core/res/src/main/res/values/strings.xml | 2 + .../domain/SendRecipientListContent.kt | 3 +- .../impl/presentation/state/StateRouter.kt | 20 +++---- .../recipient/SendRecipientListConverter.kt | 11 ++-- .../presentation/ui/SendNavigationButtons.kt | 2 +- .../send/impl/presentation/ui/SendScreen.kt | 15 +++-- .../ui/recipient/ListItemWithIcon.kt | 59 ++++++++++--------- .../ui/recipient/SendRecipientContent.kt | 3 +- 8 files changed, 61 insertions(+), 54 deletions(-) diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 345f06a0f6..6045fd4bd4 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -438,6 +438,7 @@ Amount Subtract from send amount The recipient will receive %s + Confirm %1$s at %2$s Address Destination Tag @@ -488,6 +489,7 @@ Please align your QR code with the square to scan it. Ensure you scan %s network address. Recent Recipient + Send to Not a valid address Ensure that you are sending funds to an %s wallet address. Errors may result in the loss of your tokens A Memo/Destination Tag is a unique ID for differentiating transactions sent to the same recipient on the same network. Caution: Omitting a memo may lead to misplaced funds diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/domain/SendRecipientListContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/domain/SendRecipientListContent.kt index 7f7216e6e3..47761c5956 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/domain/SendRecipientListContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/domain/SendRecipientListContent.kt @@ -11,7 +11,8 @@ internal sealed class SendRecipientListContent { val id: String, val title: TextReference, val subtitle: TextReference, - val info: TextReference? = null, + val timestamp: TextReference? = null, + val subtitleEndOffset: Int = 0, @DrawableRes val subtitleIconRes: Int? = null, ) : SendRecipientListContent() diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt index e92791bba9..97ad5f2dfc 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt @@ -8,7 +8,7 @@ import java.lang.ref.WeakReference internal class StateRouter( private val fragmentManager: WeakReference, ) { - var currentState: MutableStateFlow = MutableStateFlow(SendUiStateType.Amount) + var currentState: MutableStateFlow = MutableStateFlow(SendUiStateType.Recipient) private set private var isFromSend: Boolean = false @@ -22,9 +22,9 @@ internal class StateRouter( showSend() } else { when (currentState.value) { - SendUiStateType.Amount -> popBackStack() - SendUiStateType.Recipient -> showAmount() - SendUiStateType.Fee -> showRecipient() + SendUiStateType.Recipient -> popBackStack() + SendUiStateType.Amount -> showRecipient() + SendUiStateType.Fee -> showAmount() SendUiStateType.Send -> showFee() } } @@ -32,8 +32,8 @@ internal class StateRouter( fun onNextClick() { when (currentState.value) { - SendUiStateType.Amount -> showRecipient() - SendUiStateType.Recipient -> showFee() + SendUiStateType.Recipient -> showAmount() + SendUiStateType.Amount -> showFee() SendUiStateType.Fee -> showSend() SendUiStateType.Send -> onBackClick() } @@ -41,9 +41,9 @@ internal class StateRouter( fun onPrevClick() { when (currentState.value) { - SendUiStateType.Amount -> popBackStack() - SendUiStateType.Recipient -> showAmount() - SendUiStateType.Fee -> showRecipient() + SendUiStateType.Recipient -> popBackStack() + SendUiStateType.Amount -> showRecipient() + SendUiStateType.Fee -> showAmount() SendUiStateType.Send -> popBackStack() } } @@ -63,7 +63,7 @@ internal class StateRouter( currentState.update { SendUiStateType.Fee } } - fun showSend() { + private fun showSend() { currentState.update { SendUiStateType.Send } } } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientListConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientListConverter.kt index 8fd734e781..da2ee1a963 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientListConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientListConverter.kt @@ -3,10 +3,12 @@ package com.tangem.features.send.impl.presentation.state.recipient import androidx.paging.* import com.tangem.common.Provider import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.utils.DateTimeFormatters import com.tangem.core.ui.utils.toDateFormat import com.tangem.core.ui.utils.toTimeFormat +import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.features.send.impl.R @@ -34,6 +36,7 @@ internal class SendRecipientListConverter( val walletsItem = getWalletItems(filteredWallets, txHistoryCount) + val cryptoCurrency = cryptoCurrencyStatusProvider().currency currentStateProvider().recipientList.update { if (txHistoryCount == 0) { PagingData.from(listOf(walletsItem)) @@ -51,8 +54,9 @@ internal class SendRecipientListConverter( SendRecipientListContent.Item( id = tx.txHash, title = tx.extractAddress(), - subtitle = TextReference.Str(tx.getAmount()), - info = tx.extractTimestamp(), + subtitle = stringReference(tx.getAmount(cryptoCurrency).trim()), + timestamp = tx.extractTimestamp(), + subtitleEndOffset = cryptoCurrency.symbol.length, subtitleIconRes = tx.extractIconRes(), ) }.insertWallets(walletsItem) @@ -104,8 +108,7 @@ internal class SendRecipientListConverter( R.drawable.ic_arrow_down_24 } - private fun TxHistoryItem.getAmount(): String { - val cryptoCurrency = cryptoCurrencyStatusProvider().currency + private fun TxHistoryItem.getAmount(cryptoCurrency: CryptoCurrency): String { return amount.toFormattedCurrencyString( currency = cryptoCurrency.symbol, decimals = cryptoCurrency.decimals, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt index e7c0df4249..e8118443a5 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt @@ -50,7 +50,7 @@ internal fun SendNavigationButtons(uiState: SendUiState) { private fun SendSecondaryNavigationButton(uiState: SendUiState) { val currentState = uiState.currentState.collectAsState() AnimatedVisibility( - visible = currentState.value == SendUiStateType.Recipient || + visible = currentState.value == SendUiStateType.Amount || currentState.value == SendUiStateType.Fee, ) { Icon( diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt index 1c73c25a04..e20a0b7779 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt @@ -38,16 +38,15 @@ internal fun SendScreen(uiState: SendUiState) { horizontalAlignment = Alignment.CenterHorizontally, ) { val titleRes = when (currentState.value) { - SendUiStateType.Amount -> R.string.common_send - SendUiStateType.Recipient -> R.string.send_recipient + SendUiStateType.Amount -> R.string.send_amount_label + SendUiStateType.Recipient -> R.string.send_recipient_label SendUiStateType.Fee -> R.string.common_fee_selector_title - SendUiStateType.Send -> if (isSuccess?.value == false) R.string.common_send else null + SendUiStateType.Send -> if (isSuccess?.value == false) R.string.send_confirm_label else null } - val iconRes = when (currentState.value) { - SendUiStateType.Amount, - SendUiStateType.Recipient, - -> R.drawable.ic_qrcode_scan_24 - else -> null + val iconRes = if (currentState.value == SendUiStateType.Recipient) { + R.drawable.ic_qrcode_scan_24 + } else { + null } AppBarWithBackButtonAndIcon( diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/ListItemWithIcon.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/ListItemWithIcon.kt index f7c2cd613f..e83ba769bd 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/ListItemWithIcon.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/ListItemWithIcon.kt @@ -3,24 +3,26 @@ package com.tangem.features.send.impl.presentation.ui.recipient import androidx.annotation.DrawableRes import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon -import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension import androidx.constraintlayout.compose.Visibility -import com.tangem.core.ui.components.MiddleEllipsisText +import com.tangem.core.ui.components.atoms.text.EllipsisText +import com.tangem.core.ui.components.atoms.text.TextEllipsis import com.tangem.core.ui.components.icons.identicon.IdentIcon import com.tangem.core.ui.res.TangemTheme import com.tangem.features.send.impl.R @@ -33,6 +35,7 @@ import com.tangem.features.send.impl.R * @param onClick click listener * @param modifier modifier * @param info info + * @param subtitleEndOffset offset for subtitle ellipsis * @param subtitleIconRes icon */ @Suppress("DestructuringDeclarationWithTooManyEntries", "LongMethod") @@ -43,6 +46,7 @@ fun ListItemWithIcon( onClick: () -> Unit, modifier: Modifier = Modifier, info: String? = null, + subtitleEndOffset: Int = 0, @DrawableRes subtitleIconRes: Int? = null, ) { ConstraintLayout( @@ -51,7 +55,7 @@ fun ListItemWithIcon( .clickable { onClick() } .padding(horizontal = TangemTheme.dimens.spacing12), ) { - val (iconRef, titleRef, subtitleRef, subtitleIconRef, infoRef) = createRefs() + val (iconRef, titleRef, subtitleRef, subtitleIconRef) = createRefs() val spacing2 = TangemTheme.dimens.spacing2 val spacing8 = TangemTheme.dimens.spacing8 @@ -68,11 +72,12 @@ fun ListItemWithIcon( bottom.linkTo(parent.bottom, margin = spacing8) }, ) - MiddleEllipsisText( + EllipsisText( text = title, style = TangemTheme.typography.subtitle2, color = TangemTheme.colors.text.primary1, textAlign = TextAlign.Justify, + ellipsis = TextEllipsis.Middle, modifier = Modifier .constrainAs(titleRef) { start.linkTo(iconRef.end, margin = spacing12) @@ -87,7 +92,7 @@ fun ListItemWithIcon( tint = TangemTheme.colors.icon.informative, modifier = Modifier .size(TangemTheme.dimens.size16) - .background(TangemTheme.colors.background.tertiary, CircleShape) + .background(TangemTheme.colors.icon.informative.copy(alpha = 0.1f), CircleShape) .constrainAs(subtitleIconRef) { start.linkTo(iconRef.end, margin = spacing12) top.linkTo(titleRef.bottom) @@ -95,36 +100,29 @@ fun ListItemWithIcon( visibility = if (subtitleIconRes == null) Visibility.Gone else Visibility.Visible }, ) - Text( - text = subtitle, + + val (text, offset) = remember(subtitle, info) { + if (info != null) { + val suffix = ", $info" + subtitle + suffix to suffix.length + subtitleEndOffset + } else { + subtitle to 0 + } + } + EllipsisText( + text = text, style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.tertiary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, + ellipsis = TextEllipsis.OffsetEnd(offsetEnd = offset), modifier = Modifier .constrainAs(subtitleRef) { start.linkTo(subtitleIconRef.end, margin = spacing2, goneMargin = spacing12) - end.linkTo(infoRef.start) + end.linkTo(parent.end) top.linkTo(titleRef.bottom) bottom.linkTo(parent.bottom, margin = spacing10) width = Dimension.fillToConstraints }, ) - info?.let { - Text( - text = it, - style = TangemTheme.typography.caption2, - color = TangemTheme.colors.text.tertiary, - maxLines = 1, - modifier = Modifier - .constrainAs(infoRef) { - start.linkTo(subtitleRef.end, goneMargin = spacing12) - end.linkTo(parent.end) - top.linkTo(titleRef.bottom) - bottom.linkTo(parent.bottom, margin = spacing10) - }, - ) - } } } @@ -138,7 +136,7 @@ private fun ListItemWithIconPreview_Light( ListItemWithIcon( title = config.title, subtitle = config.subtitle, - info = config.info, + subtitleEndOffset = config.subtitleEndOffset, subtitleIconRes = config.iconRes, onClick = {}, ) @@ -154,7 +152,7 @@ private fun ListItemWithIconPreview_Dark( ListItemWithIcon( title = config.title, subtitle = config.subtitle, - info = config.info, + subtitleEndOffset = config.subtitleEndOffset, subtitleIconRes = config.iconRes, onClick = {}, ) @@ -165,6 +163,7 @@ private data class ListItemWithIconPreviewConfig( val title: String, val subtitle: String, val info: String? = null, + val subtitleEndOffset: Int = 0, val iconRes: Int? = null, ) @@ -174,12 +173,14 @@ private class ListItemWithIconPreviewProvider : CollectionPreviewParameterProvid title = "0x34B4492A412D84A6E606288f3Bd714b89135D4dE", subtitle = "0.000000000000000000000000000000 BTC", info = "0.0.0000 at 00:00", + subtitleEndOffset = "BTC".length, iconRes = R.drawable.ic_arrow_down_24, ), ListItemWithIconPreviewConfig( title = "0x34B4492A412D84A6E606288f3Bd714b89135D4dE", subtitle = "1 BTC", info = "0.0.0000 at 00:00", + subtitleEndOffset = "BTC".length, iconRes = R.drawable.ic_arrow_down_24, ), ListItemWithIconPreviewConfig( diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt index 24319091e1..5e4316a1e4 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt @@ -141,7 +141,8 @@ private fun LazyListScope.recipientListItem( ListItemWithIcon( title = item.title.resolveReference(), subtitle = item.subtitle.resolveReference(), - info = item.info?.let { ", ${it.resolveReference()}" }, + info = item.timestamp?.resolveReference(), + subtitleEndOffset = item.subtitleEndOffset, subtitleIconRes = item.subtitleIconRes, modifier = Modifier .then(