Updated on 2026-08-14
This commit is contained in:
commit
967f8b2ea0
17 changed files with 247 additions and 147 deletions
|
|
@ -134,7 +134,7 @@ private fun AddressWithMemoBlock(
|
|||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = address.value,
|
||||
style = TangemTheme.typography.body2,
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
val blockchainAddress = address.briefBlockchainAddress
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
|||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
|
|
@ -16,6 +17,7 @@ import com.tangem.domain.swap.models.SwapDirection
|
|||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountFieldUM
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountType
|
||||
import com.tangem.utils.StringsSigns.DOT
|
||||
|
||||
internal class SwapAmountFieldConverter(
|
||||
private val swapDirection: SwapDirection,
|
||||
|
|
@ -60,15 +62,26 @@ internal class SwapAmountFieldConverter(
|
|||
}
|
||||
|
||||
private fun getSubtitle(selectedType: SwapAmountType, cryptoCurrencyStatus: CryptoCurrencyStatus) = when {
|
||||
selectedType.isEnteringField() -> resourceReference(
|
||||
R.string.common_balance,
|
||||
wrappedList(
|
||||
selectedType.isEnteringField() -> combinedReference(
|
||||
stringReference(
|
||||
cryptoCurrencyStatus.value.amount.format {
|
||||
crypto(cryptoCurrency = cryptoCurrencyStatus.currency)
|
||||
},
|
||||
),
|
||||
stringReference(value = " $DOT "),
|
||||
stringReference(
|
||||
cryptoCurrencyStatus.value.fiatAmount.format {
|
||||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
},
|
||||
),
|
||||
).orMaskWithStars(isBalanceHidden)
|
||||
selectedType.isViewingField() -> resourceReference(R.string.send_with_swap_recipient_amount_text)
|
||||
selectedType.isViewingField() -> resourceReference(
|
||||
R.string.send_with_swap_recipient_get_amount,
|
||||
|
||||
)
|
||||
else -> TextReference.Companion.EMPTY
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,10 +154,7 @@ private fun SwapAmountDivider(modifier: Modifier = Modifier) {
|
|||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.stroke.primary, RoundedCornerShape(32.dp))
|
||||
.padding(1.dp)
|
||||
.background(TangemTheme.colors.text.primary2, RoundedCornerShape(32.dp)) // workaround
|
||||
.background(TangemTheme.colors.icon.informative.copy(alpha = 0.1f), RoundedCornerShape(32.dp))
|
||||
.background(TangemTheme.colors.button.secondary, RoundedCornerShape(32.dp))
|
||||
.padding(horizontal = 11.dp, vertical = 5.dp)
|
||||
.align(Alignment.Center),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ package com.tangem.features.swap.v2.impl.amount.ui
|
|||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
|
|
@ -26,7 +24,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountFieldV2
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.SpacerH2
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
|
|
@ -38,7 +36,6 @@ import com.tangem.core.ui.extensions.stringResourceSafe
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.swap.models.SwapDirection
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountFieldUM
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountType
|
||||
|
|
@ -54,13 +51,17 @@ internal fun SwapAmountContent(
|
|||
clickIntents: SwapAmountClickIntents,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val swapAmountContent = amountUM as? SwapAmountUM.Content
|
||||
val isFixedRate = swapAmountContent?.swapRateType == ExpressRateType.Fixed
|
||||
ConstraintLayout(
|
||||
modifier = modifier,
|
||||
) {
|
||||
val (amountFromRef, amountToRef, middleButtonRef) = createRefs()
|
||||
SwapAmountBlock(
|
||||
amountUM = amountUM,
|
||||
amountFieldUM = amountUM.primaryAmount,
|
||||
selectedAmountType = amountUM.selectedAmountType,
|
||||
selectedQuote = swapAmountContent?.selectedQuote,
|
||||
isFixedRate = isFixedRate,
|
||||
clickIntents = clickIntents,
|
||||
modifier = Modifier.constrainAs(amountFromRef) {
|
||||
top.linkTo(parent.top)
|
||||
|
|
@ -69,8 +70,10 @@ internal fun SwapAmountContent(
|
|||
},
|
||||
)
|
||||
SwapAmountBlock(
|
||||
amountUM = amountUM,
|
||||
amountFieldUM = amountUM.secondaryAmount,
|
||||
selectedAmountType = amountUM.selectedAmountType,
|
||||
selectedQuote = swapAmountContent?.selectedQuote,
|
||||
isFixedRate = isFixedRate,
|
||||
clickIntents = clickIntents,
|
||||
modifier = Modifier.constrainAs(amountToRef) {
|
||||
top.linkTo(amountFromRef.bottom, 8.dp)
|
||||
|
|
@ -100,7 +103,7 @@ private fun SwapAmountBlockSeparator(onClick: () -> Unit, modifier: Modifier = M
|
|||
modifier = modifier
|
||||
.heightIn(max = 28.dp)
|
||||
.clip(RoundedCornerShape(32.dp))
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.background(TangemTheme.colors.button.secondary)
|
||||
.clickable(onClick = onClick)
|
||||
.padding(vertical = 6.dp, horizontal = 12.dp),
|
||||
) {
|
||||
|
|
@ -109,10 +112,6 @@ private fun SwapAmountBlockSeparator(onClick: () -> Unit, modifier: Modifier = M
|
|||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
VerticalDivider(
|
||||
thickness = 1.dp,
|
||||
color = TangemTheme.colors.icon.inactive,
|
||||
)
|
||||
Icon(
|
||||
painter = rememberVectorPainter(
|
||||
ImageVector.vectorResource(R.drawable.ic_close_24),
|
||||
|
|
@ -126,11 +125,14 @@ private fun SwapAmountBlockSeparator(onClick: () -> Unit, modifier: Modifier = M
|
|||
|
||||
@Composable
|
||||
private fun SwapAmountBlock(
|
||||
amountUM: SwapAmountUM,
|
||||
amountFieldUM: SwapAmountFieldUM,
|
||||
selectedQuote: SwapQuoteUM?,
|
||||
selectedAmountType: SwapAmountType,
|
||||
isFixedRate: Boolean,
|
||||
clickIntents: SwapAmountClickIntents,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val isSelectedAmountType = selectedAmountType == amountFieldUM.amountType
|
||||
Column(
|
||||
modifier = modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
|
|
@ -138,7 +140,7 @@ private fun SwapAmountBlock(
|
|||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors.background.action),
|
||||
) {
|
||||
AnimatedVisibility(amountUM.selectedAmountType == amountFieldUM.amountType) {
|
||||
AnimatedVisibility(isSelectedAmountType) {
|
||||
Box {
|
||||
SwapAmountEditBlock(
|
||||
amountFieldUM = amountFieldUM,
|
||||
|
|
@ -157,8 +159,10 @@ private fun SwapAmountBlock(
|
|||
}
|
||||
}
|
||||
SwapAmountInfo(
|
||||
amountUM = amountUM,
|
||||
amountFieldUM = amountFieldUM,
|
||||
selectedQuote = selectedQuote,
|
||||
isSelectedAmountType = isSelectedAmountType,
|
||||
isFixedRate = isFixedRate,
|
||||
onExpandEditField = clickIntents::onExpandEditField,
|
||||
onSelectTokenClick = clickIntents::onSelectTokenClick,
|
||||
onMaxAmountClick = clickIntents::onMaxValueClick,
|
||||
|
|
@ -187,7 +191,7 @@ private fun SwapAmountEditBlock(
|
|||
} else {
|
||||
Text(
|
||||
text = (amountFieldUM.amountField as AmountState.Data).title.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
|
|
@ -201,10 +205,13 @@ private fun SwapAmountEditBlock(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun SwapAmountInfo(
|
||||
amountUM: SwapAmountUM,
|
||||
amountFieldUM: SwapAmountFieldUM,
|
||||
selectedQuote: SwapQuoteUM?,
|
||||
isSelectedAmountType: Boolean,
|
||||
isFixedRate: Boolean,
|
||||
onExpandEditField: (SwapAmountType) -> Unit,
|
||||
onMaxAmountClick: () -> Unit,
|
||||
onSelectTokenClick: () -> Unit,
|
||||
|
|
@ -220,7 +227,7 @@ private fun SwapAmountInfo(
|
|||
indication = ripple(),
|
||||
enabled = (amountFieldUM as? SwapAmountFieldUM.Content)?.isClickEnabled == true,
|
||||
onClick = {
|
||||
if ((amountUM as? SwapAmountUM.Content)?.swapRateType == ExpressRateType.Fixed) {
|
||||
if (isFixedRate) {
|
||||
onExpandEditField(amountFieldUM.amountType)
|
||||
} else {
|
||||
onSelectTokenClick()
|
||||
|
|
@ -237,107 +244,85 @@ private fun SwapAmountInfo(
|
|||
bottom = 16.dp,
|
||||
),
|
||||
)
|
||||
SwapAmountInfoMain(amountFieldUM = amountFieldUM)
|
||||
SwapAmountInfoMain(
|
||||
amountFieldUM = amountFieldUM,
|
||||
selectedQuote = selectedQuote,
|
||||
isSelectedAmountType = isSelectedAmountType,
|
||||
)
|
||||
SpacerWMax()
|
||||
AnimatedContent(
|
||||
amountFieldUM,
|
||||
) { wrappedFieldAmountUM ->
|
||||
if (amountUM is SwapAmountUM.Content) {
|
||||
SwapAmountInfoExtra(
|
||||
amountUM = amountUM,
|
||||
amountFieldUM = wrappedFieldAmountUM,
|
||||
onMaxAmountClick = onMaxAmountClick,
|
||||
targetState = isSelectedAmountType,
|
||||
) { isSelected ->
|
||||
if (isSelected) {
|
||||
AmountMaxButton(onMaxAmountClick)
|
||||
} else {
|
||||
SwapAmountInfoQuote(
|
||||
quoteUM = selectedQuote,
|
||||
isFixedRate = isFixedRate,
|
||||
onSelectTokenClick = onSelectTokenClick,
|
||||
)
|
||||
} else {
|
||||
RectangleShimmer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SwapAmountInfoMain(amountFieldUM: SwapAmountFieldUM, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(
|
||||
targetState = amountFieldUM is SwapAmountFieldUM.Content,
|
||||
private fun SwapAmountInfoMain(
|
||||
amountFieldUM: SwapAmountFieldUM,
|
||||
selectedQuote: SwapQuoteUM?,
|
||||
isSelectedAmountType: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
) { isContent ->
|
||||
if (isContent && amountFieldUM is SwapAmountFieldUM.Content) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
) {
|
||||
AnimatedContent(amountFieldUM is SwapAmountFieldUM.Content) { isContent ->
|
||||
if (isContent && amountFieldUM is SwapAmountFieldUM.Content) {
|
||||
Text(
|
||||
text = amountFieldUM.title.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
)
|
||||
} else {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
modifier = Modifier.width(56.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
AnimatedContent(isSelectedAmountType) { isSelected ->
|
||||
if (isSelected && amountFieldUM is SwapAmountFieldUM.Content) {
|
||||
SpacerH2()
|
||||
EllipsisText(
|
||||
text = amountFieldUM.subtitle.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
ellipsis = amountFieldUM.subtitleEllipsis,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
modifier = Modifier.width(56.dp),
|
||||
)
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.caption2,
|
||||
modifier = Modifier.width(72.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SwapAmountInfoExtra(
|
||||
amountUM: SwapAmountUM.Content,
|
||||
amountFieldUM: SwapAmountFieldUM,
|
||||
onMaxAmountClick: () -> Unit,
|
||||
onSelectTokenClick: () -> Unit,
|
||||
) {
|
||||
when (amountFieldUM.amountType) {
|
||||
SwapAmountType.From -> when (amountUM.swapDirection) {
|
||||
SwapDirection.Direct -> {
|
||||
AnimatedVisibility(
|
||||
visible = amountUM.selectedAmountType == amountFieldUM.amountType,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
AmountMaxButton(onMaxAmountClick)
|
||||
}
|
||||
}
|
||||
SwapDirection.Reverse -> {
|
||||
SwapAmountInfoQuote(
|
||||
quoteUM = amountUM.selectedQuote,
|
||||
swapRateType = amountUM.swapRateType,
|
||||
onSelectTokenClick = onSelectTokenClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SwapAmountType.To -> when (amountUM.swapDirection) {
|
||||
SwapDirection.Direct -> {
|
||||
SwapAmountInfoQuote(
|
||||
quoteUM = amountUM.selectedQuote,
|
||||
swapRateType = amountUM.swapRateType,
|
||||
onSelectTokenClick = onSelectTokenClick,
|
||||
)
|
||||
}
|
||||
SwapDirection.Reverse -> {
|
||||
AnimatedVisibility(
|
||||
visible = amountUM.selectedAmountType == amountFieldUM.amountType,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
AmountMaxButton(onMaxAmountClick)
|
||||
} else {
|
||||
AnimatedContent(selectedQuote) { quote ->
|
||||
when (quote) {
|
||||
is SwapQuoteUM.Content -> {
|
||||
SpacerH2()
|
||||
EllipsisText(
|
||||
text = stringResourceSafe(
|
||||
R.string.send_with_swap_recipient_get_amount,
|
||||
quote.quoteAmountValue.resolveReference(),
|
||||
),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
SwapQuoteUM.Loading -> {
|
||||
SpacerH2()
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.caption2,
|
||||
modifier = Modifier.width(72.dp),
|
||||
)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -353,7 +338,7 @@ private fun AmountMaxButton(onMaxAmountClick: () -> Unit) {
|
|||
modifier = Modifier
|
||||
.padding(end = 16.dp)
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.background(TangemTheme.colors.button.secondary)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = ripple(),
|
||||
|
|
@ -364,11 +349,11 @@ private fun AmountMaxButton(onMaxAmountClick: () -> Unit) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun SwapAmountInfoQuote(quoteUM: SwapQuoteUM, swapRateType: ExpressRateType, onSelectTokenClick: () -> Unit) {
|
||||
private fun SwapAmountInfoQuote(quoteUM: SwapQuoteUM?, isFixedRate: Boolean, onSelectTokenClick: () -> Unit) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.conditionalCompose(
|
||||
condition = swapRateType == ExpressRateType.Fixed,
|
||||
condition = isFixedRate,
|
||||
modifier = {
|
||||
clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
|
|
@ -378,29 +363,20 @@ private fun SwapAmountInfoQuote(quoteUM: SwapQuoteUM, swapRateType: ExpressRateT
|
|||
},
|
||||
),
|
||||
) {
|
||||
when (quoteUM) {
|
||||
is SwapQuoteUM.Content -> EllipsisText(
|
||||
text = quoteUM.quoteAmountValue.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.padding(end = 2.dp),
|
||||
)
|
||||
|
||||
is SwapQuoteUM.Error,
|
||||
is SwapQuoteUM.Empty,
|
||||
-> Box(modifier = Modifier.padding(start = 16.dp))
|
||||
|
||||
is SwapQuoteUM.Loading -> CircularProgressIndicator(
|
||||
color = TangemTheme.colors.icon.inactive,
|
||||
modifier = Modifier
|
||||
.padding(end = 4.dp)
|
||||
.size(20.dp),
|
||||
)
|
||||
|
||||
is SwapQuoteUM.Allowance -> Text(
|
||||
text = "ALLOWANCE NOT IMPLEMENTED",
|
||||
)
|
||||
AnimatedContent(
|
||||
quoteUM,
|
||||
) { quote ->
|
||||
when (quote) {
|
||||
is SwapQuoteUM.Loading -> CircularProgressIndicator(
|
||||
color = TangemTheme.colors.icon.inactive,
|
||||
modifier = Modifier
|
||||
.padding(end = 4.dp)
|
||||
.size(20.dp),
|
||||
)
|
||||
else -> Box(modifier = Modifier.padding(start = 16.dp))
|
||||
}
|
||||
}
|
||||
|
||||
Icon(
|
||||
painter = rememberVectorPainter(
|
||||
ImageVector.vectorResource(R.drawable.ic_chevron_24),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue