Updated on 2026-08-14
This commit is contained in:
parent
cbe8cb0b3c
commit
4c7016557f
23 changed files with 731 additions and 31 deletions
|
|
@ -40,7 +40,12 @@ fun AmountScreenContent(
|
|||
bottom = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
) {
|
||||
amountField(amountState = amountState, isBalanceHidden = isBalanceHidden)
|
||||
amountField(
|
||||
amountState = amountState,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
onValueChange = clickIntents::onAmountValueChange,
|
||||
onValuePastedTriggerDismiss = clickIntents::onAmountPasteTriggerDismiss,
|
||||
)
|
||||
buttons(
|
||||
segmentedButtonConfig = amountState.segmentedButtonConfig,
|
||||
clickIntents = clickIntents,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.utils.transformer.Transformer
|
|||
/**
|
||||
* Dismisses indication on pasted value
|
||||
*/
|
||||
class AmountPastedTriggerDismissTransformer : Transformer<AmountState> {
|
||||
object AmountPastedTriggerDismissTransformer : Transformer<AmountState> {
|
||||
override fun transform(prevState: AmountState): AmountState {
|
||||
if (prevState !is AmountState.Data) return prevState
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ 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
|
||||
|
|
@ -30,6 +31,7 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
* @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>,
|
||||
|
|
@ -80,4 +82,63 @@ class AmountStateConverter(
|
|||
selectedButton = 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 iconStateConverter currency icon converter
|
||||
*/
|
||||
class AmountStateConverterV2(
|
||||
private val clickIntents: AmountScreenClickIntents,
|
||||
private val appCurrency: AppCurrency,
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val maxEnterAmount: EnterAmountBoundary,
|
||||
private val iconStateConverter: CryptoCurrencyToIconStateConverter,
|
||||
) : Converter<AmountParameters, AmountState> {
|
||||
|
||||
private val amountFieldConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
AmountFieldConverterV2(
|
||||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrency = appCurrency,
|
||||
)
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
return AmountState.Data(
|
||||
title = value.title,
|
||||
availableBalance = resourceReference(R.string.common_crypto_fiat_format, wrappedList(crypto, fiat)),
|
||||
tokenIconState = iconStateConverter.convert(cryptoCurrencyStatus),
|
||||
amountTextField = amountFieldConverter.convert(value.value),
|
||||
isPrimaryButtonEnabled = false,
|
||||
appCurrencyCode = appCurrency.code,
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ class AmountFieldChangeTransformer(
|
|||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val maxEnterAmount: EnterAmountBoundary,
|
||||
private val minimumTransactionAmount: EnterAmountBoundary?,
|
||||
private val reduceAmountBy: BigDecimal = BigDecimal.ZERO,
|
||||
private val value: String,
|
||||
) : Transformer<AmountState> {
|
||||
|
||||
|
|
@ -58,7 +59,7 @@ class AmountFieldChangeTransformer(
|
|||
|
||||
val checkValue = if (amountTextField.isFiatValue) fiatValue else cryptoValue
|
||||
val isExceedBalance = checkValue.checkExceedBalance(maxEnterAmount, amountTextField)
|
||||
val isLessThanMinimumIfProvided = minimumTransactionAmount?.amount?.let { decimalCryptoValue < it } ?: false
|
||||
val isLessThanMinimumIfProvided = minimumTransactionAmount?.amount?.let { decimalCryptoValue < it } == true
|
||||
val isZero = if (amountTextField.isFiatValue) {
|
||||
decimalFiatValue.isNullOrZero()
|
||||
} else {
|
||||
|
|
@ -67,6 +68,7 @@ class AmountFieldChangeTransformer(
|
|||
val isCheckFailed = isExceedBalance || isLessThanMinimumIfProvided
|
||||
return prevState.copy(
|
||||
isPrimaryButtonEnabled = !isZero && !isCheckFailed,
|
||||
reduceAmountBy = reduceAmountBy,
|
||||
amountTextField = amountTextField.copy(
|
||||
value = cryptoValue,
|
||||
fiatValue = fiatValue,
|
||||
|
|
@ -74,10 +76,11 @@ class AmountFieldChangeTransformer(
|
|||
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),
|
||||
|
|
@ -98,6 +101,7 @@ class AmountFieldChangeTransformer(
|
|||
private fun AmountState.Data.emptyState(): AmountState.Data {
|
||||
return copy(
|
||||
isPrimaryButtonEnabled = false,
|
||||
reduceAmountBy = BigDecimal.ZERO,
|
||||
amountTextField = amountTextField.copy(
|
||||
value = "",
|
||||
fiatValue = "",
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@ import com.tangem.utils.isNullOrZero
|
|||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Converts initial [String] to [AmountField]
|
||||
* 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>,
|
||||
|
|
@ -76,6 +77,68 @@ class AmountFieldConverter(
|
|||
type = AmountType.FiatType(appCurrency.code),
|
||||
)
|
||||
|
||||
private companion object {
|
||||
private const val FIAT_DECIMALS = 2
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts initial [String] to [AmountFieldModel]
|
||||
*
|
||||
* @property clickIntents amount screen clicks
|
||||
* @property appCurrency selected app currency
|
||||
* @property cryptoCurrencyStatus current cryptocurrency status
|
||||
*/
|
||||
class AmountFieldConverterV2(
|
||||
private val clickIntents: AmountScreenClickIntents,
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val appCurrency: AppCurrency,
|
||||
) : Converter<String, AmountFieldModel> {
|
||||
|
||||
override fun convert(value: String): AmountFieldModel {
|
||||
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, appCurrency),
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.tangem.core.ui.utils.parseBigDecimal
|
|||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.extensions.isZero
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
/**
|
||||
|
|
@ -26,6 +27,7 @@ class AmountFieldSetMaxAmountTransformer(
|
|||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val maxAmount: EnterAmountBoundary,
|
||||
private val minAmount: EnterAmountBoundary?,
|
||||
private val reduceAmountBy: BigDecimal = BigDecimal.ZERO,
|
||||
) : Transformer<AmountState> {
|
||||
|
||||
override fun transform(prevState: AmountState): AmountState {
|
||||
|
|
@ -42,9 +44,10 @@ class AmountFieldSetMaxAmountTransformer(
|
|||
|
||||
val cryptoValue = decimalCryptoValue.parseBigDecimal(cryptoDecimals)
|
||||
val fiatValue = decimalFiatValue?.parseBigDecimal(fiatDecimals, roundingMode = RoundingMode.HALF_UP).orEmpty()
|
||||
val isLessThanMinimumIfProvided = minAmount?.amount?.let { decimalCryptoValue < it } ?: false
|
||||
val isLessThanMinimumIfProvided = minAmount?.amount?.let { decimalCryptoValue < it } == true
|
||||
return prevState.copy(
|
||||
isPrimaryButtonEnabled = !isLessThanMinimumIfProvided,
|
||||
reduceAmountBy = reduceAmountBy,
|
||||
amountTextField = amountTextField.copy(
|
||||
isValuePasted = true,
|
||||
value = cryptoValue,
|
||||
|
|
@ -52,10 +55,7 @@ class AmountFieldSetMaxAmountTransformer(
|
|||
isError = isLessThanMinimumIfProvided,
|
||||
error = when {
|
||||
isLessThanMinimumIfProvided -> {
|
||||
val minimumAmount = minAmount
|
||||
?.amount
|
||||
?.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
.orEmpty()
|
||||
val minimumAmount = minAmount.amount.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(minimumAmount, minimumAmount),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Stable
|
|||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import java.math.BigDecimal
|
||||
|
||||
/** Model for amount state */
|
||||
@Stable
|
||||
|
|
@ -21,6 +22,8 @@ sealed class AmountState {
|
|||
* @param isSegmentedButtonsEnabled indicates if currency switches is enabled
|
||||
* @param amountTextField amount field state
|
||||
* @param appCurrencyCode app currency code
|
||||
* @param isEditingDisabled indicated whether amount is editable
|
||||
* @param reduceAmountBy reduces amount to be sent by specified value
|
||||
*/
|
||||
data class Data(
|
||||
override val isPrimaryButtonEnabled: Boolean,
|
||||
|
|
@ -32,6 +35,8 @@ sealed class AmountState {
|
|||
val isSegmentedButtonsEnabled: Boolean,
|
||||
val amountTextField: AmountFieldModel,
|
||||
val appCurrencyCode: String,
|
||||
val isEditingDisabled: Boolean = false,
|
||||
val reduceAmountBy: BigDecimal = BigDecimal.ZERO,
|
||||
) : AmountState()
|
||||
|
||||
data class Empty(
|
||||
|
|
|
|||
|
|
@ -25,12 +25,13 @@ import com.tangem.core.ui.components.fields.visualtransformations.AmountVisualTr
|
|||
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.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.utils.rememberDecimalFormat
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@Deprecated("Use AmountField with clicks")
|
||||
@Composable
|
||||
internal fun AmountField(amountField: AmountFieldModel, appCurrencyCode: String) {
|
||||
val decimalFormat = rememberDecimalFormat()
|
||||
|
|
@ -80,6 +81,60 @@ internal fun AmountField(amountField: AmountFieldModel, appCurrencyCode: String)
|
|||
AmountSecondary(amountField, appCurrencyCode)
|
||||
}
|
||||
|
||||
@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() }
|
||||
|
||||
AmountTextField(
|
||||
value = primaryValue,
|
||||
decimals = primaryAmount.decimals,
|
||||
visualTransformation = AmountVisualTransformation(
|
||||
decimals = primaryAmount.decimals,
|
||||
symbol = primaryAmount.currencySymbol,
|
||||
currencyCode = currencyCode,
|
||||
decimalFormat = decimalFormat,
|
||||
),
|
||||
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
|
||||
|
|
@ -96,11 +151,12 @@ private fun AmountSecondary(amountField: AmountFieldModel, appCurrencyCode: Stri
|
|||
val text = if (amountField.isFiatValue) {
|
||||
secondaryAmount.value.format { crypto(secondaryAmount.currencySymbol, secondaryAmount.decimals) }
|
||||
} else {
|
||||
BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = secondaryAmount.value,
|
||||
fiatCurrencySymbol = secondaryAmount.currencySymbol,
|
||||
fiatCurrencyCode = appCurrencyCode,
|
||||
)
|
||||
secondaryAmount.value.format {
|
||||
fiat(
|
||||
fiatCurrencySymbol = secondaryAmount.currencySymbol,
|
||||
fiatCurrencyCode = appCurrencyCode,
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = text,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ internal fun LazyListScope.amountField(
|
|||
amountState: AmountState.Data,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onValueChange: (String) -> Unit,
|
||||
onValuePastedTriggerDismiss: () -> Unit,
|
||||
) {
|
||||
item(key = AMOUNT_FIELD_KEY) {
|
||||
Column(
|
||||
|
|
@ -63,6 +65,8 @@ internal fun LazyListScope.amountField(
|
|||
AmountField(
|
||||
amountField = amountState.amountTextField,
|
||||
appCurrencyCode = amountState.appCurrencyCode,
|
||||
onValueChange = onValueChange,
|
||||
onValuePastedTriggerDismiss = onValuePastedTriggerDismiss,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.tangem.features.send.v2.di
|
|||
|
||||
import com.tangem.core.decompose.di.ModelComponent
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.send.v2.send.model.SendModel
|
||||
import com.tangem.features.send.v2.subcomponents.amount.model.SendAmountModel
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.SendDestinationModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
|
@ -13,6 +15,16 @@ import dagger.multibindings.IntoMap
|
|||
@InstallIn(ModelComponent::class)
|
||||
internal interface SendModelModule {
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(SendModel::class)
|
||||
fun provideSendModel(model: SendModel): Model
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(SendAmountModel::class)
|
||||
fun provideSendAmountModel(model: SendAmountModel): Model
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(SendDestinationModel::class)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import com.tangem.core.ui.decompose.ComposableContentComponent
|
|||
import com.tangem.features.send.v2.api.SendComponent
|
||||
import com.tangem.features.send.v2.send.analytics.SendAnalyticEvents
|
||||
import com.tangem.features.send.v2.send.model.SendModel
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponent
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponentParams
|
||||
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
|
@ -63,7 +65,7 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
|||
private fun createChild(route: SendRoute, factoryContext: AppComponentContext) = when (route) {
|
||||
SendRoute.Empty -> getStubComponent()
|
||||
is SendRoute.Destination -> getDestinationComponent(factoryContext, route)
|
||||
is SendRoute.Amount -> getAmountComponent()
|
||||
is SendRoute.Amount -> getAmountComponent(factoryContext, route)
|
||||
is SendRoute.Fee -> getFeeComponent()
|
||||
SendRoute.Confirm -> getConfirmComponent()
|
||||
}
|
||||
|
|
@ -82,7 +84,20 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
|||
),
|
||||
)
|
||||
|
||||
private fun getAmountComponent() = getStubComponent() // todo
|
||||
private fun getAmountComponent(factoryContext: AppComponentContext, route: SendRoute) = SendAmountComponent(
|
||||
appComponentContext = factoryContext,
|
||||
params = SendAmountComponentParams.AmountParams(
|
||||
state = model.uiState.value.amountUM,
|
||||
currentRoute = currentRoute.filterIsInstance<SendRoute.Amount>(),
|
||||
analyticsCategoryName = SendAnalyticEvents.SEND_CATEGORY,
|
||||
userWallet = model.userWallet,
|
||||
appCurrency = model.appCurrency,
|
||||
cryptoCurrencyStatus = model.cryptoCurrencyStatus,
|
||||
callback = model,
|
||||
isEditMode = route.isEditMode,
|
||||
predefinedAmountValue = model.predefinedAmountValue,
|
||||
),
|
||||
)
|
||||
|
||||
private fun getFeeComponent() = getStubComponent() // todo
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import androidx.compose.runtime.Stable
|
|||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.send.v2.send.ui.state.SendUM
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponent
|
||||
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponent
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -21,20 +23,28 @@ import kotlin.properties.Delegates
|
|||
@Suppress("LongParameterList")
|
||||
internal class SendModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model(), SendDestinationComponent.ModelCallback {
|
||||
) : Model(),
|
||||
SendDestinationComponent.ModelCallback,
|
||||
SendAmountComponent.ModelCallback {
|
||||
|
||||
private val _uiState = MutableStateFlow(initialState())
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
var userWallet: UserWallet by Delegates.notNull()
|
||||
var cryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull()
|
||||
|
||||
private fun initialState(): SendUM = SendUM(
|
||||
amountState = AmountState.Empty(),
|
||||
destinationUM = DestinationUM.Empty(),
|
||||
)
|
||||
var appCurrency: AppCurrency = AppCurrency.Default
|
||||
var predefinedAmountValue: String? = null
|
||||
|
||||
override fun onDestinationResult(destinationUM: DestinationUM) {
|
||||
_uiState.update { it.copy(destinationUM = destinationUM) }
|
||||
}
|
||||
|
||||
override fun onAmountResult(state: AmountState) {
|
||||
_uiState.update { it.copy(amountUM = state) }
|
||||
}
|
||||
|
||||
private fun initialState(): SendUM = SendUM(
|
||||
amountUM = AmountState.Empty(),
|
||||
destinationUM = DestinationUM.Empty(),
|
||||
)
|
||||
}
|
||||
|
|
@ -4,6 +4,6 @@ import com.tangem.common.ui.amountScreen.models.AmountState
|
|||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
|
||||
internal data class SendUM(
|
||||
val amountState: AmountState,
|
||||
val amountUM: AmountState,
|
||||
val destinationUM: DestinationUM,
|
||||
)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.tangem.features.send.v2.subcomponents.amount
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountBlock
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponentParams.AmountBlockParams
|
||||
import com.tangem.features.send.v2.subcomponents.amount.model.SendAmountModel
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
internal class SendAmountBlockComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
private val params: AmountBlockParams,
|
||||
val onResult: (AmountState) -> Unit,
|
||||
val onClick: () -> Unit,
|
||||
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: SendAmountModel = getOrCreateModel(params = params, router = router)
|
||||
|
||||
init {
|
||||
model.uiState.onEach {
|
||||
onResult(it)
|
||||
}.launchIn(componentScope)
|
||||
}
|
||||
|
||||
fun updateState(amountUM: AmountState) = model.updateState(amountUM)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state = model.uiState.collectAsStateWithLifecycle()
|
||||
val isClickEnabled = params.blockClickEnableFlow.collectAsStateWithLifecycle()
|
||||
val isEditingDisabled = params.blockEditDisabledFlow.collectAsStateWithLifecycle()
|
||||
|
||||
AmountBlock(
|
||||
amountState = state.value,
|
||||
isClickDisabled = !isClickEnabled.value,
|
||||
isEditingDisabled = isEditingDisabled.value,
|
||||
onClick = onClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.tangem.features.send.v2.subcomponents.amount
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.common.ui.amountScreen.AmountScreenContent
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponentParams.AmountParams
|
||||
import com.tangem.features.send.v2.subcomponents.amount.model.SendAmountModel
|
||||
|
||||
internal class SendAmountComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
private val params: AmountParams,
|
||||
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: SendAmountModel = getOrCreateModel(params = params)
|
||||
|
||||
fun updateState(amountUM: AmountState) = model.updateState(amountUM)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
AmountScreenContent(
|
||||
amountState = state,
|
||||
isBalanceHidden = false,
|
||||
clickIntents = model,
|
||||
modifier = Modifier.background(TangemTheme.colors.background.tertiary),
|
||||
)
|
||||
}
|
||||
|
||||
interface ModelCallback {
|
||||
fun onAmountResult(amountUM: AmountState)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.tangem.features.send.v2.subcomponents.amount
|
||||
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.send.v2.send.SendRoute
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponent.ModelCallback
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
internal sealed class SendAmountComponentParams {
|
||||
|
||||
abstract val state: AmountState
|
||||
abstract val analyticsCategoryName: String
|
||||
abstract val userWallet: UserWallet
|
||||
abstract val appCurrency: AppCurrency
|
||||
abstract val cryptoCurrencyStatus: CryptoCurrencyStatus
|
||||
|
||||
data class AmountParams(
|
||||
override val state: AmountState,
|
||||
override val analyticsCategoryName: String,
|
||||
override val userWallet: UserWallet,
|
||||
override val appCurrency: AppCurrency,
|
||||
override val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val isEditMode: Boolean,
|
||||
val callback: ModelCallback,
|
||||
val currentRoute: Flow<SendRoute.Amount>,
|
||||
val predefinedAmountValue: String?,
|
||||
) : SendAmountComponentParams()
|
||||
|
||||
data class AmountBlockParams(
|
||||
override val state: AmountState,
|
||||
override val analyticsCategoryName: String,
|
||||
override val userWallet: UserWallet,
|
||||
override val appCurrency: AppCurrency,
|
||||
override val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val blockEditDisabledFlow: StateFlow<Boolean>,
|
||||
val blockClickEnableFlow: StateFlow<Boolean>,
|
||||
) : SendAmountComponentParams()
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.tangem.features.send.v2.subcomponents.amount
|
||||
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer.ReduceByData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import java.math.BigDecimal
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Trigger for reducing amount from another component
|
||||
*/
|
||||
interface SendAmountReduceTrigger {
|
||||
suspend fun triggerReduceBy(reduceBy: ReduceByData)
|
||||
suspend fun triggerReduceTo(reduceTo: BigDecimal)
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger for reducing amount from another component
|
||||
*/
|
||||
interface SendAmountReduceListener {
|
||||
val reduceToTriggerFlow: Flow<BigDecimal>
|
||||
val reduceByTriggerFlow: Flow<ReduceByData>
|
||||
}
|
||||
|
||||
@Singleton
|
||||
internal class DefaultSendAmountReduceTrigger @Inject constructor() :
|
||||
SendAmountReduceTrigger,
|
||||
SendAmountReduceListener {
|
||||
override val reduceToTriggerFlow = MutableSharedFlow<BigDecimal>()
|
||||
override val reduceByTriggerFlow = MutableSharedFlow<ReduceByData>()
|
||||
|
||||
override suspend fun triggerReduceBy(reduceBy: ReduceByData) {
|
||||
reduceByTriggerFlow.emit(reduceBy)
|
||||
}
|
||||
|
||||
override suspend fun triggerReduceTo(reduceTo: BigDecimal) {
|
||||
reduceToTriggerFlow.emit(reduceTo)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.features.send.v2.subcomponents.amount.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TYPE
|
||||
|
||||
internal sealed class SendAmountAnalyticEvents(
|
||||
category: String,
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent(category = category, event = event, params = params) {
|
||||
|
||||
/** Selected currency */
|
||||
data class SelectedCurrency(
|
||||
val categoryName: String,
|
||||
val type: SelectedCurrencyType,
|
||||
) : SendAmountAnalyticEvents(
|
||||
category = categoryName,
|
||||
event = "Selected Currency",
|
||||
params = mapOf(TYPE to type.value),
|
||||
)
|
||||
|
||||
/** Max amount button clicked */
|
||||
data class MaxAmountButtonClicked(
|
||||
val categoryName: String,
|
||||
) : SendAmountAnalyticEvents(category = categoryName, event = "Max Amount Taped")
|
||||
|
||||
internal enum class SelectedCurrencyType(val value: String) {
|
||||
Token("Token"),
|
||||
AppCurrency("App Currency"),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.features.send.v2.subcomponents.amount.di
|
||||
|
||||
import com.tangem.features.send.v2.subcomponents.amount.DefaultSendAmountReduceTrigger
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountReduceListener
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountReduceTrigger
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Module
|
||||
internal object SendAmountModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSendAmountReduceTrigger(): SendAmountReduceTrigger {
|
||||
return DefaultSendAmountReduceTrigger()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSendAmountReduceListener(): SendAmountReduceListener {
|
||||
return DefaultSendAmountReduceTrigger()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
package com.tangem.features.send.v2.subcomponents.amount.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||
import com.tangem.common.ui.amountScreen.converters.*
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldChangeTransformer
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldSetMaxAmountTransformer
|
||||
import com.tangem.common.ui.amountScreen.models.AmountParameters
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase
|
||||
import com.tangem.features.send.v2.send.SendRoute
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponentParams
|
||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountReduceListener
|
||||
import com.tangem.features.send.v2.subcomponents.amount.analytics.SendAmountAnalyticEvents
|
||||
import com.tangem.features.send.v2.subcomponents.amount.analytics.SendAmountAnalyticEvents.SelectedCurrencyType
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import com.tangem.utils.transformer.update
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class SendAmountModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val getMinimumTransactionAmountSyncUseCase: GetMinimumTransactionAmountSyncUseCase,
|
||||
private val sendAmountReduceListener: SendAmountReduceListener,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : Model(), AmountScreenClickIntents {
|
||||
|
||||
private val params: SendAmountComponentParams = paramsContainer.require()
|
||||
|
||||
private val _uiState = MutableStateFlow(params.state)
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
private val analyticsCategoryName = params.analyticsCategoryName
|
||||
private val userWallet = params.userWallet
|
||||
private val cryptoCurrencyStatus = params.cryptoCurrencyStatus
|
||||
|
||||
private var minAmountBoundary: EnterAmountBoundary? = null
|
||||
private var maxAmountBoundary: EnterAmountBoundary = MaxEnterAmountConverter().convert(cryptoCurrencyStatus)
|
||||
|
||||
init {
|
||||
configAmountNavigation()
|
||||
initMinBoundary()
|
||||
subscribeOnAmountReduceByTriggerUpdates()
|
||||
subscribeOnAmountReduceToTriggerUpdates()
|
||||
}
|
||||
|
||||
private fun initMinBoundary() {
|
||||
modelScope.launch {
|
||||
minAmountBoundary = getMinimumTransactionAmountSyncUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
).getOrNull()?.let {
|
||||
EnterAmountBoundary(
|
||||
amount = it,
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate.orZero(),
|
||||
)
|
||||
}
|
||||
|
||||
initialState()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initialState() {
|
||||
val predefinedAmountValue = (params as? SendAmountComponentParams.AmountParams)?.predefinedAmountValue
|
||||
if (uiState.value is AmountState.Empty) {
|
||||
_uiState.update {
|
||||
AmountStateConverterV2(
|
||||
clickIntents = this,
|
||||
appCurrency = params.appCurrency,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
maxEnterAmount = maxAmountBoundary,
|
||||
iconStateConverter = CryptoCurrencyToIconStateConverter(),
|
||||
).convert(
|
||||
AmountParameters(
|
||||
title = stringReference(userWallet.name),
|
||||
value = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
if (predefinedAmountValue != null) {
|
||||
onAmountValueChange(predefinedAmountValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateState(amountUM: AmountState) {
|
||||
if (amountUM !is AmountState.Empty) {
|
||||
_uiState.value = amountUM
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCurrencyChangeClick(isFiat: Boolean) {
|
||||
_uiState.update(AmountCurrencyTransformer(cryptoCurrencyStatus, isFiat))
|
||||
}
|
||||
|
||||
override fun onAmountValueChange(value: String) {
|
||||
_uiState.update(
|
||||
AmountFieldChangeTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
maxEnterAmount = maxAmountBoundary,
|
||||
minimumTransactionAmount = minAmountBoundary,
|
||||
value = value,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onMaxValueClick() {
|
||||
val decimalCryptoValue = cryptoCurrencyStatus.value.amount
|
||||
if (decimalCryptoValue.isNullOrZero()) return
|
||||
|
||||
_uiState.update(
|
||||
AmountFieldSetMaxAmountTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
maxAmount = maxAmountBoundary,
|
||||
minAmount = minAmountBoundary,
|
||||
),
|
||||
)
|
||||
analyticsEventHandler.send(
|
||||
SendAmountAnalyticEvents.MaxAmountButtonClicked(categoryName = analyticsCategoryName),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onAmountPasteTriggerDismiss() {
|
||||
_uiState.update(AmountPastedTriggerDismissTransformer)
|
||||
}
|
||||
|
||||
override fun onAmountNext() {
|
||||
(uiState.value as? AmountState.Data)?.amountTextField?.isFiatValue?.let { isFiatSelected ->
|
||||
analyticsEventHandler.send(
|
||||
SendAmountAnalyticEvents.SelectedCurrency(
|
||||
categoryName = analyticsCategoryName,
|
||||
type = if (isFiatSelected) {
|
||||
SelectedCurrencyType.AppCurrency
|
||||
} else {
|
||||
SelectedCurrencyType.Token
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
saveResult()
|
||||
if ((params as? SendAmountComponentParams.AmountParams)?.isEditMode == true) {
|
||||
router.pop()
|
||||
} else {
|
||||
router.push(SendRoute.Confirm)
|
||||
}
|
||||
}
|
||||
|
||||
private fun subscribeOnAmountReduceToTriggerUpdates() {
|
||||
sendAmountReduceListener.reduceToTriggerFlow
|
||||
.onEach { reduceTo ->
|
||||
_uiState.update(
|
||||
AmountReduceToTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
minimumTransactionAmount = minAmountBoundary,
|
||||
value = reduceTo,
|
||||
),
|
||||
)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun subscribeOnAmountReduceByTriggerUpdates() {
|
||||
sendAmountReduceListener.reduceByTriggerFlow
|
||||
.onEach { reduceByData ->
|
||||
_uiState.update(
|
||||
AmountReduceByTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
minimumTransactionAmount = minAmountBoundary,
|
||||
value = reduceByData,
|
||||
),
|
||||
)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun saveResult() {
|
||||
val params = params as? SendAmountComponentParams.AmountParams ?: return
|
||||
params.callback.onAmountResult(uiState.value)
|
||||
}
|
||||
|
||||
private fun configAmountNavigation() {
|
||||
val params = params as? SendAmountComponentParams.AmountParams ?: return
|
||||
combine(
|
||||
flow = uiState,
|
||||
flow2 = params.currentRoute,
|
||||
transform = { state, route -> state to route },
|
||||
).onEach { (_, _) ->
|
||||
// todo
|
||||
// params.callback.onNavigationResult(
|
||||
// NavigationUM.Content(
|
||||
// title = resourceReference(R.string.send_amount_label),
|
||||
// subtitle = null,
|
||||
// backIconRes = R.drawable.ic_back_24,
|
||||
// backIconClick = {
|
||||
// if (route.isEditMode) {
|
||||
// saveResult()
|
||||
// }
|
||||
// router.pop()
|
||||
// },
|
||||
// primaryButton = ButtonsUM.PrimaryButtonUM(
|
||||
// text = if (route.isEditMode) {
|
||||
// resourceReference(R.string.common_continue)
|
||||
// } else {
|
||||
// resourceReference(R.string.common_next)
|
||||
// },
|
||||
// isEnabled = state.isPrimaryButtonEnabled,
|
||||
// onClick = ::onAmountNext,
|
||||
// ),
|
||||
// prevButton = ButtonsUM.PrimaryButtonUM(
|
||||
// text = TextReference.EMPTY,
|
||||
// iconResId = R.drawable.ic_back_24,
|
||||
// isEnabled = true,
|
||||
// onClick = {
|
||||
// saveResult()
|
||||
// router.pop()
|
||||
// },
|
||||
// ).takeIf { route.isEditMode.not() },
|
||||
// secondaryPairButtonsUM = null,
|
||||
// ),
|
||||
// )
|
||||
}.launchIn(modelScope)
|
||||
}
|
||||
}
|
||||
|
|
@ -20,11 +20,11 @@ import com.tangem.domain.txhistory.usecase.GetFixedTxHistoryItemsUseCase
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.send.v2.send.SendRoute
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponent
|
||||
import com.tangem.features.send.v2.subcomponents.destination.analytics.EnterAddressSource
|
||||
import com.tangem.features.send.v2.subcomponents.destination.analytics.SendDestinationAnalyticEvents
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.*
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationWalletUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ internal class SendAmountPastedTriggerDismissConverter(
|
|||
|
||||
return state.copyWrapped(
|
||||
isEditState = isEditState,
|
||||
amountState = AmountPastedTriggerDismissTransformer().transform(amountState),
|
||||
amountState = AmountPastedTriggerDismissTransformer.transform(amountState),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ internal class AmountPasteDismissStateTransformer : Transformer<StakingUiState>
|
|||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
amountState = AmountPastedTriggerDismissTransformer().transform(prevState.amountState),
|
||||
amountState = AmountPastedTriggerDismissTransformer.transform(prevState.amountState),
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue