Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-14 19:51:58 +05:00
parent 86dc859a67
commit 006669ae0d
26 changed files with 281 additions and 87 deletions

View file

@ -0,0 +1,60 @@
package com.tangem.common.ui.account
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.account.AccountIconSize
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.test.SendScreenTestTags
/**
* A composable function that displays an account label (icon + name) with an optional prefix.
*
* Depending on the type of [accountTitleUM], it either shows a prefix text followed by
* an account label (with name and icon) or just a title text.
*
* @param accountTitleUM The data model containing information about the account title.
* @param modifier Optional [Modifier] for styling.
* @param textStyle The [TextStyle] to apply to the text elements. Defaults to subtitle2 style from TangemTheme.
*/
@Composable
fun AccountTitle(
accountTitleUM: AccountTitleUM,
modifier: Modifier = Modifier,
textStyle: TextStyle = TangemTheme.typography.subtitle2,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
modifier = modifier,
) {
when (accountTitleUM) {
is AccountTitleUM.Account -> {
Text(
text = accountTitleUM.prefixText.resolveReference(),
style = textStyle,
color = TangemTheme.colors.text.tertiary,
)
AccountLabel(
name = accountTitleUM.name,
icon = accountTitleUM.icon,
iconSize = AccountIconSize.ExtraSmall,
nameStyle = textStyle,
)
}
is AccountTitleUM.Text -> Text(
text = accountTitleUM.title.resolveReference(),
style = textStyle,
color = TangemTheme.colors.text.tertiary,
modifier = Modifier.testTag(SendScreenTestTags.AMOUNT_CONTAINER_TITLE),
)
}
}
}

View file

@ -0,0 +1,24 @@
package com.tangem.common.ui.account
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.extensions.TextReference
/**
* A sealed interface representing the title of an account, which can be either a simple text
* or a more complex account representation with a prefix, name, and icon.
*/
@Immutable
sealed interface AccountTitleUM {
/** Represents a simple text title. */
data class Text(
val title: TextReference,
) : AccountTitleUM
/** Represents an account with a prefix, name, and icon. */
data class Account(
val prefixText: TextReference,
val name: TextReference,
val icon: CryptoPortfolioIconUM,
) : AccountTitleUM
}

View file

@ -0,0 +1,27 @@
package com.tangem.common.ui.amountScreen.converters
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.account.toUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.models.account.Account
import com.tangem.utils.converter.Converter
class AmountAccountConverter(
private val prefixText: TextReference,
private val isAccountsMode: Boolean,
private val walletTitle: TextReference,
) : Converter<Account.CryptoPortfolio?, AccountTitleUM> {
override fun convert(value: Account.CryptoPortfolio?): AccountTitleUM {
return if (value != null && isAccountsMode) {
AccountTitleUM.Account(
name = value.accountName.toUM().value,
icon = value.icon.toUM(),
prefixText = prefixText,
)
} else {
AccountTitleUM.Text(
title = walletTitle,
)
}
}
}

View file

