Updated on 2026-08-14
This commit is contained in:
commit
40dd71d7f2
7 changed files with 67 additions and 62 deletions
|
|
@ -3,14 +3,13 @@ package com.tangem.core.ui.components.appbar
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
|
@ -49,7 +48,11 @@ fun AppBarWithBackButton(
|
|||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(size = TangemTheme.dimens.size24)
|
||||
.clickable { onBackClick() },
|
||||
.clickable(
|
||||
indication = rememberRipple(bounded = false),
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
onClick = onBackClick,
|
||||
),
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
)
|
||||
if (!text.isNullOrBlank()) {
|
||||
|
|
|
|||
|
|
@ -213,7 +213,10 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
return when (result) {
|
||||
is SendTxResult.Success -> {
|
||||
allowPermissionsHandler.addAddressToInProgress(permissionOptions.forTokenContractAddress)
|
||||
TxState.TxSent(txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath) ?: "")
|
||||
TxState.TxSent(
|
||||
txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
|
||||
timestamp = System.currentTimeMillis(),
|
||||
)
|
||||
}
|
||||
SendTxResult.UserCancelledError -> TxState.UserCancelled
|
||||
is SendTxResult.BlockchainSdkError -> TxState.BlockchainError
|
||||
|
|
@ -370,7 +373,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
currencyToGet = currencyToGet,
|
||||
amount = amount,
|
||||
fee = fee,
|
||||
providerId = swapProvider.providerId,
|
||||
swapProvider = swapProvider,
|
||||
userWalletId = requireNotNull(getSelectedWallet()).walletId,
|
||||
)
|
||||
}
|
||||
|
|
@ -455,7 +458,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
swapData.toTokenAmount,
|
||||
currencyToGet.symbol,
|
||||
),
|
||||
txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath) ?: "",
|
||||
txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
|
||||
timestamp = System.currentTimeMillis(),
|
||||
)
|
||||
}
|
||||
SendTxResult.UserCancelledError -> TxState.UserCancelled
|
||||
|
|
@ -471,7 +475,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
currencyToGet: CryptoCurrencyStatus,
|
||||
amount: SwapAmount,
|
||||
fee: TxFee,
|
||||
providerId: String,
|
||||
swapProvider: SwapProvider,
|
||||
userWalletId: UserWalletId,
|
||||
): TxState {
|
||||
val exchangeData = repository.getExchangeData(
|
||||
|
|
@ -481,7 +485,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
toNetwork = currencyToGet.currency.network.backendId,
|
||||
fromAmount = amount.toStringWithRightOffset(),
|
||||
fromDecimals = amount.decimals,
|
||||
providerId = providerId,
|
||||
providerId = swapProvider.providerId,
|
||||
rateType = RateType.FLOAT,
|
||||
toAddress = currencyToGet.value.networkAddress?.defaultAddress ?: "",
|
||||
)
|
||||
|
|
@ -501,14 +505,17 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
network = currencyToSend.currency.network,
|
||||
)
|
||||
|
||||
return result.fold(ifLeft = {
|
||||
when (it) {
|
||||
is SendTransactionError.NetworkError -> TxState.NetworkError
|
||||
is SendTransactionError.DataError -> TxState.BlockchainError
|
||||
SendTransactionError.DemoCardError -> TxState.UnknownError
|
||||
else -> TxState.UnknownError
|
||||
}
|
||||
}, ifRight = {
|
||||
return result.fold(
|
||||
ifLeft = {
|
||||
when (it) {
|
||||
is SendTransactionError.NetworkError -> TxState.NetworkError
|
||||
is SendTransactionError.DataError -> TxState.BlockchainError
|
||||
SendTransactionError.DemoCardError -> TxState.UnknownError
|
||||
else -> TxState.UnknownError
|
||||
}
|
||||
},
|
||||
ifRight = {
|
||||
val timestamp = System.currentTimeMillis()
|
||||
TxState.TxSent(
|
||||
fromAmount = amountFormatter.formatSwapAmountToUI(
|
||||
amount,
|
||||
|
|
@ -521,9 +528,11 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
txAddress = userWalletManager.getLastTransactionHash(
|
||||
currencyToSend.currency.network.backendId,
|
||||
derivationPath,
|
||||
) ?: "",
|
||||
).orEmpty(),
|
||||
timestamp = timestamp,
|
||||
)
|
||||
},)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Deprecated("used in old swap mechanism")
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ sealed class TxState {
|
|||
val fromAmount: String? = null,
|
||||
val toAmount: String? = null,
|
||||
val txAddress: String,
|
||||
val timestamp: Long,
|
||||
) : TxState()
|
||||
|
||||
object UserCancelled : TxState()
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ package com.tangem.feature.swap.models
|
|||
|
||||
import com.tangem.core.ui.components.currency.tokenicon.TokenIconState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.feature.swap.domain.models.domain.SwapProvider
|
||||
|
||||
data class SwapSuccessStateHolder(
|
||||
val timestamp: Long,
|
||||
val txUrl: String,
|
||||
val fee: TextReference,
|
||||
val rate: TextReference,
|
||||
val selectedProvider: SwapProvider,
|
||||
val providerName: TextReference,
|
||||
val providerType: TextReference,
|
||||
val providerIcon: String,
|
||||
val fromTokenAmount: TextReference,
|
||||
val toTokenAmount: TextReference,
|
||||
val fromTokenFiatAmount: TextReference,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import com.tangem.feature.swap.domain.models.ui.*
|
|||
import com.tangem.feature.swap.models.*
|
||||
import com.tangem.feature.swap.models.states.*
|
||||
import com.tangem.feature.swap.presentation.R
|
||||
import com.tangem.feature.swap.viewmodels.SwapProcessDataState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -459,39 +458,37 @@ internal class StateBuilder(
|
|||
)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
fun createSuccessState(
|
||||
uiState: SwapStateHolder,
|
||||
txState: TxState.TxSent,
|
||||
dataState: SwapProcessDataState,
|
||||
fromAmount: BigDecimal,
|
||||
toAmount: BigDecimal,
|
||||
txUrl: String,
|
||||
onSecondaryBtnClick: () -> Unit,
|
||||
): SwapStateHolder {
|
||||
val fromToken = requireNotNull(uiState.sendCardData as? SwapCardState.SwapCardData)
|
||||
val toToken = requireNotNull(uiState.receiveCardData as? SwapCardState.SwapCardData)
|
||||
val fromTokenIconState = fromToken.token?.let(iconStateConverter::convert)
|
||||
val toTokenIconState = toToken.token?.let(iconStateConverter::convert)
|
||||
val providerState = uiState.providerState as ProviderState.Content
|
||||
val fromToken = requireNotNull((uiState.sendCardData as? SwapCardState.SwapCardData)?.token)
|
||||
val toToken = requireNotNull((uiState.receiveCardData as? SwapCardState.SwapCardData)?.token)
|
||||
val fromTokenIconState = iconStateConverter.convert(fromToken)
|
||||
val toTokenIconState = iconStateConverter.convert(toToken)
|
||||
val fee = uiState.fee as? FeeItemState.Content ?: return uiState
|
||||
val fromCryptoCurrencyStatus = requireNotNull(fromToken.token)
|
||||
val toCryptoCurrencyStatus = requireNotNull(toToken.token)
|
||||
val rate = txState.toAmount?.toBigDecimal()?.divide(
|
||||
txState.fromAmount?.toBigDecimal(),
|
||||
toCryptoCurrencyStatus.currency.decimals,
|
||||
RoundingMode.HALF_UP,
|
||||
)
|
||||
val fromCurrencySymbol = fromCryptoCurrencyStatus.currency.symbol
|
||||
val toCurrencySymbol = toCryptoCurrencyStatus.currency.symbol
|
||||
val fromFiatAmount = getFormattedFiatAmount(fromToken.value.fiatRate?.multiply(fromAmount))
|
||||
val toFiatAmount = getFormattedFiatAmount(toToken.value.fiatRate?.multiply(toAmount))
|
||||
|
||||
return uiState.copy(
|
||||
successState = SwapSuccessStateHolder(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
timestamp = txState.timestamp,
|
||||
txUrl = txUrl,
|
||||
selectedProvider = requireNotNull(dataState.selectedProvider),
|
||||
providerName = TextReference.Str(providerState.name),
|
||||
providerType = TextReference.Str(providerState.type),
|
||||
providerIcon = providerState.iconUrl,
|
||||
fee = TextReference.Str("${fee.amountCrypto} ${fee.symbolCrypto} (${fee.amountFiatFormatted})"),
|
||||
rate = TextReference.Str("1 $fromCurrencySymbol ≈ $rate $toCurrencySymbol"),
|
||||
fromTokenAmount = TextReference.Str("${txState.fromAmount.orEmpty()} ${fromToken.tokenCurrency}}"),
|
||||
toTokenAmount = TextReference.Str("${txState.toAmount.orEmpty()} ${toToken.tokenCurrency}}"),
|
||||
fromTokenFiatAmount = TextReference.Str(fromToken.amountEquivalent.orEmpty()),
|
||||
toTokenFiatAmount = TextReference.Str(toToken.amountEquivalent.orEmpty()),
|
||||
rate = TextReference.Str(providerState.rate),
|
||||
fromTokenAmount = TextReference.Str(txState.fromAmount.orEmpty()),
|
||||
toTokenAmount = TextReference.Str(txState.toAmount.orEmpty()),
|
||||
fromTokenFiatAmount = TextReference.Str(fromFiatAmount),
|
||||
toTokenFiatAmount = TextReference.Str(toFiatAmount),
|
||||
fromTokenIconState = fromTokenIconState,
|
||||
toTokenIconState = toTokenIconState,
|
||||
onSecondaryButtonClick = onSecondaryBtnClick,
|
||||
|
|
@ -892,7 +889,7 @@ internal class StateBuilder(
|
|||
return BigDecimalFormatter.formatFiatAmount(fiatAmount, appCurrency.code, appCurrency.symbol)
|
||||
}
|
||||
|
||||
private fun getFormattedFiatAmount(amount: BigDecimal): String {
|
||||
private fun getFormattedFiatAmount(amount: BigDecimal?): String {
|
||||
val appCurrency = appCurrencyProvider()
|
||||
|
||||
return BigDecimalFormatter.formatFiatAmount(amount, appCurrency.code, appCurrency.symbol)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.shareText
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeProviderType
|
||||
import com.tangem.feature.swap.domain.models.domain.SwapProvider
|
||||
import com.tangem.feature.swap.models.SwapSuccessStateHolder
|
||||
import com.tangem.feature.swap.presentation.R
|
||||
|
||||
|
|
@ -60,7 +59,7 @@ private fun SwapSuccessScreenContent(state: SwapSuccessStateHolder, padding: Pad
|
|||
.background(TangemTheme.colors.background.secondary)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
TransactionDoneTitle(titleRes = R.string.swapping_success_view_title, date = 0L)
|
||||
TransactionDoneTitle(titleRes = R.string.swapping_success_view_title, date = state.timestamp)
|
||||
SpacerH16()
|
||||
InputRowImage(
|
||||
title = TextReference.Res(R.string.swapping_success_from_title),
|
||||
|
|
@ -83,9 +82,9 @@ private fun SwapSuccessScreenContent(state: SwapSuccessStateHolder, padding: Pad
|
|||
)
|
||||
SpacerH16()
|
||||
InputRowBestRate(
|
||||
imageUrl = state.selectedProvider.imageLarge,
|
||||
title = TextReference.Str(state.selectedProvider.name),
|
||||
titleExtra = TextReference.Str(state.selectedProvider.type.name),
|
||||
imageUrl = state.providerIcon,
|
||||
title = state.providerName,
|
||||
titleExtra = state.providerType,
|
||||
subtitle = state.rate,
|
||||
modifier = Modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
|
|
@ -153,13 +152,9 @@ private val state = SwapSuccessStateHolder(
|
|||
timestamp = 0L,
|
||||
txUrl = "https://www.google.com/#q=nam",
|
||||
fee = TextReference.Str("1 000 DAI ~ 1 000 MATIC"),
|
||||
selectedProvider = SwapProvider(
|
||||
providerId = "1inch",
|
||||
rateTypes = listOf(),
|
||||
name = "1inch",
|
||||
type = ExchangeProviderType.DEX,
|
||||
imageLarge = "",
|
||||
),
|
||||
providerName = TextReference.Str("1inch"),
|
||||
providerType = TextReference.Str(ExchangeProviderType.DEX.name),
|
||||
providerIcon = "",
|
||||
fromTokenAmount = TextReference.Str("1 000 DAI"),
|
||||
toTokenAmount = TextReference.Str("1 000 MATIC"),
|
||||
fromTokenFiatAmount = TextReference.Str("1 000 $"),
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ import com.tangem.feature.swap.presentation.SwapFragment
|
|||
import com.tangem.feature.swap.router.SwapNavScreen
|
||||
import com.tangem.feature.swap.router.SwapRouter
|
||||
import com.tangem.feature.swap.ui.StateBuilder
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.Debouncer
|
||||
import com.tangem.utils.coroutines.runCatching
|
||||
import com.tangem.utils.coroutines.*
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -401,7 +399,8 @@ internal class SwapViewModel @Inject constructor(
|
|||
uiState = stateBuilder.createSuccessState(
|
||||
uiState = uiState,
|
||||
txState = it,
|
||||
dataState = dataState,
|
||||
fromAmount = dataState.amount?.toBigDecimal() ?: BigDecimal.ZERO,
|
||||
toAmount = dataState.swapDataModel?.toTokenAmount?.value ?: BigDecimal.ZERO,
|
||||
txUrl = url,
|
||||
onSecondaryBtnClick = {
|
||||
val txHash = it.txAddress
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue