From 9ae8e54953acbe3bbd9884646b6b3a76fbe2fa3d Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 25 Dec 2023 19:30:50 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../models/response/ExchangeStatusResponse.kt | 3 + core/res/src/main/res/values-ru/strings.xml | 1 + core/res/src/main/res/values/strings.xml | 2 +- .../domain/models/domain/ExchangeStatus.kt | 1 + .../state/SwapTransactionsState.kt | 1 + ...enDetailsSwapTransactionsStateConverter.kt | 58 +++++++++++++------ .../exchange/ExchangeStatusBlock.kt | 20 +++++-- .../exchange/ExchangeStatusBottomSheet.kt | 2 +- .../exchange/ExchangeStatusItems.kt | 8 ++- .../viewmodels/TokenDetailsViewModel.kt | 3 +- 10 files changed, 70 insertions(+), 29 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeStatusResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeStatusResponse.kt index 94cd9cbf1f..3be2a6ebec 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeStatusResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeStatusResponse.kt @@ -48,6 +48,9 @@ enum class ExchangeStatus { @Json(name = "verifying") VERIFYING, + + @Json(name = "cancelled") + CANCELLED, } data class ExchangeStatusError( diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index c2434991f2..afc6fda219 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -205,6 +205,7 @@ Операция не выполнена провайдером Посетите сайт провайдера для проверки Провайдер запрашивает прохождение верификации + Отменен Подтверждено Подтверждение Подтверждение... diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 7998107847..6548a846ee 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -205,7 +205,7 @@ Operation failed by provider Visit provider’s website for verification KYC verification required by provider - Cancelled + Canceled Confirmed Confirming Confirming… diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeStatus.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeStatus.kt index e412c74751..1e3727b208 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeStatus.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeStatus.kt @@ -17,4 +17,5 @@ enum class ExchangeStatus { Sending, Finished, Refunded, + Cancelled, } \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/SwapTransactionsState.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/SwapTransactionsState.kt index d55821009b..c1e0f67210 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/SwapTransactionsState.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/SwapTransactionsState.kt @@ -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, ) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt index 514afc7709..c5069303c7 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt @@ -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 { 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 { diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBlock.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBlock.kt index 1574bb2db6..ac5edc4fc4 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBlock.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBlock.kt @@ -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 diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBottomSheet.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBottomSheet.kt index ea31904d30..da9113487a 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBottomSheet.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBottomSheet.kt @@ -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( diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusItems.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusItems.kt index c32011f436..94c1d12187 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusItems.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusItems.kt @@ -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 } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt index 1c3f77a105..fee7ee1a64 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt @@ -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,