Updated on 2026-08-14
This commit is contained in:
parent
9ff657252a
commit
f9ae0d5188
40 changed files with 225 additions and 756 deletions
|
|
@ -13,21 +13,17 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountScreenClickIntentsStub
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.common.ui.amountScreen.ui.amountField
|
||||
import com.tangem.common.ui.amountScreen.ui.amountFieldV2
|
||||
import com.tangem.common.ui.amountScreen.ui.buttons
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
/**
|
||||
* Amount screen with field
|
||||
* @param amountState amount state
|
||||
* @param isBalanceHidden flag hidden balances
|
||||
* @param clickIntents amount screen clicks
|
||||
*/
|
||||
@Composable
|
||||
fun AmountScreenContent(
|
||||
amountState: AmountState,
|
||||
isBalanceHidden: Boolean,
|
||||
clickIntents: AmountScreenClickIntents,
|
||||
modifier: Modifier = Modifier,
|
||||
extraContent: (@Composable () -> Unit)? = null,
|
||||
|
|
@ -38,32 +34,17 @@ fun AmountScreenContent(
|
|||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
if (amountState.isRedesignEnabled) {
|
||||
amountFieldV2(
|
||||
amountState = amountState,
|
||||
onValueChange = clickIntents::onAmountValueChange,
|
||||
onValuePastedTriggerDismiss = clickIntents::onAmountPasteTriggerDismiss,
|
||||
onCurrencyChange = clickIntents::onCurrencyChangeClick,
|
||||
onMaxAmountClick = clickIntents::onMaxValueClick,
|
||||
)
|
||||
if (extraContent != null) {
|
||||
item("EXTRA_CONTENT_KEY") {
|
||||
extraContent()
|
||||
}
|
||||
amountFieldV2(
|
||||
amountState = amountState,
|
||||
onValueChange = clickIntents::onAmountValueChange,
|
||||
onValuePastedTriggerDismiss = clickIntents::onAmountPasteTriggerDismiss,
|
||||
onCurrencyChange = clickIntents::onCurrencyChangeClick,
|
||||
onMaxAmountClick = clickIntents::onMaxValueClick,
|
||||
)
|
||||
if (extraContent != null) {
|
||||
item("EXTRA_CONTENT_KEY") {
|
||||
extraContent()
|
||||
}
|
||||
} else if (amountState is AmountState.Data) {
|
||||
amountField(
|
||||
amountState = amountState,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
onValueChange = clickIntents::onAmountValueChange,
|
||||
onValuePastedTriggerDismiss = clickIntents::onAmountPasteTriggerDismiss,
|
||||
)
|
||||
buttons(
|
||||
segmentedButtonConfig = amountState.segmentedButtonConfig,
|
||||
clickIntents = clickIntents,
|
||||
isSegmentedButtonsEnabled = amountState.isSegmentedButtonsEnabled,
|
||||
selectedButton = amountState.selectedButton,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -78,7 +59,6 @@ private fun SendAmountContentPreview(
|
|||
TangemThemePreview {
|
||||
AmountScreenContent(
|
||||
amountState = amountState,
|
||||
isBalanceHidden = false,
|
||||
clickIntents = AmountScreenClickIntentsStub,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ class AmountCurrencyTransformer(
|
|||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
),
|
||||
selectedButton = prevState.segmentedButtonConfig.indexOfFirst { it.isFiat == value },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,10 +70,9 @@ class AmountReduceByTransformer(
|
|||
error = when {
|
||||
isExceedBalance -> resourceReference(R.string.send_validation_amount_exceeds_balance)
|
||||
isLessThanMinimumIfProvided -> {
|
||||
val minimumAmount = minimumTransactionAmount
|
||||
?.amount
|
||||
?.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
.orEmpty()
|
||||
val minimumAmount = minimumTransactionAmount.amount.format {
|
||||
crypto(cryptoCurrencyStatus.currency)
|
||||
}
|
||||
resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(minimumAmount, minimumAmount),
|
||||
|
|
|
|||
|
|
@ -64,10 +64,9 @@ class AmountReduceToTransformer(
|
|||
error = when {
|
||||
isExceedBalance -> resourceReference(R.string.send_validation_amount_exceeds_balance)
|
||||
isLessThanMinimumIfProvided -> {
|
||||
val minimumAmount = minimumTransactionAmount
|
||||
?.amount
|
||||
?.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
.orEmpty()
|
||||
val minimumAmount = minimumTransactionAmount.amount.format {
|
||||
crypto(cryptoCurrencyStatus.currency)
|
||||
}
|
||||
resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(minimumAmount, minimumAmount),
|
||||
|
|
|
|||
|
|
@ -1,104 +1,35 @@
|
|||
package com.tangem.common.ui.amountScreen.converters
|
||||
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldConverter
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldConverterV2
|
||||
import com.tangem.common.ui.amountScreen.models.AmountParameters
|
||||
import com.tangem.common.ui.amountScreen.models.AmountSegmentedButtonsConfig
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
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
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.StringsSigns.DOT
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* Converts initial [String] to [AmountState]
|
||||
*
|
||||
* @property clickIntents amount screen clicks
|
||||
* @property appCurrencyProvider selected app currency provider
|
||||
* @property maxEnterAmount max enter amount data
|
||||
* @property cryptoCurrencyStatusProvider current cryptocurrency status provider
|
||||
* @property iconStateConverter currency icon converter
|
||||
*/
|
||||
@Deprecated("Use AmountStateConverterV2")
|
||||
class AmountStateConverter(
|
||||
private val clickIntents: AmountScreenClickIntents,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
private val maxEnterAmount: EnterAmountBoundary,
|
||||
private val iconStateConverter: CryptoCurrencyToIconStateConverter,
|
||||
) : Converter<AmountParameters, AmountState> {
|
||||
|
||||
private val amountFieldConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
AmountFieldConverter(
|
||||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatusProvider = cryptoCurrencyStatusProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
)
|
||||
}
|
||||
|
||||
override fun convert(value: AmountParameters): AmountState {
|
||||
val appCurrency = appCurrencyProvider()
|
||||
val status = cryptoCurrencyStatusProvider()
|
||||
val fiat = maxEnterAmount.fiatAmount.format { fiat(appCurrency.code, appCurrency.symbol) }
|
||||
val crypto = maxEnterAmount.amount.format { crypto(status.currency) }
|
||||
val hasNoFeeRate = status.value.fiatRate.isNullOrZero()
|
||||
|
||||
return AmountState.Data(
|
||||
title = value.title,
|
||||
availableBalance = resourceReference(R.string.common_crypto_fiat_format, wrappedList(crypto, fiat)),
|
||||
availableBalanceCrypto = stringReference(crypto),
|
||||
availableBalanceFiat = stringReference(fiat),
|
||||
tokenName = stringReference(status.currency.name),
|
||||
tokenIconState = iconStateConverter.convert(status),
|
||||
amountTextField = amountFieldConverter.convert(value.value),
|
||||
isPrimaryButtonEnabled = false,
|
||||
appCurrency = appCurrency,
|
||||
segmentedButtonConfig = persistentListOf(
|
||||
AmountSegmentedButtonsConfig(
|
||||
title = stringReference(status.currency.symbol),
|
||||
iconState = iconStateConverter.convertCustom(
|
||||
value = status,
|
||||
forceGrayscale = hasNoFeeRate,
|
||||
showCustomTokenBadge = false,
|
||||
),
|
||||
isFiat = false,
|
||||
),
|
||||
AmountSegmentedButtonsConfig(
|
||||
title = stringReference(appCurrency.code),
|
||||
iconUrl = appCurrency.iconSmallUrl,
|
||||
isFiat = true,
|
||||
),
|
||||
),
|
||||
isSegmentedButtonsEnabled = !hasNoFeeRate,
|
||||
selectedButton = 0,
|
||||
isRedesignEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts initial [String] to [AmountState]
|
||||
*
|
||||
* @property clickIntents amount screen clicks
|
||||
* @property appCurrency selected app currency
|
||||
* @property maxEnterAmount max enter amount data
|
||||
* @property cryptoCurrencyStatus current cryptocurrency status
|
||||
* @property maxEnterAmount max enter amount data
|
||||
* @property iconStateConverter currency icon converter
|
||||
* @property isBalanceHidden is balance hidden status
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
class AmountStateConverterV2(
|
||||
class AmountStateConverter(
|
||||
private val clickIntents: AmountScreenClickIntents,
|
||||
private val appCurrency: AppCurrency,
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
|
|
@ -108,7 +39,7 @@ class AmountStateConverterV2(
|
|||
) : Converter<AmountParameters, AmountState> {
|
||||
|
||||
private val amountFieldConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
AmountFieldConverterV2(
|
||||
AmountFieldConverter(
|
||||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrency = appCurrency,
|
||||
|
|
@ -118,19 +49,13 @@ class AmountStateConverterV2(
|
|||
override fun convert(value: AmountParameters): AmountState {
|
||||
val fiat = maxEnterAmount.fiatAmount.format { fiat(appCurrency.code, appCurrency.symbol) }
|
||||
val crypto = maxEnterAmount.amount.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
val noFeeRate = cryptoCurrencyStatus.value.fiatRate.isNullOrZero()
|
||||
|
||||
if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) {
|
||||
return AmountState.Empty(isRedesignEnabled = true)
|
||||
return AmountState.Empty
|
||||
}
|
||||
|
||||
return AmountState.Data(
|
||||
title = value.title,
|
||||
availableBalance = combinedReference(
|
||||
stringReference(crypto),
|
||||
stringReference(" $DOT "),
|
||||
stringReference(fiat),
|
||||
).orMaskWithStars(isBalanceHidden),
|
||||
availableBalanceCrypto = stringReference(crypto).orMaskWithStars(isBalanceHidden),
|
||||
availableBalanceFiat = if (isBalanceHidden) {
|
||||
TextReference.EMPTY
|
||||
|
|
@ -145,25 +70,6 @@ class AmountStateConverterV2(
|
|||
amountTextField = amountFieldConverter.convert(value.value),
|
||||
isPrimaryButtonEnabled = false,
|
||||
appCurrency = appCurrency,
|
||||
segmentedButtonConfig = persistentListOf(
|
||||
AmountSegmentedButtonsConfig(
|
||||
title = stringReference(cryptoCurrencyStatus.currency.symbol),
|
||||
iconState = iconStateConverter.convertCustom(
|
||||
value = cryptoCurrencyStatus,
|
||||
forceGrayscale = noFeeRate,
|
||||
showCustomTokenBadge = false,
|
||||
),
|
||||
isFiat = false,
|
||||
),
|
||||
AmountSegmentedButtonsConfig(
|
||||
title = stringReference(appCurrency.code),
|
||||
iconUrl = appCurrency.iconSmallUrl,
|
||||
isFiat = true,
|
||||
),
|
||||
),
|
||||
isSegmentedButtonsEnabled = !noFeeRate,
|
||||
selectedButton = 0,
|
||||
isRedesignEnabled = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,10 @@ package com.tangem.common.ui.amountScreen.converters.field
|
|||
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
|
|
@ -32,14 +35,7 @@ class AmountBoundaryUpdateTransformer(
|
|||
val fiat = maxEnterAmount.fiatAmount.format { fiat(appCurrency.code, appCurrency.symbol) }
|
||||
val crypto = maxEnterAmount.amount.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
|
||||
val availableBalance = combinedReference(
|
||||
stringReference(crypto),
|
||||
stringReference(" $DOT "),
|
||||
stringReference(fiat),
|
||||
)
|
||||
|
||||
return prevState.copy(
|
||||
availableBalance = availableBalance.orMaskWithStars(isBalanceHidden),
|
||||
availableBalanceCrypto = stringReference(crypto).orMaskWithStars(isBalanceHidden),
|
||||
availableBalanceFiat = if (isBalanceHidden) {
|
||||
TextReference.EMPTY
|
||||
|
|
|
|||
|
|
@ -13,75 +13,10 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.tokens.model.Amount
|
||||
import com.tangem.domain.tokens.model.AmountType
|
||||
import com.tangem.domain.tokens.model.convertToAmount
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Converts initial [String] to [AmountFieldModel]
|
||||
*
|
||||
* @property clickIntents amount screen clicks
|
||||
* @property appCurrencyProvider selected app currency provider
|
||||
* @property cryptoCurrencyStatusProvider current cryptocurrency status provider
|
||||
*/
|
||||
@Deprecated("Use AmountFieldConverterV2")
|
||||
class AmountFieldConverter(
|
||||
private val clickIntents: AmountScreenClickIntents,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
) : Converter<String, AmountFieldModel> {
|
||||
|
||||
override fun convert(value: String): AmountFieldModel {
|
||||
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
|
||||
val cryptoDecimal = value.toBigDecimalOrNull() ?: BigDecimal.ZERO
|
||||
val cryptoAmount = cryptoDecimal.convertToAmount(cryptoCurrencyStatus.currency)
|
||||
val fiatRate = cryptoCurrencyStatus.value.fiatRate
|
||||
val (fiatValue, fiatDecimal) = when {
|
||||
fiatRate.isNullOrZero() -> "" to null
|
||||
value.isEmpty() -> "" to BigDecimal.ZERO
|
||||
else -> {
|
||||
val fiatDecimal = fiatRate?.multiply(cryptoDecimal)
|
||||
val fiatValue = fiatDecimal?.parseBigDecimal(FIAT_DECIMALS).orEmpty()
|
||||
fiatValue to fiatDecimal
|
||||
}
|
||||
}
|
||||
val isDoneActionEnabled = !cryptoDecimal.isNullOrZero()
|
||||
return AmountFieldModel(
|
||||
value = value,
|
||||
fiatValue = fiatValue,
|
||||
onValueChange = clickIntents::onAmountValueChange,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = if (isDoneActionEnabled) ImeAction.Done else ImeAction.None,
|
||||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { clickIntents.onAmountNext() },
|
||||
),
|
||||
isFiatValue = false,
|
||||
cryptoAmount = cryptoAmount,
|
||||
fiatAmount = getAppCurrencyAmount(fiatDecimal, appCurrencyProvider()),
|
||||
isError = false,
|
||||
isWarning = false,
|
||||
error = TextReference.EMPTY,
|
||||
isFiatUnavailable = fiatRate == null,
|
||||
isValuePasted = false,
|
||||
onValuePastedTriggerDismiss = clickIntents::onAmountPasteTriggerDismiss,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getAppCurrencyAmount(fiatValue: BigDecimal?, appCurrency: AppCurrency) = Amount(
|
||||
currencySymbol = appCurrency.symbol,
|
||||
value = fiatValue,
|
||||
decimals = FIAT_DECIMALS,
|
||||
type = AmountType.FiatType(appCurrency.code),
|
||||
)
|
||||
|
||||
private companion object {
|
||||
private const val FIAT_DECIMALS = 2
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts initial [String] to [AmountFieldModel]
|
||||
*
|
||||
|
|
@ -89,7 +24,7 @@ class AmountFieldConverter(
|
|||
* @property appCurrency selected app currency
|
||||
* @property cryptoCurrencyStatus current cryptocurrency status
|
||||
*/
|
||||
class AmountFieldConverterV2(
|
||||
class AmountFieldConverter(
|
||||
private val clickIntents: AmountScreenClickIntents,
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val appCurrency: AppCurrency,
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class AmountFieldSetMaxAmountTransformer(
|
|||
isError = isLessThanMinimumIfProvided,
|
||||
error = when {
|
||||
isLessThanMinimumIfProvided -> {
|
||||
val minimumAmount = minAmount?.amount.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
val minimumAmount = minAmount.amount.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(minimumAmount, minimumAmount),
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
package com.tangem.common.ui.amountScreen.models
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
/**
|
||||
* Segmented buttons config
|
||||
*
|
||||
* @param title button title
|
||||
* @param iconState currency icon state
|
||||
* @param iconUrl currency icon url
|
||||
* @param isFiat is fiat currency
|
||||
*/
|
||||
@Immutable
|
||||
data class AmountSegmentedButtonsConfig(
|
||||
val title: TextReference,
|
||||
val iconState: CurrencyIconState? = null,
|
||||
val iconUrl: String? = null,
|
||||
val isFiat: Boolean,
|
||||
)
|
||||
|
|
@ -4,7 +4,6 @@ import androidx.compose.runtime.Stable
|
|||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import java.math.BigDecimal
|
||||
|
||||
/** Model for amount state */
|
||||
|
|
@ -12,18 +11,13 @@ import java.math.BigDecimal
|
|||
sealed class AmountState {
|
||||
|
||||
abstract val isPrimaryButtonEnabled: Boolean
|
||||
abstract val isRedesignEnabled: Boolean
|
||||
|
||||
/**
|
||||
* @param isPrimaryButtonEnabled indicates if next state button enabled
|
||||
* @param title title
|
||||
* @param availableBalance user crypto currency balance with fiat balance
|
||||
* @param availableBalanceCrypto user crypto currency balance in crypto
|
||||
* @param availableBalanceFiat user crypto currency balance in fiat
|
||||
* @param tokenIconState crypto currency icon state
|
||||
* @param segmentedButtonConfig currency switcher config
|
||||
* @param selectedButton selected currency index
|
||||
* @param isSegmentedButtonsEnabled indicates if currency switches is enabled
|
||||
* @param amountTextField amount field state
|
||||
* @param appCurrency app currency
|
||||
* @param isEditingDisabled indicated whether amount is editable
|
||||
|
|
@ -32,17 +26,11 @@ sealed class AmountState {
|
|||
*/
|
||||
data class Data(
|
||||
override val isPrimaryButtonEnabled: Boolean,
|
||||
override val isRedesignEnabled: Boolean,
|
||||
val title: TextReference,
|
||||
@Deprecated("Remove with SEND_REDESIGNED toggle")
|
||||
val availableBalance: TextReference,
|
||||
val availableBalanceCrypto: TextReference,
|
||||
val availableBalanceFiat: TextReference,
|
||||
val tokenName: TextReference,
|
||||
val tokenIconState: CurrencyIconState,
|
||||
val segmentedButtonConfig: PersistentList<AmountSegmentedButtonsConfig>,
|
||||
val selectedButton: Int,
|
||||
val isSegmentedButtonsEnabled: Boolean,
|
||||
val amountTextField: AmountFieldModel,
|
||||
val appCurrency: AppCurrency,
|
||||
val isEditingDisabled: Boolean = false,
|
||||
|
|
@ -50,8 +38,7 @@ sealed class AmountState {
|
|||
val isIgnoreReduce: Boolean = false,
|
||||
) : AmountState()
|
||||
|
||||
data class Empty(
|
||||
override val isPrimaryButtonEnabled: Boolean = false,
|
||||
override val isRedesignEnabled: Boolean,
|
||||
) : AmountState()
|
||||
data object Empty : AmountState() {
|
||||
override val isPrimaryButtonEnabled: Boolean = false
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package com.tangem.common.ui.amountScreen.preview
|
|||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import com.tangem.common.ui.amountScreen.models.AmountFieldModel
|
||||
import com.tangem.common.ui.amountScreen.models.AmountSegmentedButtonsConfig
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
|
@ -12,31 +11,18 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.tokens.model.Amount
|
||||
import com.tangem.domain.tokens.model.AmountType
|
||||
import com.tangem.utils.StringsSigns
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
object AmountStatePreviewData {
|
||||
|
||||
val emptyState = AmountState.Empty(isRedesignEnabled = true)
|
||||
val emptyState = AmountState.Empty
|
||||
|
||||
val amountState = AmountState.Data(
|
||||
isPrimaryButtonEnabled = false,
|
||||
title = stringReference("Family Wallet"),
|
||||
availableBalance = stringReference("2 130,81231238 USDT • 2 129,12 \$)"),
|
||||
availableBalanceCrypto = stringReference("2 130,81231238 USDT"),
|
||||
availableBalanceFiat = stringReference("1 232 129,12 \$"),
|
||||
tokenIconState = CurrencyIconState.Loading,
|
||||
segmentedButtonConfig = persistentListOf(
|
||||
AmountSegmentedButtonsConfig(
|
||||
title = stringReference("USDT"),
|
||||
iconState = CurrencyIconState.Locked,
|
||||
isFiat = false,
|
||||
),
|
||||
AmountSegmentedButtonsConfig(
|
||||
title = stringReference("USD"),
|
||||
isFiat = true,
|
||||
),
|
||||
),
|
||||
appCurrency = AppCurrency.Default,
|
||||
tokenName = stringReference("Tether"),
|
||||
amountTextField = AmountFieldModel(
|
||||
|
|
@ -65,12 +51,9 @@ object AmountStatePreviewData {
|
|||
isValuePasted = false,
|
||||
onValuePastedTriggerDismiss = {},
|
||||
),
|
||||
isSegmentedButtonsEnabled = true,
|
||||
selectedButton = 0,
|
||||
isRedesignEnabled = false,
|
||||
)
|
||||
|
||||
val amountWithValueState = amountState.copy(
|
||||
private val amountWithValueState = amountState.copy(
|
||||
amountTextField = amountState.amountTextField.copy(
|
||||
value = "100.00",
|
||||
cryptoAmount = amountState.amountTextField.cryptoAmount.copy(
|
||||
|
|
@ -84,16 +67,10 @@ object AmountStatePreviewData {
|
|||
)
|
||||
|
||||
val amountStateV2 = amountState.copy(
|
||||
isRedesignEnabled = true,
|
||||
availableBalance = stringReference("2 130,81231238 USDT • 2 129,12 \$)"),
|
||||
availableBalanceCrypto = stringReference("2 130,81231238 USDT"),
|
||||
availableBalanceFiat = stringReference(" ${StringsSigns.DOT} 1 232 129,12 $"),
|
||||
)
|
||||
|
||||
val amountWithValueFiatState = amountWithValueState.copy(
|
||||
amountTextField = amountWithValueState.amountTextField.copy(isFiatValue = false),
|
||||
)
|
||||
|
||||
val amountStateV2WithoutRates = amountState.copy(
|
||||
amountTextField = amountState.amountTextField.copy(
|
||||
fiatAmount = amountState.amountTextField.fiatAmount.copy(
|
||||
|
|
|
|||
|
|
@ -16,10 +16,13 @@ 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 androidx.compose.ui.unit.dp
|
||||
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.anyDecimals
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
|
|
@ -56,7 +59,16 @@ fun AmountBlock(amountState: AmountState, isClickDisabled: Boolean, isEditingDis
|
|||
.clickable(enabled = !isClickDisabled && !isEditingDisabled, onClick = onClick)
|
||||
.padding(TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
CurrencyIcon(state = amountState.tokenIconState)
|
||||
Text(
|
||||
text = amountState.title.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
SpacerH(20.dp)
|
||||
CurrencyIcon(
|
||||
state = amountState.tokenIconState,
|
||||
iconSize = 40.dp,
|
||||
)
|
||||
ResizableText(
|
||||
text = firstAmount,
|
||||
style = TangemTheme.typography.h2,
|
||||
|
|
|
|||
|
|
@ -1,126 +0,0 @@
|
|||
package com.tangem.common.ui.amountScreen.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
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.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||
import com.tangem.common.ui.amountScreen.models.AmountSegmentedButtonsConfig
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.buttons.segmentedbutton.SegmentedButtons
|
||||
import com.tangem.core.ui.components.currency.fiaticon.FiatIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.test.SendScreenTestTags
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
||||
private const val AMOUNT_BUTTONS_KEY = "amountButtonsKey"
|
||||
|
||||
internal fun LazyListScope.buttons(
|
||||
segmentedButtonConfig: PersistentList<AmountSegmentedButtonsConfig>,
|
||||
clickIntents: AmountScreenClickIntents,
|
||||
isSegmentedButtonsEnabled: Boolean,
|
||||
selectedButton: Int,
|
||||
) {
|
||||
item(
|
||||
key = AMOUNT_BUTTONS_KEY,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
Row {
|
||||
if (segmentedButtonConfig.isNotEmpty()) {
|
||||
SegmentedButtons(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.height(TangemTheme.dimens.size40),
|
||||
config = segmentedButtonConfig,
|
||||
showIndication = false,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
clickIntents.onCurrencyChangeClick(it.isFiat)
|
||||
},
|
||||
initialSelectedItem = segmentedButtonConfig.getOrNull(selectedButton),
|
||||
isEnabled = isSegmentedButtonsEnabled,
|
||||
) {
|
||||
AmountCurrencyButton(
|
||||
button = it,
|
||||
isSegmentedButtonsEnabled = isSegmentedButtonsEnabled,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
SpacerWMax()
|
||||
}
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.send_max_amount),
|
||||
style = TangemTheme.typography.button,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing8)
|
||||
.height(TangemTheme.dimens.size40)
|
||||
.clip(shape = RoundedCornerShape(TangemTheme.dimens.radius26))
|
||||
.background(TangemTheme.colors.button.secondary)
|
||||
.clickable {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
clickIntents.onMaxValueClick()
|
||||
}
|
||||
.padding(
|
||||
vertical = TangemTheme.dimens.spacing10,
|
||||
horizontal = TangemTheme.dimens.spacing34,
|
||||
)
|
||||
.testTag(SendScreenTestTags.MAX_BUTTON),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AmountCurrencyButton(button: AmountSegmentedButtonsConfig, isSegmentedButtonsEnabled: Boolean) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(
|
||||
horizontal = TangemTheme.dimens.spacing10,
|
||||
)
|
||||
.testTag(SendScreenTestTags.CURRENCY_BUTTON),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
val iconModifier = Modifier
|
||||
.size(TangemTheme.dimens.size18)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing1)
|
||||
if (button.isFiat) {
|
||||
FiatIcon(
|
||||
url = button.iconUrl,
|
||||
size = TangemTheme.dimens.size18,
|
||||
isGrayscale = !isSegmentedButtonsEnabled,
|
||||
modifier = iconModifier.testTag(SendScreenTestTags.FIAT_ICON),
|
||||
)
|
||||
} else if (button.iconState != null) {
|
||||
CurrencyIcon(
|
||||
state = button.iconState,
|
||||
shouldDisplayNetwork = false,
|
||||
modifier = iconModifier.testTag(SendScreenTestTags.CURRENCY_ICON),
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = button.title.resolveReference(),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.button,
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing8,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
package com.tangem.common.ui.amountScreen.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeightIn
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment.Companion.BottomCenter
|
||||
import androidx.compose.ui.Alignment.Companion.TopCenter
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
import com.tangem.common.ui.amountScreen.models.AmountFieldModel
|
||||
import com.tangem.core.ui.components.fields.AmountTextField
|
||||
import com.tangem.core.ui.components.fields.visualtransformations.AmountVisualTransformation
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
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
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.test.SendScreenTestTags
|
||||
import com.tangem.core.ui.utils.rememberDecimalFormat
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@Composable
|
||||
internal fun AmountField(
|
||||
amountField: AmountFieldModel,
|
||||
appCurrencyCode: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
onValuePastedTriggerDismiss: () -> Unit,
|
||||
) {
|
||||
val decimalFormat = rememberDecimalFormat()
|
||||
val isFiatValue = amountField.isFiatValue
|
||||
val currencyCode = if (isFiatValue) appCurrencyCode else null
|
||||
val (primaryAmount, primaryValue) = if (isFiatValue) {
|
||||
amountField.fiatAmount to amountField.fiatValue
|
||||
} else {
|
||||
amountField.cryptoAmount to amountField.value
|
||||
}
|
||||
val requester = remember { FocusRequester() }
|
||||
val symbolColor = if (primaryValue.isBlank()) TangemTheme.colors.text.disabled else TangemTheme.colors.text.primary1
|
||||
AmountTextField(
|
||||
value = primaryValue,
|
||||
decimals = primaryAmount.decimals,
|
||||
visualTransformation = AmountVisualTransformation(
|
||||
decimals = primaryAmount.decimals,
|
||||
symbol = primaryAmount.currencySymbol,
|
||||
currencyCode = currencyCode,
|
||||
decimalFormat = decimalFormat,
|
||||
symbolColor = symbolColor,
|
||||
),
|
||||
onValueChange = onValueChange,
|
||||
keyboardOptions = amountField.keyboardOptions,
|
||||
keyboardActions = amountField.keyboardActions,
|
||||
textStyle = TangemTheme.typography.h2.copy(
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
),
|
||||
isAutoResize = true,
|
||||
isValuePasted = amountField.isValuePasted,
|
||||
onValuePastedTriggerDismiss = onValuePastedTriggerDismiss,
|
||||
modifier = Modifier
|
||||
.focusRequester(requester)
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing24,
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
)
|
||||
.requiredHeightIn(min = TangemTheme.dimens.size32),
|
||||
)
|
||||
|
||||
LaunchedEffect(key1 = Unit) {
|
||||
delay(timeMillis = 200)
|
||||
requester.requestFocus()
|
||||
}
|
||||
|
||||
AmountSecondary(amountField, appCurrencyCode)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AmountSecondary(amountField: AmountFieldModel, appCurrencyCode: String) {
|
||||
val secondaryAmount = if (amountField.isFiatValue) amountField.cryptoAmount else amountField.fiatAmount
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateContentSize()
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing8,
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
) {
|
||||
val text = if (amountField.isFiatValue) {
|
||||
secondaryAmount.value.format { crypto(secondaryAmount.currencySymbol, secondaryAmount.decimals) }
|
||||
} else {
|
||||
secondaryAmount.value.format {
|
||||
fiat(
|
||||
fiatCurrencySymbol = secondaryAmount.currencySymbol,
|
||||
fiatCurrencyCode = appCurrencyCode,
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = text,
|
||||
style = TangemTheme.typography.caption2.copy(textDirection = TextDirection.ContentOrLtr),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.align(TopCenter)
|
||||
.padding(bottom = TangemTheme.dimens.spacing32)
|
||||
.testTag(SendScreenTestTags.SECONDARY_AMOUNT),
|
||||
)
|
||||
AmountFieldError(
|
||||
isError = amountField.isError,
|
||||
isWarning = amountField.isWarning,
|
||||
error = amountField.error,
|
||||
modifier = Modifier
|
||||
.align(BottomCenter)
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing20,
|
||||
bottom = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AmountFieldError(
|
||||
isError: Boolean,
|
||||
isWarning: Boolean,
|
||||
error: TextReference,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = isError || isWarning,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
modifier = modifier,
|
||||
) {
|
||||
val errorText = remember(this, error) { error }
|
||||
val color = if (isError) TangemTheme.colors.text.warning else TangemTheme.colors.text.attention
|
||||
Text(
|
||||
text = errorText.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = color,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,6 @@ 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.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
|
|
@ -25,68 +23,12 @@ import com.tangem.core.ui.components.atoms.text.EllipsisText
|
|||
import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.test.SendScreenTestTags
|
||||
|
||||
private const val AMOUNT_FIELD_KEY = "amountFieldKey"
|
||||
|
||||
internal fun LazyListScope.amountField(
|
||||
amountState: AmountState.Data,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onValueChange: (String) -> Unit,
|
||||
onValuePastedTriggerDismiss: () -> Unit,
|
||||
) {
|
||||
item(key = AMOUNT_FIELD_KEY) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens.radius16))
|
||||
.background(TangemTheme.colors.background.action),
|
||||
) {
|
||||
Text(
|
||||
text = amountState.title.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing14)
|
||||
.testTag(SendScreenTestTags.AMOUNT_CONTAINER_TITLE),
|
||||
)
|
||||
|
||||
val balance = amountState.availableBalance.orMaskWithStars(isBalanceHidden).resolveReference()
|
||||
AnimatedContent(
|
||||
targetState = balance,
|
||||
label = "Hide Balance Animation",
|
||||
) {
|
||||
Text(
|
||||
text = it,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing2)
|
||||
.testTag(SendScreenTestTags.AMOUNT_CONTAINER_TEXT),
|
||||
)
|
||||
}
|
||||
CurrencyIcon(
|
||||
state = amountState.tokenIconState,
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing32),
|
||||
)
|
||||
AmountField(
|
||||
amountField = amountState.amountTextField,
|
||||
appCurrencyCode = amountState.appCurrency.code,
|
||||
onValueChange = onValueChange,
|
||||
onValuePastedTriggerDismiss = onValuePastedTriggerDismiss,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun LazyListScope.amountFieldV2(
|
||||
amountState: AmountState,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -183,46 +125,49 @@ private fun AmountInfo(amountUM: AmountState, onMaxAmountClick: () -> Unit, modi
|
|||
@Composable
|
||||
private fun AmountInfoMain(amountUM: AmountState, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(
|
||||
targetState = amountUM !is AmountState.Data,
|
||||
targetState = amountUM,
|
||||
modifier = modifier,
|
||||
) { isContent ->
|
||||
if (isContent) {
|
||||
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),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val amountUM = amountUM as AmountState.Data
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
Text(
|
||||
text = amountUM.tokenName.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
)
|
||||
Row {
|
||||
EllipsisText(
|
||||
text = amountUM.availableBalanceCrypto.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
ellipsis = TextEllipsis.OffsetEnd(amountUM.amountTextField.cryptoAmount.currencySymbol.length),
|
||||
modifier = Modifier.weight(1f, fill = false),
|
||||
) { currentAmount ->
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
when (currentAmount) {
|
||||
is AmountState.Data -> {
|
||||
val amountUM = amountUM as AmountState.Data
|
||||
Text(
|
||||
text = amountUM.tokenName.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
)
|
||||
EllipsisText(
|
||||
text = amountUM.availableBalanceFiat.resolveReference(),
|
||||
Row {
|
||||
EllipsisText(
|
||||
text = amountUM.availableBalanceCrypto.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
ellipsis = TextEllipsis.OffsetEnd(
|
||||
amountUM.amountTextField.cryptoAmount.currencySymbol.length,
|
||||
),
|
||||
modifier = Modifier.weight(1f, fill = false),
|
||||
)
|
||||
EllipsisText(
|
||||
text = amountUM.availableBalanceFiat.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
ellipsis = TextEllipsis.OffsetEnd(
|
||||
amountUM.amountTextField.fiatAmount.currencySymbol.length,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
AmountState.Empty -> {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
modifier = Modifier.width(56.dp),
|
||||
)
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
ellipsis = TextEllipsis.OffsetEnd(amountUM.amountTextField.fiatAmount.currencySymbol.length),
|
||||
modifier = Modifier.width(72.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ fun NavigationButtonsBlock(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
PreviousButton(state?.prevButton)
|
||||
NavigationPrimaryButton(state?.primaryButton, modifier = Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ sealed class NavigationButtonsState {
|
|||
|
||||
data class Data(
|
||||
val primaryButton: NavigationButton?,
|
||||
val prevButton: NavigationButton?,
|
||||
val extraButtons: Pair<NavigationButton, NavigationButton>?,
|
||||
val txUrl: String? = null,
|
||||
val onTextClick: (String) -> Unit,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.common.ui.navigationButtons.preview
|
|||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButton
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButtonsState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
|
||||
internal object NavigationButtonsPreview {
|
||||
|
|
@ -26,16 +25,6 @@ internal object NavigationButtonsPreview {
|
|||
onClick = {},
|
||||
)
|
||||
|
||||
private val prev = NavigationButton(
|
||||
textReference = TextReference.EMPTY,
|
||||
iconRes = R.drawable.ic_back_24,
|
||||
isSecondary = true,
|
||||
isIconVisible = true,
|
||||
shouldShowProgress = false,
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
private val finished = NavigationButton(
|
||||
textReference = resourceReference(R.string.common_close),
|
||||
isSecondary = false,
|
||||
|
|
@ -47,7 +36,6 @@ internal object NavigationButtonsPreview {
|
|||
|
||||
val allButtons = NavigationButtonsState.Data(
|
||||
primaryButton = finished,
|
||||
prevButton = prev,
|
||||
extraButtons = extraButtons,
|
||||
txUrl = "https://tangem.com",
|
||||
onTextClick = {},
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ internal class SendModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun initialState(): SendUM = SendUM(
|
||||
amountUM = AmountState.Empty(isRedesignEnabled = true),
|
||||
amountUM = AmountState.Empty,
|
||||
destinationUM = SendDestinationInitialStateTransformer(
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
).transform(DestinationUM.Empty()),
|
||||
|
|
|
|||
|
|
@ -26,12 +26,10 @@ internal class SendAmountComponent(
|
|||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
val isBalanceHidden by params.isBalanceHidingFlow.collectAsStateWithLifecycle()
|
||||
val isSendWithSwapAvailable by model.isSendWithSwapAvailable.collectAsStateWithLifecycle()
|
||||
|
||||
SendAmountContent(
|
||||
amountState = state,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
clickIntents = model,
|
||||
isSendWithSwapAvailable = isSendWithSwapAvailable,
|
||||
modifier = modifier,
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ internal class SendAmountModel @Inject constructor(
|
|||
if (uiState.value is AmountState.Empty && userWallet != null) {
|
||||
val isOnlyOneWallet = getWalletsUseCase.invokeSync().size == 1
|
||||
_uiState.update {
|
||||
AmountStateConverterV2(
|
||||
AmountStateConverter(
|
||||
clickIntents = this,
|
||||
appCurrency = appCurrency,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import com.tangem.features.send.v2.subcomponents.amount.ui.preview.SendAmountCli
|
|||
@Composable
|
||||
fun SendAmountContent(
|
||||
amountState: AmountState,
|
||||
isBalanceHidden: Boolean,
|
||||
clickIntents: SendAmountClickIntents,
|
||||
isSendWithSwapAvailable: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -38,7 +37,6 @@ fun SendAmountContent(
|
|||
Column(modifier = modifier.background(TangemTheme.colors.background.tertiary)) {
|
||||
AmountScreenContent(
|
||||
amountState = amountState,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
clickIntents = clickIntents,
|
||||
extraContent = {
|
||||
SendConvertTokenButton(
|
||||
|
|
@ -95,7 +93,6 @@ private fun SendAmountContent_Preview(@PreviewParameter(SendAmountContentPreview
|
|||
TangemThemePreview {
|
||||
SendAmountContent(
|
||||
amountState = params,
|
||||
isBalanceHidden = true,
|
||||
clickIntents = SendAmountClickIntentsStub,
|
||||
isSendWithSwapAvailable = true,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -201,16 +201,11 @@ class SendConfirmationNotificationsTransformerV2Test {
|
|||
|
||||
return AmountState.Data(
|
||||
isPrimaryButtonEnabled = true,
|
||||
isRedesignEnabled = false,
|
||||
title = mockk(relaxed = true),
|
||||
availableBalance = mockk(relaxed = true),
|
||||
availableBalanceCrypto = mockk(relaxed = true),
|
||||
availableBalanceFiat = mockk(relaxed = true),
|
||||
tokenName = mockk(relaxed = true),
|
||||
tokenIconState = mockk(relaxed = true),
|
||||
segmentedButtonConfig = persistentListOf(),
|
||||
selectedButton = 0,
|
||||
isSegmentedButtonsEnabled = false,
|
||||
amountTextField = AmountFieldModel(
|
||||
value = "1.5",
|
||||
onValueChange = {},
|
||||
|
|
|
|||
|
|
@ -52,7 +52,9 @@ internal class StakingAnalyticSender(
|
|||
source = when (value.currentStep) {
|
||||
StakingStep.InitialInfo -> StakeScreenSource.Info
|
||||
StakingStep.Amount -> StakeScreenSource.Amount
|
||||
StakingStep.Confirmation -> StakeScreenSource.Confirmation
|
||||
StakingStep.Success,
|
||||
StakingStep.Confirmation,
|
||||
-> StakeScreenSource.Confirmation
|
||||
StakingStep.Validators,
|
||||
StakingStep.RestakeValidator,
|
||||
StakingStep.RewardsValidators,
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ internal class StakingStateController @Inject constructor(
|
|||
cryptoCurrencyBlockchainId = "",
|
||||
currentStep = StakingStep.InitialInfo,
|
||||
initialInfoState = StakingStates.InitialInfoState.Empty(),
|
||||
amountState = AmountState.Empty(isRedesignEnabled = false),
|
||||
amountState = AmountState.Empty,
|
||||
validatorState = StakingStates.ValidatorState.Empty(),
|
||||
rewardsValidatorsState = StakingStates.RewardsValidatorsState.Empty(),
|
||||
confirmationState = StakingStates.ConfirmationState.Empty(),
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ internal class StakingStateRouter(
|
|||
StakingStep.Amount,
|
||||
-> showConfirmation()
|
||||
StakingStep.Confirmation -> showInitial()
|
||||
StakingStep.Success -> appRouter.pop()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ internal class StakingStateRouter(
|
|||
}
|
||||
}
|
||||
StakingStep.Validators -> showConfirmation()
|
||||
StakingStep.Success -> appRouter.pop()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,4 +138,5 @@ enum class StakingStep {
|
|||
RestakeValidator,
|
||||
Confirmation,
|
||||
Validators,
|
||||
Success,
|
||||
}
|
||||
|
|
@ -46,10 +46,11 @@ internal class SetAmountDataTransformer(
|
|||
return prevState.copy(
|
||||
amountState = AmountStateConverter(
|
||||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatusProvider = cryptoCurrencyStatusProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
iconStateConverter = iconStateConverter,
|
||||
maxEnterAmount = maxEnterAmount,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatusProvider(),
|
||||
isBalanceHidden = false,
|
||||
).convert(
|
||||
AmountParameters(
|
||||
title = title,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ internal class SetButtonsStateTransformer(
|
|||
val buttonsState = if (prevState.isButtonsVisible()) {
|
||||
NavigationButtonsState.Data(
|
||||
primaryButton = getPrimaryButton(prevState),
|
||||
prevButton = getPrevButton(prevState),
|
||||
extraButtons = getExtraButtons(prevState).takeIf { txUrl != null },
|
||||
txUrl = txUrl,
|
||||
onTextClick = urlOpener::openUrl,
|
||||
|
|
@ -64,18 +63,6 @@ internal class SetButtonsStateTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
private fun getPrevButton(prevState: StakingUiState): NavigationButton? {
|
||||
return NavigationButton(
|
||||
textReference = TextReference.EMPTY,
|
||||
iconRes = R.drawable.ic_back_24,
|
||||
isSecondary = true,
|
||||
isIconVisible = true,
|
||||
shouldShowProgress = false,
|
||||
isEnabled = true,
|
||||
onClick = prevState.clickIntents::onPrevClick,
|
||||
).takeIf { prevState.currentStep.isPrevButtonVisible() }
|
||||
}
|
||||
|
||||
private fun getExtraButtons(prevState: StakingUiState): Pair<NavigationButton, NavigationButton> {
|
||||
return NavigationButton(
|
||||
textReference = resourceReference(R.string.common_explore),
|
||||
|
|
@ -111,7 +98,7 @@ internal class SetButtonsStateTransformer(
|
|||
resourceReference(R.string.common_stake)
|
||||
}
|
||||
}
|
||||
|
||||
StakingStep.Success -> resourceReference(R.string.common_close)
|
||||
StakingStep.Confirmation -> getConfirmationButtonText()
|
||||
StakingStep.Validators -> resourceReference(R.string.common_continue)
|
||||
StakingStep.Amount,
|
||||
|
|
@ -125,21 +112,17 @@ internal class SetButtonsStateTransformer(
|
|||
val confirmationState = confirmationState as? StakingStates.ConfirmationState.Data
|
||||
val amountState = amountState as? AmountState.Data
|
||||
return if (confirmationState != null && amountState != null) {
|
||||
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
|
||||
resourceReference(R.string.common_close)
|
||||
} else {
|
||||
when (actionType) {
|
||||
is StakingActionCommonType.Enter -> {
|
||||
val amount = amountState.amountTextField.cryptoAmount.value.orZero()
|
||||
if (confirmationState.isApprovalNeeded && confirmationState.allowance < amount) {
|
||||
resourceReference(R.string.give_permission_title)
|
||||
} else {
|
||||
resourceReference(R.string.common_stake)
|
||||
}
|
||||
when (actionType) {
|
||||
is StakingActionCommonType.Enter -> {
|
||||
val amount = amountState.amountTextField.cryptoAmount.value.orZero()
|
||||
if (confirmationState.isApprovalNeeded && confirmationState.allowance < amount) {
|
||||
resourceReference(R.string.give_permission_title)
|
||||
} else {
|
||||
resourceReference(R.string.common_stake)
|
||||
}
|
||||
is StakingActionCommonType.Exit -> resourceReference(R.string.common_unstake)
|
||||
is StakingActionCommonType.Pending -> confirmationState.pendingAction?.type.getPendingActionTitle()
|
||||
}
|
||||
is StakingActionCommonType.Exit -> resourceReference(R.string.common_unstake)
|
||||
is StakingActionCommonType.Pending -> confirmationState.pendingAction?.type.getPendingActionTitle()
|
||||
}
|
||||
} else {
|
||||
resourceReference(R.string.common_close)
|
||||
|
|
@ -155,6 +138,7 @@ internal class SetButtonsStateTransformer(
|
|||
StakingStep.Amount -> clickIntents.onAmountEnterClick()
|
||||
StakingStep.Confirmation -> onConfirmationClick()
|
||||
StakingStep.RewardsValidators -> Unit
|
||||
StakingStep.Success -> clickIntents.onBackClick()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,17 +162,6 @@ internal class SetButtonsStateTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
private fun StakingStep.isPrevButtonVisible(): Boolean = when (this) {
|
||||
StakingStep.InitialInfo,
|
||||
StakingStep.RewardsValidators,
|
||||
StakingStep.RestakeValidator,
|
||||
StakingStep.Confirmation,
|
||||
StakingStep.Validators,
|
||||
-> false
|
||||
StakingStep.Amount,
|
||||
-> true
|
||||
}
|
||||
|
||||
private fun StakingUiState.isPrimaryButtonDisabled(): Boolean {
|
||||
val initialState = initialInfoState as? StakingStates.InitialInfoState.Data
|
||||
val hasNotStaking = initialState?.yieldBalance == InnerYieldBalanceState.Empty
|
||||
|
|
@ -205,6 +178,7 @@ internal class SetButtonsStateTransformer(
|
|||
StakingStep.RewardsValidators -> rewardsValidatorsState.isPrimaryButtonEnabled
|
||||
StakingStep.RestakeValidator,
|
||||
StakingStep.Validators,
|
||||
StakingStep.Success,
|
||||
-> true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStep
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.features.staking.impl.presentation.state.TransactionDoneState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
|
@ -17,6 +18,7 @@ internal class SetConfirmationStateCompletedTransformer(
|
|||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
confirmationState = prevState.confirmationState.copyWrapped(),
|
||||
currentStep = StakingStep.Success,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -229,10 +229,11 @@ internal class SetInitialDataStateTransformer(
|
|||
)
|
||||
return AmountStateConverter(
|
||||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
iconStateConverter = iconStateConverter,
|
||||
maxEnterAmount = maxEnterAmount,
|
||||
isBalanceHidden = false,
|
||||
).convert(
|
||||
AmountParameters(
|
||||
title = stringReference(userWalletProvider().name),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.isNullOrEmpty
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
|
|
@ -28,7 +29,7 @@ internal object SetTitleTransformer : Transformer<StakingUiState> {
|
|||
R.string.staking_title_stake,
|
||||
wrappedList(prevState.cryptoCurrencyName),
|
||||
)
|
||||
|
||||
StakingStep.Success -> TextReference.EMPTY
|
||||
StakingStep.Confirmation -> {
|
||||
when (actionType) {
|
||||
is StakingActionCommonType.Enter -> resourceReference(
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountBlock
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountBlockV2
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.model.StakingClickIntents
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingNotification
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
|
|
@ -30,7 +31,6 @@ import com.tangem.features.staking.impl.presentation.state.stub.StakingClickInte
|
|||
import com.tangem.features.staking.impl.presentation.ui.block.NotificationsBlock
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.StakingFeeBlock
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.ValidatorBlock
|
||||
import com.tangem.features.staking.impl.presentation.model.StakingClickIntents
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
|
|
@ -60,7 +60,7 @@ internal fun StakingConfirmationContent(
|
|||
subtitle = resourceReference(R.string.staking_transaction_in_progress_text),
|
||||
)
|
||||
}
|
||||
AmountBlock(
|
||||
AmountBlockV2(
|
||||
amountState = amountState,
|
||||
isClickDisabled = !state.isAmountEditable || isTransactionSent || isTransactionInProgress,
|
||||
isEditingDisabled = !state.isAmountEditable && state.innerState != InnerConfirmationStakingState.COMPLETED,
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ private fun StakingAppBar(uiState: StakingUiState) {
|
|||
val (backIcon, click) = when (uiState.currentStep) {
|
||||
StakingStep.Amount,
|
||||
StakingStep.Confirmation,
|
||||
StakingStep.Success,
|
||||
-> R.drawable.ic_close_24 to uiState.clickIntents::onBackClick
|
||||
StakingStep.Validators,
|
||||
StakingStep.RewardsValidators,
|
||||
|
|
@ -108,6 +109,7 @@ private fun StakingAppBar(uiState: StakingUiState) {
|
|||
)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = Modifier) {
|
||||
val currentScreen = uiState.currentStep
|
||||
|
|
@ -136,10 +138,10 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M
|
|||
contentAlignment = Alignment.TopCenter,
|
||||
label = "Staking Screen Navigation",
|
||||
transitionSpec = {
|
||||
val direction = if (initialState.ordinal < targetState.ordinal) {
|
||||
AnimatedContentTransitionScope.SlideDirection.Start
|
||||
} else {
|
||||
AnimatedContentTransitionScope.SlideDirection.End
|
||||
val direction = when {
|
||||
targetState == StakingStep.Success -> AnimatedContentTransitionScope.SlideDirection.Up
|
||||
initialState.ordinal < targetState.ordinal -> AnimatedContentTransitionScope.SlideDirection.Start
|
||||
else -> AnimatedContentTransitionScope.SlideDirection.End
|
||||
}
|
||||
|
||||
slideIntoContainer(towards = direction, animationSpec = tween())
|
||||
|
|
@ -163,7 +165,6 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M
|
|||
}
|
||||
StakingStep.Amount -> AmountScreenContent(
|
||||
amountState = uiState.amountState,
|
||||
isBalanceHidden = uiState.isBalanceHidden,
|
||||
clickIntents = uiState.clickIntents,
|
||||
modifier = Modifier.background(TangemTheme.colors.background.secondary),
|
||||
)
|
||||
|
|
@ -173,6 +174,12 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M
|
|||
validatorState = uiState.validatorState,
|
||||
clickIntents = uiState.clickIntents,
|
||||
)
|
||||
StakingStep.Success -> StakingSuccessContent(
|
||||
amountState = uiState.amountState,
|
||||
state = uiState.confirmationState,
|
||||
validatorState = uiState.validatorState,
|
||||
clickIntents = uiState.clickIntents,
|
||||
)
|
||||
StakingStep.RestakeValidator,
|
||||
StakingStep.Validators,
|
||||
-> StakingValidatorListContent(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
package com.tangem.features.staking.impl.presentation.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountBlock
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.model.StakingClickIntents
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingNotification
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmationStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ValidatorStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.NotificationsBlock
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.StakingFeeBlock
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.ValidatorBlock
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
internal fun StakingSuccessContent(
|
||||
amountState: AmountState,
|
||||
state: StakingStates.ConfirmationState,
|
||||
validatorState: StakingStates.ValidatorState,
|
||||
clickIntents: StakingClickIntents,
|
||||
) {
|
||||
if (state !is StakingStates.ConfirmationState.Data) return
|
||||
val isTransactionSent = state.innerState == InnerConfirmationStakingState.COMPLETED
|
||||
val isTransactionInProgress = state.notifications.any { it is StakingNotification.Warning.TransactionInProgress }
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
TransactionDoneTitle(
|
||||
title = resourceReference(R.string.common_in_progress),
|
||||
subtitle = resourceReference(R.string.staking_transaction_in_progress_text),
|
||||
)
|
||||
AmountBlock(
|
||||
amountState = amountState,
|
||||
isClickDisabled = !state.isAmountEditable || isTransactionSent || isTransactionInProgress,
|
||||
isEditingDisabled = !state.isAmountEditable && state.innerState != InnerConfirmationStakingState.COMPLETED,
|
||||
onClick = clickIntents::onPrevClick,
|
||||
)
|
||||
ValidatorBlock(
|
||||
validatorState = validatorState,
|
||||
isClickable = !isTransactionInProgress,
|
||||
onClick = clickIntents::openValidators,
|
||||
)
|
||||
StakingFeeBlock(feeState = state.feeState)
|
||||
NotificationsBlock(notifications = state.notifications)
|
||||
Spacer(Modifier)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(widthDp = 360, showBackground = true)
|
||||
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview_StakingConfirmationContent() {
|
||||
TangemThemePreview {
|
||||
Column(Modifier.background(TangemTheme.colors.background.primary)) {
|
||||
StakingConfirmationContent(
|
||||
amountState = AmountStatePreviewData.amountState,
|
||||
state = ConfirmationStatePreviewData.assentStakingState,
|
||||
validatorState = ValidatorStatePreviewData.validatorState,
|
||||
clickIntents = StakingClickIntentsStub,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,19 +64,13 @@ sealed class SwapAmountFieldUM {
|
|||
data class Empty(
|
||||
override val amountType: SwapAmountType,
|
||||
) : SwapAmountFieldUM() {
|
||||
override val amountField: AmountState = AmountState.Empty(
|
||||
isPrimaryButtonEnabled = false,
|
||||
isRedesignEnabled = true,
|
||||
)
|
||||
override val amountField: AmountState = AmountState.Empty
|
||||
}
|
||||
|
||||
data class Loading(
|
||||
override val amountType: SwapAmountType,
|
||||
) : SwapAmountFieldUM() {
|
||||
override val amountField: AmountState = AmountState.Empty(
|
||||
isPrimaryButtonEnabled = false,
|
||||
isRedesignEnabled = true,
|
||||
)
|
||||
override val amountField: AmountState = AmountState.Empty
|
||||
}
|
||||
|
||||
data class Content(
|
||||
|
|
|
|||
|
|
@ -1,7 +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.AmountStateConverterV2
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
|
||||
import com.tangem.common.ui.amountScreen.converters.MaxEnterAmountConverter
|
||||
import com.tangem.common.ui.amountScreen.models.AmountParameters
|
||||
import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
||||
|
|
@ -44,7 +44,7 @@ internal class SwapAmountFieldConverter(
|
|||
subtitleEllipsisRight = TextEllipsis.OffsetEnd(appCurrency.symbol.length),
|
||||
priceImpact = null,
|
||||
isClickEnabled = selectedType.isViewingField(),
|
||||
amountField = AmountStateConverterV2(
|
||||
amountField = AmountStateConverter(
|
||||
clickIntents = clickIntents,
|
||||
appCurrency = appCurrency,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
|
|
|
|||
|
|
@ -46,9 +46,7 @@ internal class SwapAmountBalanceHiddenTransformer(
|
|||
val newData = recalculatedPrimary.amountField
|
||||
newData.copy(
|
||||
amountTextField = oldData.amountTextField,
|
||||
selectedButton = oldData.selectedButton,
|
||||
isPrimaryButtonEnabled = oldData.isPrimaryButtonEnabled,
|
||||
isSegmentedButtonsEnabled = oldData.isSegmentedButtonsEnabled,
|
||||
isEditingDisabled = oldData.isEditingDisabled,
|
||||
reduceAmountBy = oldData.reduceAmountBy,
|
||||
isIgnoreReduce = oldData.isIgnoreReduce,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ private fun ConstraintLayoutScope.SwapAmountBlock(
|
|||
AmountBlockV2(
|
||||
amountState = (amountUM.secondaryAmount.amountField as? AmountState.Data)?.copy(
|
||||
title = resourceReference(R.string.send_with_swap_recipient_amount_title),
|
||||
availableBalance = TextReference.EMPTY,
|
||||
availableBalanceCrypto = TextReference.EMPTY,
|
||||
) ?: amountUM.secondaryAmount.amountField,
|
||||
isClickDisabled = true,
|
||||
|
|
|
|||
|
|
@ -97,9 +97,7 @@ internal data object SwapAmountContentPreview {
|
|||
val defaultState = SwapAmountUM.Content(
|
||||
primaryAmount = SwapAmountFieldUM.Content(
|
||||
amountType = SwapAmountType.From,
|
||||
amountField = AmountStatePreviewData.amountState.copy(
|
||||
availableBalance = stringReference("Balance: 100 BTC"),
|
||||
),
|
||||
amountField = AmountStatePreviewData.amountState,
|
||||
title = stringReference("Tether"),
|
||||
subtitleLeft = stringReference("11 101,123123456 BTC"),
|
||||
subtitleRight = stringReference(" ${StringsSigns.DOT} 1 212,12 $"),
|
||||
|
|
@ -112,7 +110,6 @@ internal data object SwapAmountContentPreview {
|
|||
amountType = SwapAmountType.To,
|
||||
amountField = AmountStatePreviewData.amountState.copy(
|
||||
title = stringReference("Amount to receive"),
|
||||
availableBalance = TextReference.EMPTY,
|
||||
),
|
||||
title = stringReference("Shiba Inu"),
|
||||
priceImpact = stringReference("(-10%)"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue