From afb82a03f7513b5822414b7557980abb032e42c6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Mar 2025 16:31:59 +0200 Subject: [PATCH] Updated on 2026-08-14 --- .../models/response/ExchangeStatusResponse.kt | 7 ++ .../analytics/TokenExchangeAnalyticsEvent.kt | 23 +++- features/swap/data/build.gradle.kts | 1 + .../converters/ExchangeStatusConverter.kt | 2 + features/swap/domain/models/build.gradle.kts | 1 + .../domain/models/domain/ExchangeStatus.kt | 14 ++- .../feature/swap/domain/SwapInteractorImpl.kt | 2 + ...tions.kt => ExchangeStatusNotification.kt} | 18 ++- .../tokendetails/state/express/ExchangeUM.kt | 5 +- ...enDetailsSwapTransactionsStateConverter.kt | 54 +++++---- .../factory/express/ExchangeStatusFactory.kt | 12 +- .../factory/express/ExpressStatusFactory.kt | 29 ++++- .../express/ExpressStatusBottomSheet.kt | 23 +++- .../ExpressStatusBottomSheetStateProvider.kt | 111 ++++++++++++++++++ .../ExchangeStatusBottomSheetContent.kt | 9 +- 15 files changed, 270 insertions(+), 41 deletions(-) rename features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/{ExchangeStatusNotifications.kt => ExchangeStatusNotification.kt} (84%) create mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/ExpressStatusBottomSheetStateProvider.kt 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 043222d3e3..eaada836bf 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 @@ -2,6 +2,7 @@ package com.tangem.datasource.api.express.models.response import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.joda.time.DateTime @JsonClass(generateAdapter = true) data class ExchangeStatusResponse( @@ -26,6 +27,12 @@ data class ExchangeStatusResponse( @Json(name = "refundContractAddress") val refundContractAddress: String? = null, + + @Json(name = "createdAt") + val createdAt: DateTime? = null, + + @Json(name = "averageDuration") + val averageDuration: Int? = null, ) @JsonClass(generateAdapter = false) diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenExchangeAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenExchangeAnalyticsEvent.kt index 9df2d8a224..7fe8dfdf64 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenExchangeAnalyticsEvent.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenExchangeAnalyticsEvent.kt @@ -26,17 +26,34 @@ class TokenExchangeAnalyticsEvent( ) class GoToProviderStatus(token: String) : TokenScreenAnalyticsEvent( - event = "Button - Go To Provider", + event = BUTTON_GO_TO_PROVIDER, params = mapOf(TOKEN_PARAM to token, PLACE to "Status"), ) class GoToProviderKYC(token: String) : TokenScreenAnalyticsEvent( - event = "Button - Go To Provider", + event = BUTTON_GO_TO_PROVIDER, params = mapOf(TOKEN_PARAM to token, PLACE to "KYC"), ) class GoToProviderFail(token: String) : TokenScreenAnalyticsEvent( - event = "Button - Go To Provider", + event = BUTTON_GO_TO_PROVIDER, params = mapOf(TOKEN_PARAM to token, PLACE to "Fail"), ) + + class GoToProviderLongTime(token: String) : TokenScreenAnalyticsEvent( + event = BUTTON_GO_TO_PROVIDER, + params = mapOf(TOKEN_PARAM to token, PLACE to "LongTime"), + ) + + class LongTimeTransaction(token: String, provider: String) : TokenScreenAnalyticsEvent( + event = "Notice - Long Time Transaction", + params = mapOf( + TOKEN_PARAM to token, + PROVIDER to provider, + ), + ) + + private companion object { + const val BUTTON_GO_TO_PROVIDER = "Button - Go To Provider" + } } \ No newline at end of file diff --git a/features/swap/data/build.gradle.kts b/features/swap/data/build.gradle.kts index 08890ead13..0134f08d66 100644 --- a/features/swap/data/build.gradle.kts +++ b/features/swap/data/build.gradle.kts @@ -49,6 +49,7 @@ dependencies { /** Others */ implementation(deps.timber) + implementation(deps.jodatime) /** DI */ implementation(deps.hilt.android) diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExchangeStatusConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExchangeStatusConverter.kt index cb3ba18d9f..a1cd69d8cb 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExchangeStatusConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExchangeStatusConverter.kt @@ -17,6 +17,8 @@ internal class ExchangeStatusConverter : Converter createdAt + } else { + false + } +} @JsonClass(generateAdapter = false) enum class ExchangeStatus { diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index a36223d839..717a096159 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -1006,6 +1006,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( timestamp: Long, txExternalUrl: String? = null, txExternalId: String? = null, + averageDuration: Int? = null, ) { swapTransactionRepository.storeTransaction( userWalletId = userWalletId, @@ -1023,6 +1024,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( txId = swapDataModel.transaction.txId, txExternalUrl = txExternalUrl, txExternalId = txExternalId, + averageDuration = averageDuration, ), ), ) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/ExchangeStatusNotifications.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/ExchangeStatusNotification.kt similarity index 84% rename from features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/ExchangeStatusNotifications.kt rename to features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/ExchangeStatusNotification.kt index 599abba71d..348e8e63ba 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/ExchangeStatusNotifications.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/ExchangeStatusNotification.kt @@ -15,9 +15,9 @@ import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.features.tokendetails.impl.R @Immutable -internal sealed interface ExchangeStatusNotifications { +internal sealed interface ExchangeStatusNotification { - sealed class CommonNotification(val config: NotificationConfig) : ExchangeStatusNotifications + sealed class CommonNotification(val config: NotificationConfig) : ExchangeStatusNotification @Deprecated("Use one in ExpressNotificationsUM") data class NeedVerification(val onGoToProviderClick: () -> Unit) : CommonNotification( @@ -45,11 +45,23 @@ internal sealed interface ExchangeStatusNotifications { ), ) + data class LongTimeExchange(val onGoToProviderClick: () -> Unit) : CommonNotification( + config = NotificationConfig( + title = resourceReference(R.string.express_exchange_notification_long_transaction_time_title), + subtitle = resourceReference(R.string.express_exchange_notification_long_transaction_time_text), + iconResId = R.drawable.ic_alert_triangle_20, + buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig( + text = resourceReference(R.string.common_go_to_provider), + onClick = onGoToProviderClick, + ), + ), + ) + data class TokenRefunded( val cryptoCurrency: CryptoCurrency, val onReadMoreClick: () -> Unit, val onGoToTokenClick: () -> Unit, - ) : ExchangeStatusNotifications { + ) : ExchangeStatusNotification { val config = CurrencyNotificationConfig( title = resourceReference( diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/express/ExchangeUM.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/express/ExchangeUM.kt index ac23c537eb..85d610e7d9 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/express/ExchangeUM.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/express/ExchangeUM.kt @@ -5,7 +5,7 @@ import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.feature.swap.domain.models.domain.ExchangeStatus import com.tangem.feature.swap.domain.models.domain.SwapProvider -import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotifications +import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotification import kotlinx.collections.immutable.ImmutableList internal data class ExchangeUM( @@ -13,8 +13,9 @@ internal data class ExchangeUM( val provider: SwapProvider, val activeStatus: ExchangeStatus?, val statuses: ImmutableList, - val notification: ExchangeStatusNotifications? = null, + val notification: ExchangeStatusNotification?, val showProviderLink: Boolean, val fromCryptoCurrency: CryptoCurrency, val toCryptoCurrency: CryptoCurrency, + val hasLongTime: Boolean, ) : ExpressTransactionStateUM \ No newline at end of file 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 d13c0cab28..780910ba7b 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 @@ -24,7 +24,7 @@ import com.tangem.feature.swap.domain.models.domain.ExchangeStatus.Companion.isF import com.tangem.feature.swap.domain.models.domain.ExchangeStatusModel import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionListModel import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionModel -import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotifications +import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeStatusState import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents @@ -82,17 +82,18 @@ internal class TokenDetailsSwapTransactionsStateConverter( } } val statusModel = transaction.status - val notifications = getNotification( + val notification = getNotification( status = statusModel?.status, txUrl = statusModel?.txExternalUrl, refundToken = statusModel?.refundCurrency, + hasLongTime = statusModel?.hasLongTime, ) - val showProviderLink = getShowProviderLink(notifications, transaction.status) + val showProviderLink = getShowProviderLink(notification, transaction.status) result.add( ExchangeUM( provider = transaction.provider, statuses = getStatuses(statusModel?.status), - notification = notifications, + notification = notification, activeStatus = statusModel?.status, showProviderLink = showProviderLink, fromCryptoCurrency = fromCryptoCurrency, @@ -104,6 +105,7 @@ internal class TokenDetailsSwapTransactionsStateConverter( toFiatAmount, fromFiatAmount, ), + hasLongTime = transaction.status?.hasLongTime ?: false, ), ) } @@ -111,17 +113,22 @@ internal class TokenDetailsSwapTransactionsStateConverter( return result.toPersistentList() } - fun updateTxStatus(tx: ExchangeUM, statusModel: ExchangeStatusModel?): ExchangeUM { - if (statusModel == null || tx.activeStatus == statusModel.status) { + fun updateTxStatus(tx: ExchangeUM, statusModel: ExchangeStatusModel): ExchangeUM { + if (tx.activeStatus == statusModel.status && tx.hasLongTime == statusModel.hasLongTime) { Timber.e("UpdateTxStatus isn't required. Current status isn't changed") return tx } val hasFailed = statusModel.status.isFailed() - val notifications = getNotification(statusModel.status, statusModel.txExternalUrl, statusModel.refundCurrency) - val showProviderLink = getShowProviderLink(notifications, statusModel) + val notification = getNotification( + status = statusModel.status, + txUrl = statusModel.txExternalUrl, + refundToken = statusModel.refundCurrency, + hasLongTime = statusModel.hasLongTime, + ) + val showProviderLink = getShowProviderLink(notification, statusModel) return tx.copy( activeStatus = statusModel.status, - notification = notifications, + notification = notification, statuses = getStatuses(statusModel.status, hasFailed), showProviderLink = showProviderLink, info = tx.info.copy(txExternalUrl = statusModel.txExternalUrl), @@ -184,39 +191,46 @@ internal class TokenDetailsSwapTransactionsStateConverter( status: ExchangeStatus?, txUrl: String?, refundToken: CryptoCurrency?, - ): ExchangeStatusNotifications? { - return when (status) { - ExchangeStatus.Failed, - ExchangeStatus.TxFailed, - -> { + hasLongTime: Boolean?, + ): ExchangeStatusNotification? { + return when { + status == ExchangeStatus.Failed || status == ExchangeStatus.TxFailed -> { if (txUrl == null) return null - ExchangeStatusNotifications.Failed { + ExchangeStatusNotification.Failed { analyticsEventsHandler.send( TokenExchangeAnalyticsEvent.GoToProviderFail(cryptoCurrency.symbol), ) clickIntents.onGoToProviderClick(txUrl) } } - ExchangeStatus.Verifying -> { + status == ExchangeStatus.Verifying -> { if (txUrl == null) return null - ExchangeStatusNotifications.NeedVerification { + ExchangeStatusNotification.NeedVerification { analyticsEventsHandler.send( TokenExchangeAnalyticsEvent.GoToProviderKYC(cryptoCurrency.symbol), ) clickIntents.onGoToProviderClick(txUrl) } } - ExchangeStatus.Refunded -> { + status == ExchangeStatus.Refunded -> { if (refundToken == null) { null } else { - ExchangeStatusNotifications.TokenRefunded( + ExchangeStatusNotification.TokenRefunded( cryptoCurrency = refundToken, onReadMoreClick = { clickIntents.onOpenUrlClick(url = getAboutCrossChainBridgesLink()) }, onGoToTokenClick = { clickIntents.onGoToRefundedTokenClick(refundToken) }, ) } } + status?.isTerminal == false && txUrl != null && hasLongTime == true -> { + ExchangeStatusNotification.LongTimeExchange { + analyticsEventsHandler.send( + event = TokenExchangeAnalyticsEvent.GoToProviderLongTime(cryptoCurrency.symbol), + ) + clickIntents.onGoToProviderClick(txUrl) + } + } else -> null } } @@ -239,7 +253,7 @@ internal class TokenDetailsSwapTransactionsStateConverter( statuses = persistentListOf(), ) - private fun getShowProviderLink(notifications: ExchangeStatusNotifications?, status: ExchangeStatusModel?) = + private fun getShowProviderLink(notifications: ExchangeStatusNotification?, status: ExchangeStatusModel?) = notifications == null && status?.txExternalUrl != null && status.status != ExchangeStatus.Cancelled private fun getStatuses(status: ExchangeStatus?, hasFailed: Boolean = false): ImmutableList { diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt index 8596a83abd..f9d9aed682 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt @@ -101,10 +101,14 @@ internal class ExchangeStatusFactory @AssistedInject constructor( } else { val statusModel = getExchangeStatus(swapTx.info.txId, swapTx.provider) - swapTransactionsStateConverter.updateTxStatus( - tx = swapTx, - statusModel = statusModel, - ) + if (statusModel != null) { + swapTransactionsStateConverter.updateTxStatus( + tx = swapTx, + statusModel = statusModel, + ) + } else { + swapTx + } } } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt index 289cfffede..636fa5cc1f 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt @@ -12,6 +12,7 @@ import com.tangem.domain.tokens.model.analytics.TokenOnrampAnalyticsEvent import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.swap.domain.models.domain.ExchangeStatus import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState +import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider @@ -110,9 +111,7 @@ internal class ExpressStatusFactory @AssistedInject constructor( return state.copy( expressTxs = expressTxs, expressTxsToDisplay = expressTxsToDisplay, - bottomSheetConfig = currentTx?.let( - ::updateStateWithExpressStatusBottomSheet, - ) ?: config, + bottomSheetConfig = currentTx?.let(::updateStateWithExpressStatusBottomSheet) ?: config, ) } @@ -146,6 +145,12 @@ internal class ExpressStatusFactory @AssistedInject constructor( val state = currentStateProvider() val bottomSheetConfig = state.bottomSheetConfig val currentConfig = bottomSheetConfig?.content as? ExpressStatusBottomSheetConfig ?: return bottomSheetConfig + + sendLongTimeExchangeNotificationShowEvent( + expressState = expressState, + currentStateNotification = (currentConfig.value as? ExchangeUM)?.notification, + ) + return bottomSheetConfig.copy( content = if (currentConfig.value != expressState) { ExpressStatusBottomSheetConfig(expressState) @@ -167,6 +172,24 @@ internal class ExpressStatusFactory @AssistedInject constructor( } } + private fun sendLongTimeExchangeNotificationShowEvent( + expressState: ExpressTransactionStateUM, + currentStateNotification: ExchangeStatusNotification?, + ) { + val newState = expressState as? ExchangeUM + val newStateNotification = newState?.notification + if (currentStateNotification !is ExchangeStatusNotification.LongTimeExchange && + newStateNotification is ExchangeStatusNotification.LongTimeExchange + ) { + analyticsEventsHandler.send( + TokenExchangeAnalyticsEvent.LongTimeTransaction( + token = cryptoCurrency.symbol, + provider = newState.provider.name, + ), + ) + } + } + @AssistedFactory interface Factory { @Suppress("LongParameterList") diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/ExpressStatusBottomSheet.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/ExpressStatusBottomSheet.kt index 8eec7243af..0bf0416539 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/ExpressStatusBottomSheet.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/ExpressStatusBottomSheet.kt @@ -1,12 +1,16 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.express +import android.content.res.Configuration import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig import com.tangem.common.ui.expressStatus.OnrampStatusBottomSheetContent -import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM +import com.tangem.common.ui.expressStatus.state.* import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.express.exchange.ExchangeStatusBottomSheetContent @@ -21,4 +25,21 @@ internal fun ExpressStatusBottomSheet(config: TangemBottomSheetConfig) { is ExchangeUM -> ExchangeStatusBottomSheetContent(state) } } +} + +@Preview(showBackground = true, widthDp = 360, heightDp = 720) +@Preview(showBackground = true, widthDp = 360, heightDp = 720, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun PreviewExpressStatusBottomSheet( + @PreviewParameter(ExpressStatusBottomSheetStateProvider::class) param: ExpressStatusBottomSheetConfig, +) { + TangemThemePreview { + ExpressStatusBottomSheet( + config = TangemBottomSheetConfig( + isShown = true, + onDismissRequest = {}, + content = param, + ), + ) + } } \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/ExpressStatusBottomSheetStateProvider.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/ExpressStatusBottomSheetStateProvider.kt new file mode 100644 index 0000000000..c5ae881c94 --- /dev/null +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/ExpressStatusBottomSheetStateProvider.kt @@ -0,0 +1,111 @@ +package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.express + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig +import com.tangem.common.ui.expressStatus.state.* +import com.tangem.core.ui.components.currency.icon.CurrencyIconState +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.tokens.model.CryptoCurrency.ID +import com.tangem.domain.tokens.model.Network +import com.tangem.feature.swap.domain.models.domain.ExchangeProviderType +import com.tangem.feature.swap.domain.models.domain.ExchangeStatus +import com.tangem.feature.swap.domain.models.domain.SwapProvider +import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotification +import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeStatusState +import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM +import kotlinx.collections.immutable.persistentListOf +import java.math.BigDecimal + +class ExpressStatusBottomSheetStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + ExpressStatusBottomSheetConfig( + ExchangeUM( + info = ExpressTransactionStateInfoUM( + title = TextReference.Str("Transaction Status"), + status = ExpressStatusUM( + title = TextReference.Str("Status Details"), + link = ExpressLinkUM.Empty, + statuses = persistentListOf( + ExpressStatusItemUM(TextReference.Str("Created"), ExpressStatusItemState.Active), + ExpressStatusItemUM(TextReference.Str("Exchanging"), ExpressStatusItemState.Active), + ExpressStatusItemUM(TextReference.Str("Done"), ExpressStatusItemState.Active), + ), + ), + notification = null, + txId = "123456", + txExternalId = "78910", + txExternalUrl = "https://example.com/tx/78910", + timestamp = System.currentTimeMillis(), + timestampFormatted = TextReference.Str("Just now"), + onGoToProviderClick = {}, + onClick = {}, + onDisposeExpressStatus = {}, + iconState = ExpressTransactionStateIconUM.None, + toAmount = TextReference.Str("0.1 BTC"), + toFiatAmount = TextReference.Str("$5000"), + toAmountSymbol = "BTC", + toCurrencyIcon = CurrencyIconState.Empty(), + fromAmount = TextReference.Str("5000 USDT"), + fromFiatAmount = TextReference.Str("$5000"), + fromAmountSymbol = "USDT", + fromCurrencyIcon = CurrencyIconState.Empty(), + ), + provider = SwapProvider( + providerId = "1", + rateTypes = emptyList(), + name = "Provider", + type = ExchangeProviderType.DEX, + imageLarge = "", + termsOfUse = null, + privacyPolicy = null, + slippage = BigDecimal.ZERO, + ), + activeStatus = null, + statuses = persistentListOf( + ExchangeStatusState( + status = ExchangeStatus.Exchanging, + text = stringReference("Exchanging"), + isActive = true, + isDone = false, + ), + ), + notification = ExchangeStatusNotification.LongTimeExchange {}, + showProviderLink = false, + fromCryptoCurrency = token, + toCryptoCurrency = token, + hasLongTime = true, + ), + ), + ) + + private val token + get() = CryptoCurrency.Coin( + id = ID( + ID.Prefix.COIN_PREFIX, + ID.Body.NetworkId(network.id.value), + ID.Suffix.RawID("token1"), + ), + network = network, + name = "Token 1", + symbol = "T1", + decimals = 8, + iconUrl = null, + isCustom = false, + ) + + private val network = Network( + id = Network.ID("network1"), + name = "Network One", + isTestnet = false, + standardType = Network.StandardType.ERC20, + backendId = "network1", + currencySymbol = "ETH", + derivationPath = Network.DerivationPath.None, + hasFiatFeeRate = true, + canHandleTokens = true, + transactionExtrasType = Network.TransactionExtrasType.NONE, + ) +} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/exchange/ExchangeStatusBottomSheetContent.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/exchange/ExchangeStatusBottomSheetContent.kt index c91628293c..581f05d757 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/exchange/ExchangeStatusBottomSheetContent.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/express/exchange/ExchangeStatusBottomSheetContent.kt @@ -24,7 +24,7 @@ import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.feature.swap.domain.models.domain.ExchangeStatus import com.tangem.feature.swap.domain.models.domain.ExchangeStatus.Companion.isFailed -import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotifications +import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM @Composable @@ -88,14 +88,15 @@ internal fun ExchangeStatusBottomSheetContent(state: ExchangeUM) { } @Composable -private fun Notification(state: ExchangeStatusNotifications, activeStatus: ExchangeStatus?) { +private fun Notification(state: ExchangeStatusNotification, activeStatus: ExchangeStatus?) { AnimatedContent( targetState = state, modifier = Modifier.padding(top = TangemTheme.dimens.spacing12), label = "Exchange Status Notification Change", + contentKey = { it::class.java }, ) { notification -> when (notification) { - is ExchangeStatusNotifications.CommonNotification -> { + is ExchangeStatusNotification.CommonNotification -> { com.tangem.core.ui.components.notifications.Notification( config = notification.config, iconTint = when { @@ -106,7 +107,7 @@ private fun Notification(state: ExchangeStatusNotifications, activeStatus: Excha containerColor = TangemTheme.colors.background.action, ) } - is ExchangeStatusNotifications.TokenRefunded -> { + is ExchangeStatusNotification.TokenRefunded -> { CurrencyNotification( config = notification.config, containerColor = TangemTheme.colors.background.action,