Updated on 2026-08-14
This commit is contained in:
commit
ca49abf2b1
892 changed files with 17979 additions and 6555 deletions
|
|
@ -14,7 +14,11 @@ dependencies {
|
|||
implementation(projects.core.ui)
|
||||
|
||||
/** Domain models */
|
||||
api(projects.domain.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.nft.models)
|
||||
|
||||
/* Compose */
|
||||
implementation(deps.compose.runtime)
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ package com.tangem.features.send.v2.api
|
|||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
interface SendComponent : ComposableContentComponent {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.features.send.v2.api.deeplink
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
interface SellDeepLinkHandler {
|
||||
|
||||
interface Factory {
|
||||
fun create(coroutineScope: CoroutineScope, queryParams: Map<String, String>): SellDeepLinkHandler
|
||||
}
|
||||
}
|
||||
|
|
@ -57,6 +57,7 @@ dependencies {
|
|||
implementation(projects.domain.balanceHiding.models)
|
||||
implementation(projects.domain.balanceHiding)
|
||||
implementation(projects.domain.nft.models)
|
||||
implementation(projects.domain.nft)
|
||||
implementation(projects.domain.notifications)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
package com.tangem.features.send.v2.common
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.nft.RefreshAllNFTUseCase
|
||||
import com.tangem.domain.tokens.FetchPendingTransactionsUseCase
|
||||
import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -22,6 +23,7 @@ internal class SendBalanceUpdater @AssistedInject constructor(
|
|||
private val getTxHistoryItemsUseCase: GetTxHistoryItemsUseCase,
|
||||
private val txHistoryFeatureToggles: TxHistoryFeatureToggles,
|
||||
private val txHistoryContentUpdateEmitter: TxHistoryContentUpdateEmitter,
|
||||
private val refreshAllNFTUseCase: RefreshAllNFTUseCase,
|
||||
@DelayedWork private val coroutineScope: CoroutineScope,
|
||||
@Assisted private val userWallet: UserWallet,
|
||||
@Assisted private val cryptoCurrency: CryptoCurrency,
|
||||
|
|
@ -33,7 +35,7 @@ internal class SendBalanceUpdater @AssistedInject constructor(
|
|||
async {
|
||||
fetchPendingTransactionsUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
networks = setOf(cryptoCurrency.network),
|
||||
network = cryptoCurrency.network,
|
||||
)
|
||||
},
|
||||
// we should update tx history and network for new balances
|
||||
|
|
@ -43,16 +45,25 @@ internal class SendBalanceUpdater @AssistedInject constructor(
|
|||
async {
|
||||
updateNetworkStatuses()
|
||||
},
|
||||
async {
|
||||
updateNFT()
|
||||
},
|
||||
).awaitAll()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateNFT() {
|
||||
delay(BALANCE_UPDATE_DELAY)
|
||||
refreshAllNFTUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun updateNetworkStatuses(delay: Long = BALANCE_UPDATE_DELAY) {
|
||||
updateDelayedNetworkStatusUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
network = cryptoCurrency.network,
|
||||
delayMillis = delay,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package com.tangem.features.send.v2.common.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.Keyboard
|
||||
import com.tangem.core.ui.components.keyboardAsState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveAnnotatedReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun SendingText(footerText: TextReference, modifier: Modifier = Modifier) {
|
||||
var isVisibleProxy by remember { mutableStateOf(footerText != TextReference.EMPTY) }
|
||||
val keyboard by keyboardAsState()
|
||||
|
||||
// the text should appear when the keyboard is closed
|
||||
LaunchedEffect(footerText != TextReference.EMPTY, keyboard) {
|
||||
if (footerText != TextReference.EMPTY && keyboard is Keyboard.Opened) {
|
||||
return@LaunchedEffect
|
||||
}
|
||||
isVisibleProxy = footerText != TextReference.EMPTY
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = isVisibleProxy,
|
||||
modifier = modifier,
|
||||
enter = slideInVertically(initialOffsetY = { it / 2 }) + fadeIn(),
|
||||
exit = fadeOut(tween(durationMillis = 300)),
|
||||
label = "Animate show sending state text",
|
||||
) {
|
||||
Text(
|
||||
text = footerText.resolveAnnotatedReference(),
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ internal sealed class ConfirmUM {
|
|||
|
||||
data class Content(
|
||||
override val isPrimaryButtonEnabled: Boolean = false,
|
||||
val walletName: TextReference,
|
||||
val isSending: Boolean,
|
||||
val showTapHelp: Boolean,
|
||||
val sendingFooter: TextReference,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
package com.tangem.features.send.v2.common.utils
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fee
|
||||
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.features.send.v2.impl.R
|
||||
import com.tangem.utils.StringsSigns.COMA_SIGN
|
||||
|
||||
internal fun getTronTokenFeeSendingText(fee: Fee.Tron, fiatFee: String, fiatSending: TextReference): TextReference {
|
||||
val suffix = when {
|
||||
fee.remainingEnergy == 0L -> {
|
||||
resourceReference(
|
||||
R.string.send_summary_transaction_description_suffix_including,
|
||||
wrappedList(fiatFee),
|
||||
)
|
||||
}
|
||||
fee.feeEnergy <= fee.remainingEnergy -> {
|
||||
resourceReference(
|
||||
R.string.send_summary_transaction_description_suffix_fee_covered,
|
||||
wrappedList(fee.feeEnergy),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
resourceReference(
|
||||
R.string.send_summary_transaction_description_suffix_fee_reduced,
|
||||
wrappedList(fee.remainingEnergy),
|
||||
)
|
||||
}
|
||||
}
|
||||
val prefix = resourceReference(
|
||||
R.string.send_summary_transaction_description_prefix,
|
||||
wrappedList(fiatSending),
|
||||
)
|
||||
|
||||
return combinedReference(prefix, stringReference("$COMA_SIGN "), suffix)
|
||||
}
|
||||
|
||||
internal fun formatFooterFiatFee(
|
||||
amount: Amount?,
|
||||
isFeeConvertibleToFiat: Boolean,
|
||||
isFeeApproximate: Boolean,
|
||||
appCurrency: AppCurrency,
|
||||
): String {
|
||||
return if (isFeeConvertibleToFiat) {
|
||||
amount?.value.format {
|
||||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
amount?.value.format {
|
||||
crypto(
|
||||
decimals = amount?.decimals ?: 0,
|
||||
symbol = amount?.currencySymbol.orEmpty(),
|
||||
).fee(
|
||||
canBeLower = isFeeApproximate,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.tangem.features.send.v2.deeplink
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.features.send.v2.api.deeplink.SellDeepLinkHandler
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("ComplexCondition")
|
||||
internal class DefaultSellDeepLinkHandler @AssistedInject constructor(
|
||||
@Assisted scope: CoroutineScope,
|
||||
@Assisted queryParams: Map<String, String>,
|
||||
appRouter: AppRouter,
|
||||
getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
getCryptoCurrencyUseCase: GetCryptoCurrencyUseCase,
|
||||
) : SellDeepLinkHandler {
|
||||
|
||||
init {
|
||||
val currencyId = queryParams[CURRENCY_ID_KEY]
|
||||
val transactionId = queryParams[TRANSACTION_ID_KEY]
|
||||
val amount = queryParams[AMOUNT_KEY]
|
||||
val destinationAddress = queryParams[DESTINATION_ADDRESS_KEY]
|
||||
val memo = queryParams[MEMO_KEY]
|
||||
|
||||
// It is okay here, we are navigating from outside, and there is no other way to getting UserWallet
|
||||
getSelectedWalletSyncUseCase()
|
||||
.fold(
|
||||
ifLeft = {
|
||||
Timber.e("Error on getting user wallet: $it")
|
||||
},
|
||||
ifRight = { userWallet ->
|
||||
if (currencyId.isNullOrEmpty() || transactionId.isNullOrEmpty() ||
|
||||
amount.isNullOrEmpty() || destinationAddress.isNullOrEmpty()
|
||||
) {
|
||||
Timber.e(
|
||||
"""
|
||||
Invalid parameters for SELL deeplink
|
||||
|- Params: $queryParams
|
||||
""".trimIndent(),
|
||||
)
|
||||
return@fold
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
val cryptoCurrency = getCryptoCurrencyUseCase(userWallet, currencyId).getOrElse {
|
||||
Timber.e("Error on getting cryptoCurrency: $it")
|
||||
return@launch
|
||||
}
|
||||
|
||||
appRouter.push(
|
||||
AppRoute.Send(
|
||||
currency = cryptoCurrency,
|
||||
userWalletId = userWallet.walletId,
|
||||
transactionId = transactionId,
|
||||
destinationAddress = destinationAddress,
|
||||
amount = amount,
|
||||
tag = memo,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : SellDeepLinkHandler.Factory {
|
||||
override fun create(
|
||||
coroutineScope: CoroutineScope,
|
||||
queryParams: Map<String, String>,
|
||||
): DefaultSellDeepLinkHandler
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TRANSACTION_ID_KEY = "transactionId"
|
||||
const val CURRENCY_ID_KEY = "currency_id"
|
||||
const val AMOUNT_KEY = "baseCurrencyAmount"
|
||||
const val DESTINATION_ADDRESS_KEY = "depositWalletAddress"
|
||||
const val MEMO_KEY = "depositWalletAddressTag"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.features.send.v2.deeplink.di
|
||||
|
||||
import com.tangem.features.send.v2.api.deeplink.SellDeepLinkHandler
|
||||
import com.tangem.features.send.v2.deeplink.DefaultSellDeepLinkHandler
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface SendDeepLinkModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindFactory(impl: DefaultSellDeepLinkHandler.Factory): SellDeepLinkHandler.Factory
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
|
|||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.send.v2.send.ui.state.SendUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationTextFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
|
|
|
|||
|
|
@ -15,17 +15,18 @@ import com.tangem.core.decompose.navigation.Router
|
|||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase
|
||||
import com.tangem.domain.settings.NeverShowTapHelpUseCase
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.IsAmountSubtractAvailableUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.transaction.usecase.CreateTransferTransactionUseCase
|
||||
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
|
|
@ -255,7 +256,7 @@ internal class SendConfirmModel @Inject constructor(
|
|||
saveBlockchainErrorUseCase(
|
||||
error = BlockchainErrorInfo(
|
||||
errorMessage = errorMessage,
|
||||
blockchainId = cryptoCurrency.network.id.value,
|
||||
blockchainId = cryptoCurrency.network.rawId,
|
||||
derivationPath = cryptoCurrency.network.derivationPath.value,
|
||||
destinationAddress = confirmData.enteredDestination.orEmpty(),
|
||||
tokenSymbol = if (amount?.type is AmountType.Token) {
|
||||
|
|
@ -286,6 +287,7 @@ internal class SendConfirmModel @Inject constructor(
|
|||
it.copy(
|
||||
confirmUM = SendConfirmInitialStateTransformer(
|
||||
isShowTapHelp = isShowTapHelp,
|
||||
walletName = stringReference(userWallet.name),
|
||||
).transform(uiState.value.confirmUM),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
|
||||
internal class SendConfirmInitialStateTransformer(
|
||||
private val isShowTapHelp: Boolean,
|
||||
private val walletName: TextReference,
|
||||
) : Transformer<ConfirmUM> {
|
||||
override fun transform(prevState: ConfirmUM): ConfirmUM {
|
||||
return ConfirmUM.Content(
|
||||
walletName = walletName,
|
||||
isSending = false,
|
||||
showTapHelp = isShowTapHelp,
|
||||
sendingFooter = TextReference.EMPTY,
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
package com.tangem.features.send.v2.send.confirm.model.transformers
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fee
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
import com.tangem.features.send.v2.common.utils.formatFooterFiatFee
|
||||
import com.tangem.features.send.v2.common.utils.getTronTokenFeeSendingText
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkIfFeeTooHigh
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeSelectorUM
|
||||
|
|
@ -92,17 +94,18 @@ internal class SendConfirmationNotificationsTransformer(
|
|||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
}
|
||||
val fiatFee = formatFiatFee(
|
||||
val fiatFee = formatFooterFiatFee(
|
||||
amount = fee.amount,
|
||||
isFeeConvertibleToFiat = feeUM.isFeeConvertibleToFiat,
|
||||
isFeeApproximate = feeUM.isFeeApproximate,
|
||||
appCurrency = appCurrency,
|
||||
)
|
||||
|
||||
return if (feeUM.isTronToken && fee is Fee.Tron) {
|
||||
getTokenFeeSendingText(
|
||||
getTronTokenFeeSendingText(
|
||||
fee = fee,
|
||||
fiatFee = fiatFee,
|
||||
fiatSending = fiatSending,
|
||||
fiatSending = stringReference(fiatSending),
|
||||
)
|
||||
} else {
|
||||
resourceReference(
|
||||
|
|
@ -115,57 +118,4 @@ internal class SendConfirmationNotificationsTransformer(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatFiatFee(amount: Amount?, isFeeConvertibleToFiat: Boolean, isFeeApproximate: Boolean): String {
|
||||
return if (isFeeConvertibleToFiat) {
|
||||
amount?.value.format {
|
||||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
amount?.value.format {
|
||||
crypto(
|
||||
decimals = amount?.decimals ?: 0,
|
||||
symbol = amount?.currencySymbol.orEmpty(),
|
||||
).fee(
|
||||
canBeLower = isFeeApproximate,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTokenFeeSendingText(fee: Fee.Tron, fiatFee: String, fiatSending: String): TextReference {
|
||||
val suffix = when {
|
||||
fee.remainingEnergy == 0L -> {
|
||||
resourceReference(
|
||||
R.string.send_summary_transaction_description_suffix_including,
|
||||
wrappedList(fiatFee),
|
||||
)
|
||||
}
|
||||
fee.feeEnergy <= fee.remainingEnergy -> {
|
||||
resourceReference(
|
||||
R.string.send_summary_transaction_description_suffix_fee_covered,
|
||||
wrappedList(fee.feeEnergy),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
resourceReference(
|
||||
R.string.send_summary_transaction_description_suffix_fee_reduced,
|
||||
wrappedList(fee.remainingEnergy),
|
||||
)
|
||||
}
|
||||
}
|
||||
val prefix = resourceReference(
|
||||
R.string.send_summary_transaction_description_prefix,
|
||||
wrappedList(fiatSending),
|
||||
)
|
||||
|
||||
return combinedReference(prefix, COMMA_SEPARATOR, suffix)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val COMMA_SEPARATOR = stringReference(", ")
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +1,24 @@
|
|||
package com.tangem.features.send.v2.send.confirm.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.ui.components.Keyboard
|
||||
import com.tangem.core.ui.components.SpacerHMax
|
||||
import com.tangem.core.ui.components.keyboardAsState
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveAnnotatedReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||
import com.tangem.core.ui.utils.toTimeFormat
|
||||
import com.tangem.features.send.v2.common.ui.SendingText
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
import com.tangem.features.send.v2.common.ui.tapHelp
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
|
|
@ -82,38 +73,6 @@ internal fun SendConfirmContent(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SendingText(footerText: TextReference, modifier: Modifier = Modifier) {
|
||||
var isVisibleProxy by remember { mutableStateOf(footerText != TextReference.EMPTY) }
|
||||
val keyboard by keyboardAsState()
|
||||
|
||||
// the text should appear when the keyboard is closed
|
||||
LaunchedEffect(footerText != TextReference.EMPTY, keyboard) {
|
||||
if (footerText != TextReference.EMPTY && keyboard is Keyboard.Opened) {
|
||||
return@LaunchedEffect
|
||||
}
|
||||
isVisibleProxy = footerText != TextReference.EMPTY
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = isVisibleProxy,
|
||||
modifier = modifier,
|
||||
enter = slideInVertically() + fadeIn(),
|
||||
exit = fadeOut(tween(durationMillis = 300)),
|
||||
label = "Animate show sending state text",
|
||||
) {
|
||||
Text(
|
||||
text = footerText.resolveAnnotatedReference(),
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.blocks(
|
||||
uiState: SendUM,
|
||||
destinationBlockComponent: SendDestinationBlockComponent,
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
|
|||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
|
|
@ -73,8 +72,7 @@ internal class SendModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
|
|
@ -275,13 +273,13 @@ internal class SendModel @Inject constructor(
|
|||
isMultiCurrency: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return if (isMultiCurrency) {
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = isSingleWalletWithToken,
|
||||
)
|
||||
} else {
|
||||
getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWalletId)
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +333,7 @@ internal class SendModel @Inject constructor(
|
|||
saveBlockchainErrorUseCase(
|
||||
error = BlockchainErrorInfo(
|
||||
errorMessage = errorMessage.orEmpty(),
|
||||
blockchainId = cryptoCurrency.network.id.value,
|
||||
blockchainId = cryptoCurrency.network.rawId,
|
||||
derivationPath = cryptoCurrency.network.derivationPath.value,
|
||||
destinationAddress = "",
|
||||
tokenSymbol = "",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
|
|||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.send.v2.sendnft.ui.state.NFTSendUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationTextFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.core.decompose.navigation.Router
|
|||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.datasource.local.nft.converter.NFTSdkAssetConverter
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.settings.NeverShowTapHelpUseCase
|
|||
import com.tangem.domain.transaction.usecase.CreateNFTTransferTransactionUseCase
|
||||
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.features.nft.entity.NFTSendSuccessTrigger
|
||||
import com.tangem.features.send.v2.common.CommonSendRoute
|
||||
import com.tangem.features.send.v2.common.SendBalanceUpdater
|
||||
import com.tangem.features.send.v2.common.SendConfirmAlertFactory
|
||||
|
|
@ -78,6 +79,7 @@ internal class NFTSendConfirmModel @Inject constructor(
|
|||
private val shareManager: ShareManager,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val nftSendAnalyticHelper: NFTSendAnalyticHelper,
|
||||
private val nftSendSuccessTrigger: NFTSendSuccessTrigger,
|
||||
sendBalanceUpdaterFactory: SendBalanceUpdater.Factory,
|
||||
) : Model(), NFTSendConfirmClickIntents {
|
||||
|
||||
|
|
@ -201,7 +203,7 @@ internal class NFTSendConfirmModel @Inject constructor(
|
|||
saveBlockchainErrorUseCase(
|
||||
error = BlockchainErrorInfo(
|
||||
errorMessage = errorMessage,
|
||||
blockchainId = cryptoCurrency.network.id.value,
|
||||
blockchainId = cryptoCurrency.network.rawId,
|
||||
derivationPath = cryptoCurrency.network.derivationPath.value,
|
||||
destinationAddress = confirmData.enteredDestination.orEmpty(),
|
||||
tokenSymbol = null,
|
||||
|
|
@ -228,6 +230,7 @@ internal class NFTSendConfirmModel @Inject constructor(
|
|||
it.copy(
|
||||
confirmUM = NFTSendConfirmInitialStateTransformer(
|
||||
isShowTapHelp = isShowTapHelp,
|
||||
walletName = stringReference(userWallet.name),
|
||||
).transform(uiState.value.confirmUM),
|
||||
)
|
||||
}
|
||||
|
|
@ -357,6 +360,7 @@ internal class NFTSendConfirmModel @Inject constructor(
|
|||
analyticsEventHandler = analyticsEventHandler,
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency,
|
||||
analyticsCategoryName = analyticsCategoryName,
|
||||
appCurrency = params.appCurrency,
|
||||
).transform(uiState.value.confirmUM),
|
||||
)
|
||||
}
|
||||
|
|
@ -369,15 +373,13 @@ internal class NFTSendConfirmModel @Inject constructor(
|
|||
transform = { state, route -> state to route },
|
||||
).onEach { (state, _) ->
|
||||
val confirmUM = state.confirmUM
|
||||
val isReadyToSend = confirmUM is ConfirmUM.Content && !confirmUM.isSending
|
||||
val confirmUMContent = confirmUM as? ConfirmUM.Content
|
||||
val isReadyToSend = confirmUMContent != null && !confirmUM.isSending
|
||||
params.callback.onResult(
|
||||
state.copy(
|
||||
navigationUM = NavigationUM.Content(
|
||||
title = resourceReference(
|
||||
id = R.string.send_summary_title,
|
||||
formatArgs = wrappedList(params.cryptoCurrencyStatus.currency.name),
|
||||
),
|
||||
subtitle = null,
|
||||
title = resourceReference(R.string.nft_send),
|
||||
subtitle = confirmUMContent?.walletName,
|
||||
backIconRes = R.drawable.ic_close_24,
|
||||
backIconClick = {
|
||||
analyticsEventHandler.send(
|
||||
|
|
@ -404,15 +406,7 @@ internal class NFTSendConfirmModel @Inject constructor(
|
|||
isEnabled = confirmUM.isPrimaryButtonEnabled,
|
||||
isHapticClick = isReadyToSend,
|
||||
onClick = {
|
||||
when (confirmUM) {
|
||||
is ConfirmUM.Success -> appRouter.pop()
|
||||
is ConfirmUM.Content -> if (confirmUM.isSending) {
|
||||
return@PrimaryButtonUM
|
||||
} else {
|
||||
onSendClick()
|
||||
}
|
||||
else -> return@PrimaryButtonUM
|
||||
}
|
||||
onNextClick(confirmUM)
|
||||
},
|
||||
),
|
||||
prevButton = null,
|
||||
|
|
@ -430,6 +424,23 @@ internal class NFTSendConfirmModel @Inject constructor(
|
|||
}.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun onNextClick(confirmUM: ConfirmUM) {
|
||||
when (confirmUM) {
|
||||
is ConfirmUM.Success -> {
|
||||
modelScope.launch {
|
||||
nftSendSuccessTrigger.triggerSuccessNFTSend()
|
||||
}
|
||||
appRouter.pop()
|
||||
}
|
||||
is ConfirmUM.Content -> if (confirmUM.isSending) {
|
||||
return
|
||||
} else {
|
||||
onSendClick()
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val CHECK_FEE_UPDATE_DELAY = 10_000L
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
|
||||
internal class NFTSendConfirmInitialStateTransformer(
|
||||
private val isShowTapHelp: Boolean,
|
||||
private val walletName: TextReference,
|
||||
) : Transformer<ConfirmUM> {
|
||||
override fun transform(prevState: ConfirmUM): ConfirmUM {
|
||||
return ConfirmUM.Content(
|
||||
isSending = false,
|
||||
showTapHelp = isShowTapHelp,
|
||||
sendingFooter = TextReference.EMPTY,
|
||||
walletName = walletName,
|
||||
notifications = persistentListOf(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
package com.tangem.features.send.v2.sendnft.confirm.model.transformers
|
||||
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
import com.tangem.features.send.v2.common.utils.formatFooterFiatFee
|
||||
import com.tangem.features.send.v2.common.utils.getTronTokenFeeSendingText
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkIfFeeTooHigh
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeSelectorUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeType
|
||||
|
|
@ -19,11 +27,13 @@ internal class NFTSendConfirmationNotificationsTransformer(
|
|||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val cryptoCurrency: CryptoCurrency,
|
||||
private val analyticsCategoryName: String,
|
||||
private val appCurrency: AppCurrency,
|
||||
) : Transformer<ConfirmUM> {
|
||||
override fun transform(prevState: ConfirmUM): ConfirmUM {
|
||||
val state = prevState as? ConfirmUM.Content ?: return prevState
|
||||
val feeUM = feeUM as? FeeUM.Content ?: return prevState
|
||||
return state.copy(
|
||||
sendingFooter = getSendingFooterText(),
|
||||
notifications = buildList {
|
||||
addTooHighNotification(feeUM.feeSelectorUM)
|
||||
addTooLowNotification(feeUM)
|
||||
|
|
@ -48,6 +58,38 @@ internal class NFTSendConfirmationNotificationsTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getSendingFooterText(): TextReference {
|
||||
val feeUM = feeUM as? FeeUM.Content
|
||||
val fee = (feeUM?.feeSelectorUM as? FeeSelectorUM.Content)?.selectedFee ?: return TextReference.EMPTY
|
||||
|
||||
val fiatFee = formatFooterFiatFee(
|
||||
amount = fee.amount,
|
||||
isFeeConvertibleToFiat = feeUM.isFeeConvertibleToFiat,
|
||||
isFeeApproximate = feeUM.isFeeApproximate,
|
||||
appCurrency = appCurrency,
|
||||
)
|
||||
|
||||
return if (feeUM.isTronToken && fee is Fee.Tron) {
|
||||
getTronTokenFeeSendingText(
|
||||
fee = fee,
|
||||
fiatFee = fiatFee,
|
||||
fiatSending = resourceReference(R.string.common_nft),
|
||||
)
|
||||
} else {
|
||||
resourceReference(
|
||||
id = if (feeUM.isFeeConvertibleToFiat) {
|
||||
R.string.send_summary_transaction_description
|
||||
} else {
|
||||
R.string.send_summary_transaction_description_no_fiat_fee
|
||||
},
|
||||
formatArgs = wrappedList(
|
||||
resourceReference(R.string.common_nft),
|
||||
fiatFee,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<NotificationUM>.addTooHighNotification(feeSelectorUM: FeeSelectorUM) {
|
||||
if (feeSelectorUM !is FeeSelectorUM.Content) return
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,16 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.ui.components.SpacerHMax
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||
import com.tangem.core.ui.utils.toTimeFormat
|
||||
import com.tangem.features.nft.component.NFTDetailsBlockComponent
|
||||
import com.tangem.features.send.v2.common.ui.SendingText
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
import com.tangem.features.send.v2.common.ui.tapHelp
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
|
|
@ -66,6 +69,8 @@ internal fun NFTSendConfirmContent(
|
|||
)
|
||||
}
|
||||
}
|
||||
SpacerHMax()
|
||||
SendingText(footerText = confirmUM?.sendingFooter ?: TextReference.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
|||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.domain.transaction.usecase.CreateNFTTransferTransactionUseCase
|
||||
|
|
@ -60,7 +60,7 @@ internal class NFTSendModel @Inject constructor(
|
|||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val createNFTTransferTransactionUseCase: CreateNFTTransferTransactionUseCase,
|
||||
private val getFeeUseCase: GetFeeUseCase,
|
||||
|
|
@ -166,7 +166,7 @@ internal class NFTSendModel @Inject constructor(
|
|||
saveBlockchainErrorUseCase(
|
||||
error = BlockchainErrorInfo(
|
||||
errorMessage = errorMessage.orEmpty(),
|
||||
blockchainId = cryptoCurrency.network.id.value,
|
||||
blockchainId = cryptoCurrency.network.rawId,
|
||||
derivationPath = cryptoCurrency.network.derivationPath.value,
|
||||
destinationAddress = "",
|
||||
tokenSymbol = null,
|
||||
|
|
@ -183,7 +183,7 @@ internal class NFTSendModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun getCurrenciesStatusUpdates(isSingleWalletWithToken: Boolean) {
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = isSingleWalletWithToken,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.features.send.v2.sendnft.ui.state
|
||||
|
||||
import com.tangem.features.send.v2.common.ui.state.NavigationUM
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
import com.tangem.features.send.v2.common.ui.state.NavigationUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeUM
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.features.send.v2.subcomponents.destination
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.send.v2.common.CommonSendRoute
|
||||
import com.tangem.features.send.v2.common.PredefinedValues
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ 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.extensions.resourceReference
|
||||
import com.tangem.domain.models.network.CryptoCurrencyAddress
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyUseCase
|
||||
import com.tangem.domain.tokens.GetNetworkAddressesUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
|
||||
import com.tangem.domain.transaction.usecase.IsUtxoConsolidationAvailableUseCase
|
||||
import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase
|
||||
import com.tangem.domain.transaction.usecase.ValidateWalletMemoUseCase
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ import com.tangem.core.ui.format.bigdecimal.format
|
|||
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||
import com.tangem.core.ui.utils.toDateFormatWithTodayYesterday
|
||||
import com.tangem.core.ui.utils.toTimeFormat
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationRecipientListUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.RECENT_DEFAULT_COUNT
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.RECENT_KEY_TAG
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.emptyListState
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationRecipientListUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.isZero
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -23,21 +23,21 @@ import kotlinx.collections.immutable.toPersistentList
|
|||
|
||||
internal class SendRecipientHistoryListConverter(
|
||||
private val cryptoCurrency: CryptoCurrency,
|
||||
) : Converter<List<TxHistoryItem>, ImmutableList<DestinationRecipientListUM>> {
|
||||
) : Converter<List<TxInfo>, ImmutableList<DestinationRecipientListUM>> {
|
||||
|
||||
override fun convert(value: List<TxHistoryItem>): ImmutableList<DestinationRecipientListUM> {
|
||||
override fun convert(value: List<TxInfo>): ImmutableList<DestinationRecipientListUM> {
|
||||
return value.filterRecipients(cryptoCurrency).ifEmpty {
|
||||
emptyListState(RECENT_KEY_TAG, RECENT_DEFAULT_COUNT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<TxHistoryItem>.filterRecipients(cryptoCurrency: CryptoCurrency) = this.filter { item ->
|
||||
val isTransfer = item.type == TxHistoryItem.TransactionType.Transfer
|
||||
val isNotContract = item.interactionAddressType is TxHistoryItem.InteractionAddressType.User
|
||||
private fun List<TxInfo>.filterRecipients(cryptoCurrency: CryptoCurrency) = this.filter { item ->
|
||||
val isTransfer = item.type == TxInfo.TransactionType.Transfer
|
||||
val isNotContract = item.interactionAddressType is TxInfo.InteractionAddressType.User
|
||||
val isSingleAddress = if (item.isOutgoing) {
|
||||
item.destinationType is TxHistoryItem.DestinationType.Single
|
||||
item.destinationType is TxInfo.DestinationType.Single
|
||||
} else {
|
||||
item.sourceType is TxHistoryItem.SourceType.Single
|
||||
item.sourceType is TxInfo.SourceType.Single
|
||||
}
|
||||
val notZero = !item.amount.isZero()
|
||||
isTransfer && isSingleAddress && isNotContract && item.isOutgoing && notZero
|
||||
|
|
@ -54,31 +54,31 @@ internal class SendRecipientHistoryListConverter(
|
|||
)
|
||||
}.toPersistentList()
|
||||
|
||||
private fun TxHistoryItem.extractAddress(): TextReference = if (isOutgoing) {
|
||||
private fun TxInfo.extractAddress(): TextReference = if (isOutgoing) {
|
||||
when (val destination = destinationType) {
|
||||
is TxHistoryItem.DestinationType.Multiple -> resourceReference(
|
||||
is TxInfo.DestinationType.Multiple -> resourceReference(
|
||||
R.string.transaction_history_multiple_addresses,
|
||||
)
|
||||
is TxHistoryItem.DestinationType.Single -> stringReference(destination.addressType.address)
|
||||
is TxInfo.DestinationType.Single -> stringReference(destination.addressType.address)
|
||||
}
|
||||
} else {
|
||||
when (val source = sourceType) {
|
||||
is TxHistoryItem.SourceType.Multiple -> resourceReference(R.string.transaction_history_multiple_addresses)
|
||||
is TxHistoryItem.SourceType.Single -> stringReference(source.address)
|
||||
is TxInfo.SourceType.Multiple -> resourceReference(R.string.transaction_history_multiple_addresses)
|
||||
is TxInfo.SourceType.Single -> stringReference(source.address)
|
||||
}
|
||||
}
|
||||
|
||||
private fun TxHistoryItem.extractIconRes() = if (isOutgoing) {
|
||||
private fun TxInfo.extractIconRes() = if (isOutgoing) {
|
||||
R.drawable.ic_arrow_up_24
|
||||
} else {
|
||||
R.drawable.ic_arrow_down_24
|
||||
}
|
||||
|
||||
private fun TxHistoryItem.getAmount(cryptoCurrency: CryptoCurrency): String {
|
||||
private fun TxInfo.getAmount(cryptoCurrency: CryptoCurrency): String {
|
||||
return amount.format { crypto(cryptoCurrency) }
|
||||
}
|
||||
|
||||
private fun TxHistoryItem.extractTimestamp(): TextReference {
|
||||
private fun TxInfo.extractTimestamp(): TextReference {
|
||||
val date = timestampInMillis.toDateFormatWithTodayYesterday(
|
||||
formatter = DateTimeFormatters.dateDDMMYYYY,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.features.send.v2.subcomponents.destination.model.converters
|
||||
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationRecipientListUM
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.WALLET_DEFAULT_COUNT
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.WALLET_KEY_TAG
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.emptyListState
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationRecipientListUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationWalletUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationTextFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.features.send.v2.subcomponents.destination.model.transformers
|
||||
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.converters.SendRecipientHistoryListConverter
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.converters.SendRecipientWalletListConverter
|
||||
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.transformer.Transformer
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ internal class SendDestinationRecentListTransformer(
|
|||
private val cryptoCurrency: CryptoCurrency,
|
||||
private val isUtxoConsolidationAvailable: Boolean,
|
||||
private val destinationWalletList: List<DestinationWalletUM>,
|
||||
private val txHistoryList: List<TxHistoryItem>,
|
||||
private val txHistoryList: List<TxInfo>,
|
||||
) : Transformer<DestinationUM> {
|
||||
override fun transform(prevState: DestinationUM): DestinationUM {
|
||||
val state = prevState as? DestinationUM.Content ?: return prevState
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.features.send.v2.subcomponents.destination.ui.state
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.features.send.v2.subcomponents.destination.ui.state
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ internal class BitcoinCustomFeeConverter(
|
|||
) : CustomFeeConverter<Fee.Bitcoin> {
|
||||
|
||||
private val currencyStatus = feeCryptoCurrencyStatus.value
|
||||
private val network = feeCryptoCurrencyStatus.currency.network.id.value
|
||||
private val network = feeCryptoCurrencyStatus.currency.network.rawId
|
||||
|
||||
override fun convert(value: Fee.Bitcoin): ImmutableList<CustomFeeFieldUM> {
|
||||
val feeValue = value.amount.value
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.features.send.v2.subcomponents.fee.model.transformers
|
||||
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeSelectorUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeUM
|
||||
|
|
@ -28,7 +28,7 @@ internal class SendFeeInitialStateTransformer(
|
|||
isCustomSelected = false,
|
||||
isFeeConvertibleToFiat = feeCryptoCurrencyStatus.currency.network.hasFiatFeeRate,
|
||||
isTronToken = cryptoCurrency is CryptoCurrency.Token &&
|
||||
isTron(cryptoCurrency.network.id.value),
|
||||
isTron(cryptoCurrency.network.rawId),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -25,12 +25,12 @@ 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.ui.extensions.resourceReference
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.notifications.GetTronFeeNotificationShowCountUseCase
|
||||
import com.tangem.domain.notifications.IncrementNotificationsShowCountUseCase
|
||||
import com.tangem.domain.tokens.GetBalanceNotEnoughForFeeWarningUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyCheckUseCase
|
||||
import com.tangem.domain.tokens.IsAmountSubtractAvailableUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck
|
||||
import com.tangem.domain.transaction.usecase.ValidateTransactionUseCase
|
||||
|
|
@ -255,7 +255,7 @@ internal class NotificationsModel @Inject constructor(
|
|||
)
|
||||
},
|
||||
)
|
||||
if (!BlockchainUtils.isCardano(currency.network.id.value)) {
|
||||
if (!BlockchainUtils.isCardano(currency.network.rawId)) {
|
||||
addDustWarningNotification(
|
||||
dustValue = currencyCheck.dustValue,
|
||||
feeValue = feeValue,
|
||||
|
|
@ -375,7 +375,7 @@ internal class NotificationsModel @Inject constructor(
|
|||
private suspend fun MutableList<NotificationUM>.addTronNetworkFeesNotification() {
|
||||
val cryptoCurrency = cryptoCurrencyStatus.currency
|
||||
val isTronToken = cryptoCurrency is CryptoCurrency.Token &&
|
||||
isTron(cryptoCurrency.network.id.value)
|
||||
isTron(cryptoCurrency.network.rawId)
|
||||
|
||||
if (isTronToken && getTronFeeNotificationShowCountUseCase() <= TRON_FEE_NOTIFICATION_MAX_SHOW_COUNT) {
|
||||
add(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue