Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-26 16:57:08 +05:00
parent aae09c4b68
commit 39aa3b744d
7 changed files with 123 additions and 80 deletions

View file

@ -38,6 +38,7 @@ dependencies {
implementation(projects.domain.feedback)
implementation(projects.domain.feedback.models)
implementation(projects.domain.models)
implementation(projects.domain.onramp.models)
implementation(projects.domain.visa)
implementation(projects.domain.visa.models)
implementation(projects.domain.wallets)

View file

@ -15,8 +15,8 @@ import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.navigation.inner.InnerRouter
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.tangempay.components.express.ExpressTransactionsComponentProvider
import com.tangem.features.tangempay.navigation.TangemPayAccountDetailsInnerRoute
import com.tangem.features.tokendetails.ExpressTransactionsComponent
import com.tangem.features.tokenreceive.TokenReceiveComponent
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -27,7 +27,7 @@ internal class DefaultTangemPayDetailsContainerComponent @AssistedInject constru
@Assisted private val params: TangemPayDetailsContainerComponent.Params,
private val tangemPayCardPageFactory: TangemPayCardPageComponent.Factory,
private val tokenReceiveComponentFactory: TokenReceiveComponent.Factory,
private val expressTransactionsComponentProvider: ExpressTransactionsComponentProvider,
private val expressTransactionsComponentFactory: ExpressTransactionsComponent.Factory,
) : AppComponentContext by appComponentContext, TangemPayDetailsContainerComponent {
private val stackNavigation = StackNavigation<TangemPayAccountDetailsInnerRoute>()
@ -63,7 +63,7 @@ internal class DefaultTangemPayDetailsContainerComponent @AssistedInject constru
appComponentContext = childByContext(componentContext = componentContext, router = innerRouter),
params = params,
tokenReceiveComponentFactory = tokenReceiveComponentFactory,
expressTransactionsComponentProvider = expressTransactionsComponentProvider,
expressTransactionsComponentFactory = expressTransactionsComponentFactory,
)
TangemPayAccountDetailsInnerRoute.CardDetails -> tangemPayCardPageFactory.create(
context = childByContext(componentContext = componentContext, router = innerRouter),

View file

@ -16,7 +16,6 @@ import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.tangempay.components.express.ExpressTransactionsComponentProvider
import com.tangem.features.tangempay.components.txHistory.DefaultTangemPayTxHistoryComponent
import com.tangem.features.tangempay.components.txHistory.TangemPayTxHistoryDetailsComponent
import com.tangem.features.tangempay.entity.TangemPayDetailsNavigation
@ -24,13 +23,14 @@ import com.tangem.features.tangempay.model.TangemPayDetailsModel
import com.tangem.features.tangempay.ui.TangemPayDetailsScreen
import com.tangem.features.tangempay.utils.requireLoaded
import com.tangem.features.tangempay.utils.userWalletId
import com.tangem.features.tokendetails.ExpressTransactionsComponent
import com.tangem.features.tokenreceive.TokenReceiveComponent
internal class TangemPayDetailsComponent(
private val appComponentContext: AppComponentContext,
private val params: TangemPayDetailsContainerComponent.Params,
private val tokenReceiveComponentFactory: TokenReceiveComponent.Factory,
private val expressTransactionsComponentProvider: ExpressTransactionsComponentProvider,
private val expressTransactionsComponentFactory: ExpressTransactionsComponent.Factory,
) : AppComponentContext by appComponentContext, ComposableContentComponent {
private val model: TangemPayDetailsModel = getOrCreateModel(params = params)
@ -50,10 +50,12 @@ internal class TangemPayDetailsComponent(
)
private val expressTransactionsComponent by lazy {
expressTransactionsComponentProvider.create(
appComponentContext = child("expressTransactionsComponent"),
userWalletId = params.initialStatus.userWalletId,
cryptoCurrency = model.cryptoCurrency,
expressTransactionsComponentFactory.create(
context = child("expressTransactionsComponent"),
params = ExpressTransactionsComponent.Params(
userWalletId = params.initialStatus.userWalletId,
currency = model.cryptoCurrency,
),
)
}

View file

@ -1,39 +0,0 @@
package com.tangem.features.tangempay.components.express
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM
import com.tangem.common.ui.expressStatus.state.ExpressTransactionsBlockState
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.features.tokendetails.ExpressTransactionsComponent
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@Stable
internal class EmptyExpressTransactionsComponent(
context: AppComponentContext,
) : AppComponentContext by context, ExpressTransactionsComponent {
override val state: StateFlow<ExpressTransactionsBlockState> = MutableStateFlow(getInitialState())
override fun LazyListScope.expressTransactionsContentLegacy(
state: PersistentList<ExpressTransactionStateUM>,
modifier: Modifier,
) {}
override fun LazyListScope.expressTransactionsContent(
state: PersistentList<ExpressTransactionStateUM>,
modifier: Modifier,
) {}
private fun getInitialState(): ExpressTransactionsBlockState {
return ExpressTransactionsBlockState(
transactions = persistentListOf(),
transactionsToDisplay = persistentListOf(),
bottomSheetSlot = null,
)
}
}

View file

@ -1,25 +0,0 @@
package com.tangem.features.tangempay.components.express
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.features.tokendetails.ExpressTransactionsComponent
import javax.inject.Inject
internal class ExpressTransactionsComponentProvider @Inject constructor(
private val expressTransactionsComponentFactory: ExpressTransactionsComponent.Factory,
) {
fun create(
appComponentContext: AppComponentContext,
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency?,
): ExpressTransactionsComponent = if (cryptoCurrency != null) {
expressTransactionsComponentFactory.create(
context = appComponentContext,
params = ExpressTransactionsComponent.Params(userWalletId = userWalletId, currency = cryptoCurrency),
)
} else {
EmptyExpressTransactionsComponent(context = appComponentContext)
}
}

View file

@ -2,17 +2,24 @@ package com.tangem.features.tangempay.components.express
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.ui.Modifier
import com.tangem.common.ui.expressStatus.expressTransactionsItemsLegacy
import com.tangem.common.ui.expressStatus.state.ExpressLinkUM
import com.tangem.common.ui.expressStatus.state.ExpressStatusItemState
import com.tangem.common.ui.expressStatus.state.ExpressStatusItemUM
import com.tangem.common.ui.expressStatus.state.ExpressStatusUM
import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateIconUM
import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateInfoUM
import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM
import com.tangem.common.ui.expressStatus.state.ExpressTransactionsBlockState
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.onramp.model.OnrampStatus
import com.tangem.features.tokendetails.ExpressTransactionsComponent
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
/** Cannot really preview anything here since the UM implementation [ExchangeUM] is in token:details module
* For the actual preview @see [TokenDetailsScreen]
**/
internal class PreviewEmptyExpressTransactionsComponent : ExpressTransactionsComponent {
override val state: StateFlow<ExpressTransactionsBlockState> = MutableStateFlow(getInitialState())
@ -20,18 +27,114 @@ internal class PreviewEmptyExpressTransactionsComponent : ExpressTransactionsCom
override fun LazyListScope.expressTransactionsContentLegacy(
state: PersistentList<ExpressTransactionStateUM>,
modifier: Modifier,
) {}
) {
expressTransactionsItemsLegacy(expressTxs = state, modifier = modifier)
}
override fun LazyListScope.expressTransactionsContent(
state: PersistentList<ExpressTransactionStateUM>,
modifier: Modifier,
) {}
) {
expressTransactionsItemsLegacy(expressTxs = state, modifier = modifier)
}
private fun getInitialState(): ExpressTransactionsBlockState {
val sample = persistentListOf<ExpressTransactionStateUM>(
sampleOnrampUM(
txId = "preview-onramp-1",
title = "Buying USDC",
activeStatusText = "Verifying",
activeStatus = OnrampStatus.Status.Verifying,
timestampAgo = "5m ago",
toAmount = "100.00",
toSymbol = "USDC",
fromAmount = "100.00",
fromSymbol = "USD",
iconState = ExpressTransactionStateIconUM.None,
),
sampleOnrampUM(
txId = "preview-onramp-2",
title = "Buying USDC",
activeStatusText = "Waiting for payment",
activeStatus = OnrampStatus.Status.WaitingForPayment,
timestampAgo = "1h ago",
toAmount = "250.00",
toSymbol = "USDC",
fromAmount = "250.00",
fromSymbol = "EUR",
iconState = ExpressTransactionStateIconUM.Warning,
),
sampleOnrampUM(
txId = "preview-onramp-3",
title = "Buying USDC",
activeStatusText = "Failed",
activeStatus = OnrampStatus.Status.Failed,
timestampAgo = "2d ago",
toAmount = "50.00",
toSymbol = "USDC",
fromAmount = "50.00",
fromSymbol = "USD",
iconState = ExpressTransactionStateIconUM.Error,
),
)
return ExpressTransactionsBlockState(
transactions = persistentListOf(),
transactionsToDisplay = persistentListOf(),
transactions = sample,
transactionsToDisplay = sample,
bottomSheetSlot = null,
)
}
@Suppress("LongParameterList")
private fun sampleOnrampUM(
txId: String,
title: String,
activeStatusText: String,
activeStatus: OnrampStatus.Status,
timestampAgo: String,
toAmount: String,
toSymbol: String,
fromAmount: String,
fromSymbol: String,
iconState: ExpressTransactionStateIconUM,
): ExpressTransactionStateUM.OnrampUM {
return ExpressTransactionStateUM.OnrampUM(
info = ExpressTransactionStateInfoUM(
title = TextReference.Str(title),
status = ExpressStatusUM(
title = TextReference.Str("Status"),
link = ExpressLinkUM.Empty,
statuses = persistentListOf(
ExpressStatusItemUM(TextReference.Str("Created"), ExpressStatusItemState.Done),
ExpressStatusItemUM(TextReference.Str(activeStatusText), ExpressStatusItemState.Active),
ExpressStatusItemUM(TextReference.Str("Finished"), ExpressStatusItemState.Default),
),
),
notification = null,
txId = txId,
txExternalId = null,
txExternalUrl = null,
timestamp = 0L,
timestampFormatted = TextReference.Str(timestampAgo),
timestampAgoFormatted = TextReference.Str(timestampAgo),
activeStatus = TextReference.Str(activeStatusText),
onGoToProviderClick = {},
onClick = {},
onDisposeExpressStatus = {},
iconState = iconState,
toAmount = TextReference.Str(toAmount),
toFiatAmount = null,
toAmountSymbol = toSymbol,
toCurrencyIcon = CurrencyIconState.Empty(),
fromAmount = TextReference.Str(fromAmount),
fromFiatAmount = null,
fromAmountSymbol = fromSymbol,
fromCurrencyIcon = CurrencyIconState.Empty(),
),
providerName = "Preview Provider",
providerImageUrl = "",
providerType = "CEX",
activeStatus = activeStatus,
fromCurrencyCode = fromSymbol,
)
}
}

View file

@ -161,6 +161,7 @@ internal fun TangemPayDetailsScreen(
state = expressState.transactionsToDisplay,
modifier = modifier
.padding(horizontal = 16.dp)
.padding(top = 12.dp)
.fillMaxWidth(),
)
}