@ -1,5 +1,6 @@
package com.tangem.common.ui.amountScreen.converters
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldConverter
import com.tangem.common.ui.amountScreen.models.AmountParameters
@ -36,6 +37,7 @@ class AmountStateConverter(
private val maxEnterAmount: EnterAmountBoundary,
private val iconStateConverter: CryptoCurrencyToIconStateConverter,
private val isBalanceHidden: Boolean,
private val accountTitleUM: AccountTitleUM,
) : Converter<AmountParameters, AmountState> {
private val amountFieldConverter by lazy(LazyThreadSafetyMode.NONE) {
@ -55,7 +57,7 @@ class AmountStateConverter(
}
return AmountState.Data(
title = value.title,
accountTitleUM = accountTitleUM,
availableBalanceCrypto = stringReference(crypto).orMaskWithStars(isBalanceHidden),
availableBalanceFiat = if (isBalanceHidden) {
TextReference.EMPTY

View file

@ -1,6 +1,7 @@
package com.tangem.common.ui.amountScreen.models
import androidx.compose.runtime.Stable
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.appcurrency.model.AppCurrency
@ -14,7 +15,7 @@ sealed class AmountState {
/**
* @param isPrimaryButtonEnabled indicates if next state button enabled
* @param title title
* @param accountTitleUM info about current account or wallet
* @param availableBalanceCrypto user crypto currency balance in crypto
* @param availableBalanceFiat user crypto currency balance in fiat
* @param tokenIconState crypto currency icon state
@ -26,7 +27,7 @@ sealed class AmountState {
*/
data class Data(
override val isPrimaryButtonEnabled: Boolean,
val title: TextReference,
val accountTitleUM: AccountTitleUM,
val availableBalanceCrypto: TextReference,
val availableBalanceFiat: TextReference,
val tokenName: TextReference,

View file

@ -2,12 +2,18 @@ package com.tangem.common.ui.amountScreen.preview
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import com.tangem.common.ui.R
import com.tangem.common.ui.account.AccountNameUM
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.account.toUM
import com.tangem.common.ui.amountScreen.models.AmountFieldModel
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.domain.tokens.model.Amount
import com.tangem.domain.tokens.model.AmountType
import com.tangem.utils.StringsSigns
@ -19,7 +25,7 @@ object AmountStatePreviewData {
val amountState = AmountState.Data(
isPrimaryButtonEnabled = false,
title = stringReference("Family Wallet"),
accountTitleUM = AccountTitleUM.Text(stringReference("Family Wallet")),
availableBalanceCrypto = stringReference("2 130,81231238 USDT"),
availableBalanceFiat = stringReference("1 232 129,12 \$"),
tokenIconState = CurrencyIconState.Loading,
@ -78,6 +84,17 @@ object AmountStatePreviewData {
),
),
)
val amountStateV2Accounts = amountState.copy(
accountTitleUM = AccountTitleUM.Account(
name = AccountNameUM.DefaultMain.value,
icon = CryptoPortfolioIcon.ofDefaultCustomAccount().toUM(),
prefixText = resourceReference(R.string.common_from),
),
availableBalanceCrypto = stringReference("2 130,81231238 USDT"),
availableBalanceFiat = stringReference(" ${StringsSigns.DOT} 1 232 129,12 $"),
)
val amountErrorState = amountWithValueState.copy(
amountTextField = amountWithValueState.amountTextField.copy(
isError = true,

View file

@ -16,12 +16,12 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.account.AccountTitle
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
import com.tangem.core.ui.components.ResizableText
import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
@ -60,11 +60,7 @@ fun AmountBlock(amountState: AmountState, isClickDisabled: Boolean, isEditingDis
.clickable(enabled = !isClickDisabled && !isEditingDisabled, onClick = onClick)
.padding(TangemTheme.dimens.spacing16),
) {
Text(
text = amountState.title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
AccountTitle(accountTitleUM = amountState.accountTitleUM)
SpacerH(20.dp)
CurrencyIcon(
state = amountState.tokenIconState,

View file

@ -14,6 +14,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.account.AccountTitle
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
import com.tangem.core.ui.components.ResizableText
@ -65,7 +67,7 @@ fun AmountBlockV2(
val currencyTitle = amount.cryptoAmount.currencySymbol
AmountBlockV2(
title = amountState.title,
accountTitleUM = amountState.accountTitleUM,
balance = amountState.availableBalanceCrypto,
currencyTitle = currencyTitle,
currencyIconState = amountState.tokenIconState,
@ -82,7 +84,7 @@ fun AmountBlockV2(
@Suppress("LongParameterList", "LongMethod")
@Composable
private fun AmountBlockV2(
title: TextReference,
accountTitleUM: AccountTitleUM,
balance: TextReference,
currencyTitle: String,
currencyIconState: CurrencyIconState,
@ -107,11 +109,7 @@ private fun AmountBlockV2(
.padding(TangemTheme.dimens.spacing16),
) {
Row {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
AccountTitle(accountTitleUM)
SpacerWMax()
Text(
text = balance.resolveReference(),
@ -188,6 +186,7 @@ private class AmountBlockV2PreviewProvider : PreviewParameterProvider<AmountStat
override val values: Sequence<AmountState>
get() = sequenceOf(
AmountStatePreviewData.amountState,
AmountStatePreviewData.amountStateV2Accounts,
)
}
// endregion

View file

@ -18,6 +18,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.R
import com.tangem.common.ui.account.AccountTitle
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.core.ui.components.TextShimmer
import com.tangem.core.ui.components.atoms.text.EllipsisText
@ -58,12 +59,7 @@ internal fun LazyListScope.amountFieldV2(
modifier = Modifier.width(60.dp),
)
} else {
Text(
text = amountState.title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
modifier = Modifier.testTag(SendScreenTestTags.AMOUNT_CONTAINER_TITLE),
)
AccountTitle(amountState.accountTitleUM)
}
AmountFieldV2(
amountUM = amountState,
@ -137,9 +133,8 @@ private fun AmountInfoMain(amountUM: AmountState, modifier: Modifier = Modifier)
) {
when (currentAmount) {
is AmountState.Data -> {
val amountUM = amountUM as AmountState.Data
Text(
text = amountUM.tokenName.resolveReference(),
text = currentAmount.tokenName.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
maxLines = 1,
@ -147,22 +142,22 @@ private fun AmountInfoMain(amountUM: AmountState, modifier: Modifier = Modifier)
)
Row {
EllipsisText(
text = amountUM.availableBalanceCrypto.resolveReference(),
text = currentAmount.availableBalanceCrypto.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
ellipsis = TextEllipsis.OffsetEnd(
amountUM.amountTextField.cryptoAmount.currencySymbol.length,
currentAmount.amountTextField.cryptoAmount.currencySymbol.length,
),
modifier = Modifier
.weight(1f, fill = false)
.testTag(SendScreenTestTags.PRIMARY_AMOUNT),
)
EllipsisText(
text = amountUM.availableBalanceFiat.resolveReference(),
text = currentAmount.availableBalanceFiat.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
ellipsis = TextEllipsis.OffsetEnd(
amountUM.amountTextField.fiatAmount.currencySymbol.length,
currentAmount.amountTextField.fiatAmount.currencySymbol.length,
),
modifier = Modifier.testTag(SendScreenTestTags.SECONDARY_AMOUNT),
)

View file

@ -1,6 +1,6 @@
package com.tangem.utils.converter
interface Converter<I : Any, O : Any?> {
interface Converter<I : Any?, O : Any?> {
fun convert(value: I): O

View file

@ -3,6 +3,7 @@ package com.tangem.features.nft.component
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.models.NFTAsset
@ -12,7 +13,9 @@ interface NFTDetailsBlockComponent : ComposableContentComponent {
val userWalletId: UserWalletId,
val nftAsset: NFTAsset,
val nftCollectionName: String,
val title: TextReference,
val account: Account.CryptoPortfolio?,
val isAccountsMode: Boolean,
val walletTitle: TextReference,
val isSuccessScreen: Boolean,
)

View file

@ -2,11 +2,15 @@ package com.tangem.features.nft.details.block
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.account.toUM
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.ui.extensions.getActiveIconRes
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.features.nft.component.NFTDetailsBlockComponent
import com.tangem.features.nft.details.block.ui.NFTDetailsBlock
import com.tangem.features.nft.impl.R
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -16,13 +20,23 @@ class DefaultNFTDetailsBlockComponent @AssistedInject constructor(
@Assisted private val params: NFTDetailsBlockComponent.Params,
) : NFTDetailsBlockComponent, AppComponentContext by context {
private val account = params.account
@Composable
override fun Content(modifier: Modifier) {
NFTDetailsBlock(
assetName = stringReference(params.nftAsset.name.orEmpty()),
collectionName = stringReference(params.nftCollectionName),
assetImage = params.nftAsset.media?.imageUrl,
title = params.title,
accountTitleUM = if (account != null && params.isAccountsMode) {
AccountTitleUM.Account(
prefixText = resourceReference(R.string.common_from),
name = account.accountName.toUM().value,
icon = account.icon.toUM(),
)
} else {
AccountTitleUM.Text(params.walletTitle)
},
isSuccessScreen = params.isSuccessScreen,
networkIconRes = getActiveIconRes(params.nftAsset.network.rawId),
)

View file

@ -11,6 +11,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.account.AccountTitle
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
@ -23,7 +25,7 @@ import com.tangem.features.nft.impl.R
@Suppress("LongParameterList")
@Composable
internal fun NFTDetailsBlock(
title: TextReference,
accountTitleUM: AccountTitleUM,
assetName: TextReference,
collectionName: TextReference,
assetImage: String?,
@ -38,11 +40,7 @@ internal fun NFTDetailsBlock(
.padding(12.dp),
verticalArrangement = Arrangement.spacedBy(6.dp),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
AccountTitle(accountTitleUM)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
@ -91,7 +89,7 @@ private fun NFTDetailsBlock_Preview() {
collectionName = stringReference("NFT Collection"),
assetImage = null,
networkIconRes = R.drawable.img_polygon_22,
title = stringReference("From My Wallet"),
accountTitleUM = AccountTitleUM.Text(stringReference("From My Wallet")),
isSuccessScreen = false,
)
}

View file

@ -156,6 +156,8 @@ internal class DefaultNFTSendComponent @AssistedInject constructor(
isBalanceHidingFlow = model.isBalanceHiddenFlow,
onLoadFee = model::loadFee,
analyticsSendSource = analyticsSendSource,
account = model.account,
isAccountsMode = model.isAccountsMode,
onSendTransaction = { innerRouter.replaceAll(CommonSendRoute.ConfirmSuccess) },
),
)
@ -181,6 +183,8 @@ internal class DefaultNFTSendComponent @AssistedInject constructor(
callback = model,
currentRoute = model.currentRouteFlow.filterIsInstance<CommonSendRoute.ConfirmSuccess>(),
txUrl = txUrl,
account = model.account,
isAccountsMode = model.isAccountsMode,
),
)
}

View file

@ -13,6 +13,7 @@ import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.nft.models.NFTAsset
@ -88,7 +89,9 @@ internal class NFTSendConfirmComponent @AssistedInject constructor(
nftAsset = params.nftAsset,
nftCollectionName = params.nftCollectionName,
isSuccessScreen = false,
title = resourceReference(R.string.send_from_wallet_name, wrappedList(params.userWallet.name)),
account = params.account,
isAccountsMode = params.isAccountsMode,
walletTitle = resourceReference(R.string.send_from_wallet_name, wrappedList(params.userWallet.name)),
),
)
@ -150,6 +153,8 @@ internal class NFTSendConfirmComponent @AssistedInject constructor(
val nftCollectionName: String,
val cryptoCurrencyStatus: CryptoCurrencyStatus,
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
val account: Account.CryptoPortfolio?,
val isAccountsMode: Boolean,
val callback: ModelCallback,
val currentRoute: Flow<CommonSendRoute.Confirm>,
val isBalanceHidingFlow: StateFlow<Boolean>,

View file

@ -10,6 +10,7 @@ import com.tangem.core.decompose.context.child
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.nft.models.NFTAsset
@ -46,7 +47,9 @@ internal class NFTSendSuccessComponent @AssistedInject constructor(
nftAsset = params.nftAsset,
nftCollectionName = params.nftCollectionName,
isSuccessScreen = true,
title = resourceReference(R.string.nft_asset),
account = params.account,
isAccountsMode = params.isAccountsMode,
walletTitle = resourceReference(R.string.nft_asset),
),
)
@ -86,6 +89,8 @@ internal class NFTSendSuccessComponent @AssistedInject constructor(
val nftAsset: NFTAsset,
val nftCollectionName: String,
val txUrl: String,
val account: Account.CryptoPortfolio?,
val isAccountsMode: Boolean,
val callback: ModelCallback,
)

View file

@ -185,6 +185,14 @@ internal class SendAmountModel @Inject constructor(
) {
if (uiState.value is AmountState.Empty && userWallet != null) {
val isOnlyOneWallet = getWalletsUseCase.invokeSync().size == 1
val walletTitle = if (isOnlyOneWallet) {
resourceReference(R.string.send_from_title)
} else {
resourceReference(
R.string.send_from_wallet_name,
WrappedList(listOf(userWallet?.name.orEmpty())), // TODO [REDACTED_TASK_KEY]
)
}
_uiState.update {
AmountStateConverter(
clickIntents = this,
@ -193,16 +201,14 @@ internal class SendAmountModel @Inject constructor(
maxEnterAmount = maxAmountBoundary,
iconStateConverter = CryptoCurrencyToIconStateConverter(),
isBalanceHidden = params.isBalanceHidingFlow.value,
accountTitleUM = AmountAccountConverter(
isAccountsMode = isAccountsMode,
walletTitle = walletTitle,
prefixText = resourceReference(R.string.common_from),
).convert(account),
).convert(
AmountParameters(
title = if (isOnlyOneWallet) {
resourceReference(R.string.send_from_title)
} else {
resourceReference(
R.string.send_from_wallet_name,
WrappedList(listOf(userWallet?.name.orEmpty())), // TODO [REDACTED_TASK_KEY]
)
},
title = walletTitle,
value = "",
),
)

View file

@ -103,6 +103,7 @@ private class SendAmountContentPreviewProvider : PreviewParameterProvider<Amount
override val values: Sequence<AmountState>
get() = sequenceOf(
AmountStatePreviewData.amountStateV2,
AmountStatePreviewData.amountStateV2Accounts,
)
}
// endregion

View file

@ -201,7 +201,7 @@ class SendConfirmationNotificationsTransformerV2Test {
return AmountState.Data(
isPrimaryButtonEnabled = true,
title = mockk(relaxed = true),
accountTitleUM = mockk(relaxed = true),
availableBalanceCrypto = mockk(relaxed = true),
availableBalanceFiat = mockk(relaxed = true),
tokenName = mockk(relaxed = true),

View file

@ -1,5 +1,6 @@
package com.tangem.features.staking.impl.presentation.state.transformers
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
import com.tangem.common.ui.amountScreen.models.AmountParameters
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
@ -51,6 +52,7 @@ internal class SetAmountDataTransformer(
appCurrency = appCurrencyProvider(),
cryptoCurrencyStatus = cryptoCurrencyStatusProvider(),
isBalanceHidden = false,
accountTitleUM = AccountTitleUM.Text(title),
).convert(
AmountParameters(
title = title,

View file

@ -2,6 +2,7 @@ package com.tangem.features.staking.impl.presentation.state.transformers
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.extensions.remove
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
import com.tangem.common.ui.amountScreen.models.AmountParameters
import com.tangem.common.ui.amountScreen.models.AmountState
@ -234,6 +235,7 @@ internal class SetInitialDataStateTransformer(
iconStateConverter = iconStateConverter,
maxEnterAmount = maxEnterAmount,
isBalanceHidden = false,
accountTitleUM = AccountTitleUM.Text(stringReference(userWalletProvider().name)),
).convert(
AmountParameters(
title = stringReference(userWalletProvider().name),

View file

@ -1,6 +1,7 @@
package com.tangem.features.swap.v2.impl.amount.model.converter
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
import com.tangem.common.ui.amountScreen.converters.AmountAccountConverter
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
import com.tangem.common.ui.amountScreen.converters.MaxEnterAmountConverter
import com.tangem.common.ui.amountScreen.models.AmountParameters
@ -28,14 +29,19 @@ internal class SwapAmountFieldConverter(
private val appCurrency: AppCurrency,
private val clickIntents: AmountScreenClickIntents,
private val isSingleWallet: Boolean,
@Suppress("UnusedPrivateProperty") private val isAccountsMode: Boolean,
@Suppress("UnusedPrivateProperty") private val account: Account.CryptoPortfolio?,
private val isAccountsMode: Boolean,
private val account: Account.CryptoPortfolio?,
) {
private val iconStateConverter = CryptoCurrencyToIconStateConverter()
private val maxEnterAmountConverter = MaxEnterAmountConverter()
fun convert(selectedType: SwapAmountType, cryptoCurrencyStatus: CryptoCurrencyStatus): SwapAmountFieldUM {
val walletTitle = if (isSingleWallet) {
resourceReference(R.string.send_from_title)
} else {
resourceReference(R.string.send_from_wallet_name, wrappedList(userWallet.name))
}
return SwapAmountFieldUM.Content(
amountType = selectedType,
title = stringReference(cryptoCurrencyStatus.currency.name),
@ -55,13 +61,18 @@ internal class SwapAmountFieldConverter(
maxEnterAmount = maxEnterAmountConverter.convert(cryptoCurrencyStatus),
iconStateConverter = iconStateConverter,
isBalanceHidden = isBalanceHidden,
accountTitleUM = AmountAccountConverter(
isAccountsMode = isAccountsMode,
walletTitle = walletTitle,
prefixText = when {
selectedType.isEnteringField() -> resourceReference(R.string.common_from)
selectedType.isViewingField() -> resourceReference(R.string.common_to)
else -> TextReference.Companion.EMPTY
},
).convert(account),
).convert(
AmountParameters(
title = if (isSingleWallet) {
resourceReference(R.string.send_from_title)
} else {
resourceReference(R.string.send_from_wallet_name, wrappedList(userWallet.name))
},
title = walletTitle,
value = "",
),
),

View file

@ -22,10 +22,13 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstrainedLayoutReference
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.ConstraintLayoutScope
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.amountScreen.ui.AmountBlockV2
import com.tangem.core.ui.extensions.TextReference
@ -126,7 +129,7 @@ private fun ConstraintLayoutScope.SwapAmountBlock(
)
AmountBlockV2(
amountState = (amountUM.secondaryAmount.amountField as? AmountState.Data)?.copy(
title = resourceReference(R.string.send_with_swap_recipient_amount_title),
accountTitleUM = AccountTitleUM.Text(resourceReference(R.string.send_with_swap_recipient_amount_title)),
availableBalanceCrypto = TextReference.EMPTY,
) ?: amountUM.secondaryAmount.amountField,
isClickDisabled = true,
@ -231,10 +234,12 @@ private fun BoxScope.SwapDivider() {
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun SwapAmountBlockContent_Preview() {
private fun SwapAmountBlockContent_Preview(
@PreviewParameter(SwapAmountBlockContentPreviewProvider::class) params: SwapAmountUM,
) {
TangemThemePreview {
SwapAmountBlockContent(
amountUM = SwapAmountContentPreview.defaultState,
amountUM = params,
isClickEnabled = true,
onProviderSelectClick = {},
onInfoClick = {},
@ -243,4 +248,12 @@ private fun SwapAmountBlockContent_Preview() {
)
}
}
private class SwapAmountBlockContentPreviewProvider : PreviewParameterProvider<SwapAmountUM> {
override val values: Sequence<SwapAmountUM>
get() = sequenceOf(
SwapAmountContentPreview.defaultState,
SwapAmountContentPreview.defaultStateAccount,
)
}
// endregion

View file

@ -24,6 +24,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import com.tangem.common.ui.account.AccountTitle
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.amountScreen.ui.AmountFieldV2
import com.tangem.core.ui.components.SpacerH16
@ -194,17 +195,14 @@ private fun SwapAmountEditBlock(
verticalArrangement = Arrangement.spacedBy(12.dp),
modifier = modifier.padding(top = 48.dp, bottom = 28.dp),
) {
if (amountFieldUM.amountField !is AmountState.Data) {
when (val amountFieldUM = amountFieldUM.amountField) {
!is AmountState.Data -> {
TextShimmer(
style = TangemTheme.typography.caption2,
modifier = Modifier.width(60.dp),
)
} else {
Text(
text = (amountFieldUM.amountField as AmountState.Data).title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
}
else -> AccountTitle(amountFieldUM.accountTitleUM)
}
AmountFieldV2(
amountUM = amountFieldUM.amountField,
@ -435,6 +433,7 @@ private class SwapAmountContentPreviewProvider : PreviewParameterProvider<SwapAm
get() = sequenceOf(
SwapAmountContentPreview.emptyState,
SwapAmountContentPreview.defaultState,
SwapAmountContentPreview.defaultStateAccount,
)
}
// endregion

View file

@ -1,5 +1,6 @@
package com.tangem.features.swap.v2.impl.amount.ui.preview
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
import com.tangem.core.ui.components.atoms.text.TextEllipsis
import com.tangem.core.ui.extensions.TextReference
@ -41,7 +42,6 @@ internal data object SwapAmountContentPreview {
canHandleTokens = false,
transactionExtrasType = Network.TransactionExtrasType.NONE,
nameResolvingType = Network.NameResolvingType.NONE,
),
name = "Bitcoin",
symbol = "BTC",
@ -109,7 +109,7 @@ internal data object SwapAmountContentPreview {
secondaryAmount = SwapAmountFieldUM.Content(
amountType = SwapAmountType.To,
amountField = AmountStatePreviewData.amountState.copy(
title = stringReference("Amount to receive"),
accountTitleUM = AccountTitleUM.Text(stringReference("Amount to receive")),
),
title = stringReference("Shiba Inu"),
priceImpact = stringReference("(-10%)"),
@ -132,4 +132,16 @@ internal data object SwapAmountContentPreview {
showBestRateAnimation = false,
showFCAWarning = true,
)
val defaultStateAccount: SwapAmountUM.Content
get() = defaultState.copy(
primaryAmount = (defaultState.primaryAmount as SwapAmountFieldUM.Content).copy(
amountField = AmountStatePreviewData.amountStateV2Accounts,
),
secondaryAmount = (defaultState.secondaryAmount as SwapAmountFieldUM.Content).copy(
amountField = AmountStatePreviewData.amountStateV2Accounts.copy(
accountTitleUM = AccountTitleUM.Text(stringReference("Amount to receive")),
),
),
)
}

View file

@ -16,6 +16,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.common.ui.account.AccountTitle
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.amountScreen.utils.getFiatReference
import com.tangem.common.ui.navigationButtons.NavigationButton
@ -130,24 +132,24 @@ private fun SuccessContent(sendWithSwapUM: SendWithSwapUM, modifier: Modifier =
@Composable
private fun SwapAmountBlock(amountUM: SwapAmountUM.Content) {
val amountFieldUM = amountUM.primaryAmount.amountField as? AmountState.Data ?: return
AmountBlock(
title = resourceReference(
id = R.string.send_from_wallet_name,
formatArgs = wrappedList(
(amountUM.primaryAmount.amountField as? AmountState.Data)?.title
?: TextReference.EMPTY,
),
),
accountTitleUM = amountFieldUM.accountTitleUM,
amountFieldUM = amountUM.primaryAmount,
)
AmountBlock(
title = resourceReference(R.string.send_with_swap_recipient_amount_success_title),
accountTitleUM = AccountTitleUM.Text(resourceReference(R.string.send_with_swap_recipient_amount_success_title)),
amountFieldUM = amountUM.secondaryAmount,
)
}
@Composable
private fun AmountBlock(title: TextReference, amountFieldUM: SwapAmountFieldUM, modifier: Modifier = Modifier) {
private fun AmountBlock(
accountTitleUM: AccountTitleUM,
amountFieldUM: SwapAmountFieldUM,
modifier: Modifier = Modifier,
) {
val amountFieldData = amountFieldUM.amountField as? AmountState.Data ?: return
val cryptoAmount = amountFieldData.amountTextField.cryptoAmount
val fiatAmount = amountFieldData.amountTextField.fiatAmount
@ -158,11 +160,7 @@ private fun AmountBlock(title: TextReference, amountFieldUM: SwapAmountFieldUM,
.background(TangemTheme.colors.background.action)
.padding(12.dp),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
AccountTitle(accountTitleUM)
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically,