Updated on 2026-08-14
This commit is contained in:
parent
7e5473b8c5
commit
9ae8e54953
10 changed files with 70 additions and 29 deletions
|
|
@ -48,6 +48,9 @@ enum class ExchangeStatus {
|
|||
|
||||
@Json(name = "verifying")
|
||||
VERIFYING,
|
||||
|
||||
@Json(name = "cancelled")
|
||||
CANCELLED,
|
||||
}
|
||||
|
||||
data class ExchangeStatusError(
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@
|
|||
<string name="express_exchange_notification_failed_title">Операция не выполнена провайдером</string>
|
||||
<string name="express_exchange_notification_verification_text">Посетите сайт провайдера для проверки</string>
|
||||
<string name="express_exchange_notification_verification_title">Провайдер запрашивает прохождение верификации</string>
|
||||
<string name="express_exchange_status_canceled">Отменен</string>
|
||||
<string name="express_exchange_status_confirmed">Подтверждено</string>
|
||||
<string name="express_exchange_status_confirming">Подтверждение</string>
|
||||
<string name="express_exchange_status_confirming_active">Подтверждение...</string>
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@
|
|||
<string name="express_exchange_notification_failed_title">Operation failed by provider</string>
|
||||
<string name="express_exchange_notification_verification_text">Visit provider’s website for verification</string>
|
||||
<string name="express_exchange_notification_verification_title">KYC verification required by provider</string>
|
||||
<string name="express_exchange_status_cancelled">Cancelled</string>
|
||||
<string name="express_exchange_status_canceled">Canceled</string>
|
||||
<string name="express_exchange_status_confirmed">Confirmed</string>
|
||||
<string name="express_exchange_status_confirming">Confirming</string>
|
||||
<string name="express_exchange_status_confirming_active">Confirming…</string>
|
||||
|
|
|
|||
|
|
@ -17,4 +17,5 @@ enum class ExchangeStatus {
|
|||
Sending,
|
||||
Finished,
|
||||
Refunded,
|
||||
Cancelled,
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ internal data class SwapTransactionsState(
|
|||
val fromCryptoSymbol: String,
|
||||
val fromFiatAmount: String,
|
||||
val fromCurrencyIcon: TokenIconState,
|
||||
val showProviderLink: Boolean,
|
||||
val onClick: () -> Unit,
|
||||
val onGoToProviderClick: (String) -> Unit,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
val toFiatAmount = toAmount.multiply(toCurrency.value.fiatRate)
|
||||
val fromFiatAmount = fromAmount.multiply(fromCurrency.value.fiatRate)
|
||||
val timestamp = transaction.timestamp
|
||||
val notifications = getNotification(transaction.status?.status, transaction.status?.txExternalUrl)
|
||||
val showProviderLink = getShowProviderLink(notifications, transaction.status)
|
||||
result.add(
|
||||
SwapTransactionsState(
|
||||
txId = transaction.txId,
|
||||
|
|
@ -92,6 +94,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
fromCryptoSymbol = fromCurrency.currency.symbol,
|
||||
fromFiatAmount = getFiatAmount(fromFiatAmount),
|
||||
fromCurrencyIcon = iconStateConverter.convert(fromCurrency),
|
||||
showProviderLink = showProviderLink,
|
||||
onClick = { clickIntents.onSwapTransactionClick(transaction.txId) },
|
||||
onGoToProviderClick = { url ->
|
||||
analyticsEventsHandlerProvider().send(
|
||||
|
|
@ -109,12 +112,15 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
fun updateTxStatus(tx: SwapTransactionsState, statusModel: ExchangeStatusModel?): SwapTransactionsState {
|
||||
if (statusModel == null || tx.activeStatus == statusModel.status) return tx
|
||||
val hasFailed = tx.hasFailed || statusModel.status == ExchangeStatus.Failed
|
||||
val notifications = getNotification(statusModel.status, statusModel.txExternalUrl)
|
||||
val showProviderLink = getShowProviderLink(notifications, statusModel)
|
||||
return tx.copy(
|
||||
activeStatus = statusModel.status,
|
||||
hasFailed = hasFailed,
|
||||
notification = getNotification(statusModel.status, statusModel.txExternalUrl),
|
||||
notification = notifications,
|
||||
statuses = getStatuses(statusModel.status, hasFailed),
|
||||
txUrl = statusModel.txExternalUrl,
|
||||
showProviderLink = showProviderLink,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -149,6 +155,9 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getShowProviderLink(notifications: ExchangeStatusNotifications?, status: ExchangeStatusModel?) =
|
||||
notifications == null && status?.txExternalUrl != null && status.status != ExchangeStatus.Cancelled
|
||||
|
||||
private fun getStatuses(status: ExchangeStatus?, hasFailed: Boolean = false): ImmutableList<ExchangeStatusState> {
|
||||
if (status == null) return persistentListOf()
|
||||
val isWaiting = status == ExchangeStatus.New || status == ExchangeStatus.Waiting
|
||||
|
|
@ -164,26 +173,37 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
val isExchangingDone = !isExchanging && isConfirmingDone
|
||||
val isSendingDone = !isSending && !isVerifying && !isFailed && isExchangingDone
|
||||
|
||||
return listOf(
|
||||
waitStep(isWaiting, isWaitingDone),
|
||||
confirmStep(isConfirming, isConfirmingDone),
|
||||
exchangeStep(
|
||||
isExchanging = isExchanging,
|
||||
isExchangingDone = isExchangingDone,
|
||||
isRefunded = isRefunded,
|
||||
hasFailed = hasFailed,
|
||||
isVerifying = isVerifying,
|
||||
isFailed = isFailed,
|
||||
),
|
||||
sendStep(
|
||||
isSending = isSending,
|
||||
isSendingDone = isSendingDone,
|
||||
isRefunded = isRefunded,
|
||||
hasFailed = hasFailed,
|
||||
),
|
||||
).toPersistentList()
|
||||
return if (status == ExchangeStatus.Cancelled) {
|
||||
listOf(cancelledStep())
|
||||
} else {
|
||||
listOf(
|
||||
waitStep(isWaiting, isWaitingDone),
|
||||
confirmStep(isConfirming, isConfirmingDone),
|
||||
exchangeStep(
|
||||
isExchanging = isExchanging,
|
||||
isExchangingDone = isExchangingDone,
|
||||
isRefunded = isRefunded,
|
||||
hasFailed = hasFailed,
|
||||
isVerifying = isVerifying,
|
||||
isFailed = isFailed,
|
||||
),
|
||||
sendStep(
|
||||
isSending = isSending,
|
||||
isSendingDone = isSendingDone,
|
||||
isRefunded = isRefunded,
|
||||
hasFailed = hasFailed,
|
||||
),
|
||||
)
|
||||
}.toPersistentList()
|
||||
}
|
||||
|
||||
private fun cancelledStep() = ExchangeStatusState(
|
||||
status = ExchangeStatus.Cancelled,
|
||||
text = TextReference.Res(R.string.express_exchange_status_canceled),
|
||||
isActive = true,
|
||||
isDone = true,
|
||||
)
|
||||
|
||||
private fun waitStep(isNew: Boolean, isNewDone: Boolean) = ExchangeStatusState(
|
||||
status = ExchangeStatus.New,
|
||||
text = when {
|
||||
|
|
|
|||
|
|
@ -75,11 +75,15 @@ internal fun ExchangeStatusBlock(
|
|||
}
|
||||
}
|
||||
|
||||
statuses.forEachIndexed { index, item ->
|
||||
ExchangeStatusStep(
|
||||
stepStatus = item,
|
||||
isLast = index == statuses.lastIndex,
|
||||
)
|
||||
AnimatedContent(targetState = statuses.lastIndex, label = "Exchange Status List Change") {
|
||||
Column {
|
||||
statuses.forEachIndexed { index, item ->
|
||||
ExchangeStatusStep(
|
||||
stepStatus = item,
|
||||
isLast = index == it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -101,6 +105,11 @@ private fun ExchangeStatusStep(
|
|||
.size(TangemTheme.dimens.size20),
|
||||
) {
|
||||
when {
|
||||
it.status == ExchangeStatus.Cancelled -> ExchangeStep(
|
||||
iconRes = R.drawable.ic_close_24,
|
||||
color = TangemTheme.colors.icon.warning,
|
||||
isDone = false,
|
||||
)
|
||||
it.status == ExchangeStatus.Failed -> ExchangeStep(
|
||||
iconRes = R.drawable.ic_close_24,
|
||||
color = TangemTheme.colors.icon.warning,
|
||||
|
|
@ -131,6 +140,7 @@ private fun ExchangeStatusStep(
|
|||
@Composable
|
||||
private fun ExchangeStatusStepText(stepStatus: ExchangeStatusState) {
|
||||
val textColor = when {
|
||||
stepStatus.status == ExchangeStatus.Cancelled -> TangemTheme.colors.icon.warning
|
||||
stepStatus.status == ExchangeStatus.Failed && !stepStatus.isDone -> TangemTheme.colors.icon.warning
|
||||
stepStatus.status == ExchangeStatus.Verifying && !stepStatus.isDone -> TangemTheme.colors.icon.attention
|
||||
stepStatus.isDone -> TangemTheme.colors.text.primary1
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ private fun ExchangeStatusBottomSheetContent(content: ExchangeStatusBottomSheetC
|
|||
SpacerH12()
|
||||
ExchangeStatusBlock(
|
||||
statuses = config.statuses,
|
||||
showLink = config.notification == null && config.txUrl != null,
|
||||
showLink = config.showProviderLink,
|
||||
onClick = { config.onGoToProviderClick(config.txUrl.orEmpty()) },
|
||||
)
|
||||
AnimatedContent(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ import androidx.annotation.DrawableRes
|
|||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
|
|
@ -42,7 +44,9 @@ internal fun LazyListScope.swapTransactionsItems(
|
|||
val item = swapTxs[it]
|
||||
val (iconRes, tint) = when (item.activeStatus) {
|
||||
ExchangeStatus.Verifying -> R.drawable.ic_alert_triangle_20 to TangemTheme.colors.icon.attention
|
||||
ExchangeStatus.Failed -> R.drawable.ic_alert_circle_24 to TangemTheme.colors.icon.warning
|
||||
ExchangeStatus.Failed, ExchangeStatus.Cancelled -> {
|
||||
R.drawable.ic_alert_circle_24 to TangemTheme.colors.icon.warning
|
||||
}
|
||||
else -> null to null
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
clickIntents = this,
|
||||
appCurrencyProvider = Provider { selectedAppCurrencyFlow.value },
|
||||
analyticsEventsHandlerProvider = Provider { analyticsEventsHandler },
|
||||
currentStateProvider = Provider { uiState },
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
)
|
||||
|
|
@ -229,7 +230,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
delay = EXCHANGE_STATUS_UPDATE_DELAY,
|
||||
task = {
|
||||
runCatching(dispatchers.io) {
|
||||
exchangeStatusFactory.updateSwapTxStatuses(swapTxs)
|
||||
exchangeStatusFactory.updateSwapTxStatuses(uiState.swapTxs)
|
||||
}
|
||||
},
|
||||
onSuccess = ::updateSwapTx,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue