From 5516a0aa333b83601f220ab390fba74728cab0cd Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Mar 2024 17:42:38 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../ui/components/rows/SelectorRowItem.kt | 110 ++++++++-------- .../presentation/ui/fee/SendSpeedSelector.kt | 118 ++++-------------- .../impl/presentation/ui/send/FeeBlock.kt | 56 +++------ .../feature/swap/ui/ChooseFeeBottomSheet.kt | 32 +++-- .../tangem/feature/swap/ui/ProviderItem.kt | 41 +++--- .../feature/swap/ui/SwapScreenContent.kt | 9 +- 6 files changed, 136 insertions(+), 230 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/rows/SelectorRowItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/rows/SelectorRowItem.kt index 667ec44c08..bedec66060 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/rows/SelectorRowItem.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/rows/SelectorRowItem.kt @@ -14,11 +14,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.R +import com.tangem.core.ui.components.atoms.text.EllipsisText +import com.tangem.core.ui.components.atoms.text.TextEllipsis import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.TangemTheme @@ -27,12 +27,14 @@ import com.tangem.core.ui.res.TangemTheme fun SelectorRowItem( @StringRes titleRes: Int, @DrawableRes iconRes: Int, - onSelect: () -> Unit, modifier: Modifier = Modifier, - preEllipsize: TextReference? = null, - postEllipsize: TextReference? = null, + paddingValues: PaddingValues = PaddingValues(TangemTheme.dimens.spacing12), + preDot: TextReference? = null, + postDot: TextReference? = null, + ellipsizeOffset: Int? = null, isSelected: Boolean = false, showDivider: Boolean = true, + onSelect: (() -> Unit)? = null, ) { val iconTint by animateColorAsState( targetValue = if (isSelected) { @@ -43,45 +45,39 @@ fun SelectorRowItem( label = "Selector icon tint change", ) - val textStyle = if (isSelected) { - TangemTheme.typography.subtitle2 - } else { - TangemTheme.typography.body2 - } - Box( modifier = modifier .fillMaxWidth() - .clickable { onSelect() }, + .then( + if (onSelect != null) { + Modifier.clickable { onSelect() } + } else { + Modifier + }, + ), ) { - Row(modifier = Modifier.fillMaxWidth()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(paddingValues), + verticalAlignment = Alignment.CenterVertically, + ) { Icon( painter = painterResource(iconRes), tint = iconTint, contentDescription = null, - modifier = Modifier - .padding( - start = TangemTheme.dimens.spacing12, - top = TangemTheme.dimens.spacing12, - bottom = TangemTheme.dimens.spacing12, - ), ) Text( text = stringResource(titleRes), - style = textStyle, + style = TangemTheme.typography.body2, color = TangemTheme.colors.text.primary1, - modifier = Modifier - .padding( - start = TangemTheme.dimens.spacing8, - top = TangemTheme.dimens.spacing14, - bottom = TangemTheme.dimens.spacing14, - ), + modifier = Modifier.padding(start = TangemTheme.dimens.spacing8), ) - if (preEllipsize != null && postEllipsize != null) { + if (preDot != null && postDot != null) { SelectorValueContent( - amount = preEllipsize, - symbol = postEllipsize, - textStyle = textStyle, + preDot = preDot, + postDot = postDot, + ellipsizeOffset = ellipsizeOffset, ) } } @@ -99,33 +95,37 @@ fun SelectorRowItem( } @Composable -private fun RowScope.SelectorValueContent(amount: TextReference, symbol: TextReference, textStyle: TextStyle) { - Text( - text = amount.resolveReference(), - style = textStyle, +private fun RowScope.SelectorValueContent( + preDot: TextReference, + postDot: TextReference, + ellipsizeOffset: Int? = null, +) { + val ellipsis = if (ellipsizeOffset == null) { + TextEllipsis.End + } else { + TextEllipsis.OffsetEnd(ellipsizeOffset) + } + EllipsisText( + text = preDot.resolveReference(), + style = TangemTheme.typography.body2, color = TangemTheme.colors.text.primary1, textAlign = TextAlign.End, - overflow = TextOverflow.Ellipsis, - maxLines = 1, + ellipsis = ellipsis, modifier = Modifier .weight(1f) - .padding( - start = TangemTheme.dimens.spacing4, - top = TangemTheme.dimens.spacing14, - bottom = TangemTheme.dimens.spacing14, - ), + .padding(start = TangemTheme.dimens.spacing4), ) Text( - text = symbol.resolveReference(), - style = textStyle, + text = "•", + style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.primary1, - modifier = Modifier - .padding( - start = TangemTheme.dimens.spacing1, - end = TangemTheme.dimens.spacing12, - top = TangemTheme.dimens.spacing14, - bottom = TangemTheme.dimens.spacing14, - ), + textAlign = TextAlign.Center, + modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing4), + ) + Text( + text = postDot.resolveReference(), + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.tertiary, ) } @@ -136,8 +136,9 @@ private fun SelectorRowItemPreview_Light() { SelectorRowItem( titleRes = R.string.common_fee_selector_option_slow, iconRes = R.drawable.ic_tortoise_24, - preEllipsize = TextReference.Str("1000"), - postEllipsize = TextReference.Str("$"), + preDot = TextReference.Str("1000 ETH"), + postDot = TextReference.Str("1000 $"), + ellipsizeOffset = 4, isSelected = true, onSelect = { }, ) @@ -151,8 +152,9 @@ private fun SelectorRowItemPreview_Dark() { SelectorRowItem( titleRes = R.string.common_fee_selector_option_slow, iconRes = R.drawable.ic_tortoise_24, - preEllipsize = TextReference.Str("1000"), - postEllipsize = TextReference.Str("$"), + preDot = TextReference.Str("1000 ETH"), + postDot = TextReference.Str("1000 $"), + ellipsizeOffset = 4, isSelected = true, onSelect = { }, ) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt index f5b10f50a8..e0a3868ec1 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt @@ -3,7 +3,6 @@ package com.tangem.features.send.impl.presentation.ui.fee import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.animateColorAsState import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.Image @@ -16,7 +15,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color @@ -33,11 +31,9 @@ import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.ui.components.RectangleShimmer import com.tangem.core.ui.components.SpacerWMax -import com.tangem.core.ui.components.atoms.text.EllipsisText -import com.tangem.core.ui.components.atoms.text.TextEllipsis +import com.tangem.core.ui.components.rows.SelectorRowItem import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.combinedReference -import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.utils.BigDecimalFormatter @@ -267,55 +263,23 @@ private fun SendSpeedSelectorItem( showDivider: Boolean = true, showWarning: Boolean = false, ) { - val iconTint by animateColorAsState( - targetValue = if (isSelected) { - TangemTheme.colors.icon.accent - } else { - TangemTheme.colors.icon.informative - }, - label = "Selector icon tint change", - ) - - val textStyle = if (isSelected) { - TangemTheme.typography.subtitle2 - } else { - TangemTheme.typography.body2 - } - Box( modifier = modifier .fillMaxWidth() .clickable { onSelect() }, ) { - Row(modifier = Modifier.fillMaxWidth()) { - SelectorTitleContent( - titleRes = titleRes, - iconRes = iconRes, - iconTint = iconTint, - textStyle = textStyle, - ) - if (amount != null && symbolLength != null && fiatAmount != null) { - SelectorValueContent( - amount = amount, - fiatAmount = fiatAmount, - symbolLength = symbolLength, - textStyle = textStyle, - ) - } else { - SpacerWMax() - } - WarningIcon(showWarning = showWarning) - } - if (showDivider) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(TangemTheme.dimens.size1) - .padding(horizontal = TangemTheme.dimens.spacing12) - .background(TangemTheme.colors.stroke.primary) - .align(Alignment.BottomCenter), - ) - } + SelectorRowItem( + titleRes = titleRes, + iconRes = iconRes, + onSelect = onSelect, + modifier = modifier, + preDot = amount, + postDot = fiatAmount, + ellipsizeOffset = symbolLength, + isSelected = isSelected, + showDivider = showDivider, + ) + WarningIcon(showWarning = showWarning) } } @@ -350,41 +314,6 @@ private fun SelectorTitleContent( ) } -@Composable -private fun RowScope.SelectorValueContent( - amount: TextReference, - fiatAmount: TextReference, - symbolLength: Int, - textStyle: TextStyle, -) { - EllipsisText( - text = amount.resolveReference(), - style = textStyle, - color = TangemTheme.colors.text.primary1, - textAlign = TextAlign.End, - ellipsis = TextEllipsis.OffsetEnd(symbolLength), - modifier = Modifier - .weight(1f) - .padding( - start = TangemTheme.dimens.spacing4, - top = TangemTheme.dimens.spacing14, - bottom = TangemTheme.dimens.spacing14, - ), - ) - Text( - text = "(${fiatAmount.resolveReference()})", - style = textStyle, - color = TangemTheme.colors.text.primary1, - modifier = Modifier - .padding( - start = TangemTheme.dimens.spacing4, - end = TangemTheme.dimens.spacing12, - top = TangemTheme.dimens.spacing14, - bottom = TangemTheme.dimens.spacing14, - ), - ) -} - @Composable private fun WarningIcon(showWarning: Boolean = false) { AnimatedVisibility( @@ -393,15 +322,18 @@ private fun WarningIcon(showWarning: Boolean = false) { enter = fadeIn(), exit = fadeOut(), ) { - Image( - painter = painterResource(R.drawable.ic_alert_triangle_20), - contentDescription = null, - modifier = Modifier - .padding( - vertical = TangemTheme.dimens.spacing12, - horizontal = TangemTheme.dimens.spacing14, - ), - ) + Row { + SpacerWMax() + Image( + painter = painterResource(R.drawable.ic_alert_triangle_20), + contentDescription = null, + modifier = Modifier + .padding( + vertical = TangemTheme.dimens.spacing12, + horizontal = TangemTheme.dimens.spacing14, + ), + ) + } } } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/FeeBlock.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/FeeBlock.kt index 11c2b5d8de..23af8a4893 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/FeeBlock.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/FeeBlock.kt @@ -3,23 +3,19 @@ package com.tangem.features.send.impl.presentation.ui.send import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import com.tangem.core.ui.components.atoms.text.EllipsisText -import com.tangem.core.ui.components.atoms.text.TextEllipsis +import com.tangem.core.ui.components.rows.SelectorRowItem +import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.features.send.impl.R @@ -54,48 +50,24 @@ internal fun FeeBlock(feeState: SendStates.FeeState, isSuccess: Boolean, onClick .clip(TangemTheme.shapes.roundedCornersXMedium) .background(TangemTheme.colors.background.action) .clickable(enabled = !isSuccess) { onClick() } - .padding( - vertical = TangemTheme.dimens.spacing12, - horizontal = TangemTheme.dimens.spacing14, - ), + .padding(TangemTheme.dimens.spacing12), ) { Text( text = stringResource(R.string.common_network_fee_title), style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.secondary, ) - Row( + SelectorRowItem( + titleRes = title, + iconRes = icon, + preDot = stringReference(feeCryptoValue), + postDot = stringReference(feeFiatValue), + ellipsizeOffset = fee.amount.currencySymbol.length, + isSelected = true, + showDivider = false, + paddingValues = PaddingValues(), modifier = Modifier.padding(top = TangemTheme.dimens.spacing8), - verticalAlignment = Alignment.CenterVertically, - ) { - Icon( - painter = painterResource(icon), - tint = TangemTheme.colors.icon.accent, - contentDescription = null, - ) - Text( - text = stringResource(title), - style = TangemTheme.typography.body2, - color = TangemTheme.colors.text.primary1, - modifier = Modifier.padding(start = TangemTheme.dimens.spacing8), - ) - EllipsisText( - text = feeCryptoValue, - style = TangemTheme.typography.body2, - color = TangemTheme.colors.text.primary1, - textAlign = TextAlign.End, - ellipsis = TextEllipsis.OffsetEnd(fee.amount.currencySymbol.length), - modifier = Modifier - .weight(1f) - .padding(start = TangemTheme.dimens.spacing4), - ) - Text( - text = "($feeFiatValue)", - style = TangemTheme.typography.body2, - color = TangemTheme.colors.text.primary1, - modifier = Modifier.padding(start = TangemTheme.dimens.spacing4), - ) - } + ) } } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ChooseFeeBottomSheet.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ChooseFeeBottomSheet.kt index 4cef8254c1..35f1fb8fe4 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ChooseFeeBottomSheet.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ChooseFeeBottomSheet.kt @@ -4,10 +4,11 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.ClickableText -import androidx.compose.material.Text +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString @@ -30,7 +31,10 @@ import kotlinx.collections.immutable.toImmutableList @Composable fun ChooseFeeBottomSheet(config: TangemBottomSheetConfig) { - TangemBottomSheet(config) { content: ChooseFeeBottomSheetConfig -> + TangemBottomSheet( + config = config, + containerColor = TangemTheme.colors.background.tertiary, + ) { content: ChooseFeeBottomSheetConfig -> ChooseFeeBottomSheetContent(content = content) } } @@ -39,7 +43,7 @@ fun ChooseFeeBottomSheet(config: TangemBottomSheetConfig) { private fun ChooseFeeBottomSheetContent(content: ChooseFeeBottomSheetConfig) { Column( modifier = Modifier - .background(TangemTheme.colors.background.primary) + .background(TangemTheme.colors.background.tertiary) .padding(bottom = TangemTheme.dimens.spacing8), ) { Text( @@ -53,6 +57,7 @@ private fun ChooseFeeBottomSheetContent(content: ChooseFeeBottomSheetConfig) { Column( modifier = Modifier .padding(TangemTheme.dimens.spacing16) + .clip(TangemTheme.shapes.roundedCornersXMedium) .background( color = TangemTheme.colors.background.action, shape = TangemTheme.shapes.roundedCornersXMedium, @@ -103,29 +108,36 @@ private fun FooterBlock(readMore: TextReference, readMoreUrl: String, onReadMore @Composable private fun FeeItemsBlock(content: ChooseFeeBottomSheetConfig) { - content.feeItems.forEach { feeItem -> + content.feeItems.forEachIndexed { index, feeItem -> val isSelected = feeItem.feeType == content.selectedFee - val preEllipsizeText = feeItem.amountCrypto - val postEllipsizeText = " ${feeItem.symbolCrypto} (${feeItem.amountFiatFormatted})" + val showDivider = content.feeItems.lastIndex != index + val symbol = " ${feeItem.symbolCrypto}" + val preDotText = "${feeItem.amountCrypto}$symbol" + val postDot = feeItem.amountFiatFormatted + val ellipsizeOffset = symbol.length when (feeItem.feeType) { FeeType.NORMAL -> { SelectorRowItem( titleRes = R.string.common_fee_selector_option_market, iconRes = R.drawable.ic_bird_24, - preEllipsize = TextReference.Str(preEllipsizeText), - postEllipsize = TextReference.Str(postEllipsizeText), + preDot = TextReference.Str(preDotText), + postDot = TextReference.Str(postDot), + ellipsizeOffset = ellipsizeOffset, isSelected = isSelected, onSelect = { content.onSelectFeeType(feeItem.feeType) }, + showDivider = showDivider, ) } FeeType.PRIORITY -> { SelectorRowItem( titleRes = R.string.common_fee_selector_option_fast, iconRes = R.drawable.ic_hare_24, - preEllipsize = TextReference.Str(preEllipsizeText), - postEllipsize = TextReference.Str(postEllipsizeText), + preDot = TextReference.Str(preDotText), + postDot = TextReference.Str(postDot), + ellipsizeOffset = ellipsizeOffset, isSelected = isSelected, onSelect = { content.onSelectFeeType(feeItem.feeType) }, + showDivider = showDivider, ) } } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt index 6ad6ced2fe..723d81e622 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt @@ -2,6 +2,7 @@ package com.tangem.feature.swap.ui import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Icon @@ -30,7 +31,7 @@ import com.tangem.feature.swap.models.states.PercentDifference import com.tangem.feature.swap.models.states.ProviderState /** - * UI Item for swap provider wrapped in a [BaseContainer] with rounded corners + * UI Item for swap provider wrapped with rounded corners * * https://www.figma.com/file/Vs6SkVsFnUPsSCNwlnVf5U/Android-%E2%80%93-UI?type=design&node-id=7856-41909&mode=design&t=vo7dyElitnzSPSW3-4 */ @@ -43,12 +44,21 @@ private val GrayscaleColorFilter: ColorFilter @Composable fun ProviderItemBlock(state: ProviderState, modifier: Modifier = Modifier) { if (state !is ProviderState.Empty) { - BaseContainer(modifier = modifier) { - ProviderItem( - state = state, - modifier = Modifier.align(Alignment.CenterStart), - ) - } + ProviderItem( + state = state, + modifier = modifier + .clip(shape = TangemTheme.shapes.roundedCornersXMedium) + .background( + color = TangemTheme.colors.background.action, + shape = TangemTheme.shapes.roundedCornersXMedium, + ) + .clickable( + enabled = state.onProviderClick != null, + onClick = { state.onProviderClick?.invoke(state.id) }, + ) + .fillMaxWidth() + .padding(vertical = TangemTheme.dimens.spacing12), + ) } } @@ -80,6 +90,7 @@ fun ProviderItem(state: ProviderState, modifier: Modifier = Modifier, isSelected } } +@Deprecated("Replace with InputRowBestRate") @Suppress("LongMethod") @Composable private fun ProviderContentState( @@ -326,22 +337,6 @@ private fun BoxScope.ProviderChevron(selectionType: ProviderState.SelectionType, } } -@Composable -private fun BaseContainer(modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit) { - Box( - modifier = modifier - .background( - color = TangemTheme.colors.background.action, - shape = TangemTheme.shapes.roundedCornersXMedium, - ) - .clip(shape = TangemTheme.shapes.roundedCornersXMedium) - .fillMaxWidth() - .defaultMinSize(minHeight = TangemTheme.dimens.size68), - ) { - content() - } -} - @Composable private fun ErrorProviderIcon(modifier: Modifier = Modifier) { Box( diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt index fa48e3f6fb..e68875f3ee 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt @@ -62,14 +62,7 @@ internal fun SwapScreenContent(state: SwapStateHolder, modifier: Modifier = Modi ) { MainInfo(state) - ProviderItemBlock( - state = state.providerState, - modifier = Modifier - .clickable( - enabled = state.providerState.onProviderClick != null, - onClick = { state.providerState.onProviderClick?.invoke(state.providerState.id) }, - ), - ) + ProviderItemBlock(state = state.providerState) FeeItemBlock(state = state.fee)