diff --git a/features/virtual-accounts/main/api/build.gradle.kts b/features/virtual-accounts/main/api/build.gradle.kts index 7cb5ec24bc..9d87052ccb 100644 --- a/features/virtual-accounts/main/api/build.gradle.kts +++ b/features/virtual-accounts/main/api/build.gradle.kts @@ -9,4 +9,12 @@ android { } dependencies { + /** Core */ + implementation(projects.core.decompose) + implementation(projects.core.ui) + + /** Compose */ + implementation(deps.compose.runtime) + implementation(deps.compose.foundation) + implementation(deps.compose.ui) } \ No newline at end of file diff --git a/features/virtual-accounts/main/api/src/main/kotlin/com/tangem/features/virtualaccount/main/component/VirtualAccountMainBlockComponent.kt b/features/virtual-accounts/main/api/src/main/kotlin/com/tangem/features/virtualaccount/main/component/VirtualAccountMainBlockComponent.kt new file mode 100644 index 0000000000..faa959dddf --- /dev/null +++ b/features/virtual-accounts/main/api/src/main/kotlin/com/tangem/features/virtualaccount/main/component/VirtualAccountMainBlockComponent.kt @@ -0,0 +1,19 @@ +package com.tangem.features.virtualaccount.main.component + +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.runtime.Stable +import androidx.compose.ui.Modifier +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM + +@Stable +interface VirtualAccountMainBlockComponent { + + fun LazyListScope.virtualAccountMainContent( + state: VirtualAccountMainUM, + isBalanceHidden: Boolean, + modifier: Modifier = Modifier, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/features/virtual-accounts/main/api/src/main/kotlin/com/tangem/features/virtualaccount/main/entity/VirtualAccountMainUM.kt b/features/virtual-accounts/main/api/src/main/kotlin/com/tangem/features/virtualaccount/main/entity/VirtualAccountMainUM.kt new file mode 100644 index 0000000000..1050d8d186 --- /dev/null +++ b/features/virtual-accounts/main/api/src/main/kotlin/com/tangem/features/virtualaccount/main/entity/VirtualAccountMainUM.kt @@ -0,0 +1,31 @@ +package com.tangem.features.virtualaccount.main.entity + +import androidx.compose.runtime.Immutable +import com.tangem.core.ui.extensions.TextReference + +/** + * UI model for the Virtual Account main-screen block. + * + * Mirrors `TangemPayMainUM` but carries virtual-account-specific states (no card-related variants). + */ +@Immutable +sealed class VirtualAccountMainUM { + + data object Empty : VirtualAccountMainUM() + data object Loading : VirtualAccountMainUM() + data class UnderReview(val subtitle: TextReference, val onClick: () -> Unit) : VirtualAccountMainUM() + data class Provisioning(val onClick: () -> Unit) : VirtualAccountMainUM() + data class CountryNotSupported(val onClick: () -> Unit) : VirtualAccountMainUM() + data class Content( + val subtitle: TextReference, + val isBalanceFlickering: Boolean, + val balance: TextReference, + val balanceSubtitle: TextReference, + val onClick: () -> Unit, + val shouldShowOnlyCacheWarning: Boolean, + ) : VirtualAccountMainUM() + + data object TemporaryUnavailable : VirtualAccountMainUM() + data object SyncNeeded : VirtualAccountMainUM() + data object ExposedDevice : VirtualAccountMainUM() +} \ No newline at end of file diff --git a/features/virtual-accounts/main/impl/build.gradle.kts b/features/virtual-accounts/main/impl/build.gradle.kts index e7c483cb69..91a30582f6 100644 --- a/features/virtual-accounts/main/impl/build.gradle.kts +++ b/features/virtual-accounts/main/impl/build.gradle.kts @@ -1,6 +1,8 @@ plugins { alias(deps.plugins.android.library) alias(deps.plugins.kotlin.android) + alias(deps.plugins.kotlin.kapt) + alias(deps.plugins.hilt.android) id("configuration") } @@ -9,4 +11,24 @@ android { } dependencies { + /** Core */ + implementation(projects.core.decompose) + implementation(projects.core.res) + implementation(projects.core.ui) + + /** Common */ + implementation(projects.common.ui) + + /** Features api */ + implementation(projects.features.virtualAccounts.main.api) + + /** Compose */ + implementation(deps.compose.foundation) + implementation(deps.compose.material3) + implementation(deps.compose.ui) + implementation(deps.compose.ui.tooling) + + /** DI */ + implementation(deps.hilt.android) + kapt(deps.hilt.kapt) } \ No newline at end of file diff --git a/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/component/DefaultVirtualAccountMainBlockComponent.kt b/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/component/DefaultVirtualAccountMainBlockComponent.kt new file mode 100644 index 0000000000..40af817f8c --- /dev/null +++ b/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/component/DefaultVirtualAccountMainBlockComponent.kt @@ -0,0 +1,42 @@ +package com.tangem.features.virtualaccount.main.component + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.ui.Modifier +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM +import com.tangem.features.virtualaccount.main.ui.VirtualAccountMainBlockContent +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +private const val VIRTUAL_ACCOUNT_CONTENT_TYPE = "VirtualAccount" + +@Suppress("UnusedPrivateProperty") +internal class DefaultVirtualAccountMainBlockComponent @AssistedInject constructor( + @Assisted context: AppComponentContext, + @Assisted params: Unit, +) : VirtualAccountMainBlockComponent, AppComponentContext by context { + + override fun LazyListScope.virtualAccountMainContent( + state: VirtualAccountMainUM, + isBalanceHidden: Boolean, + modifier: Modifier, + ) { + item( + key = VIRTUAL_ACCOUNT_CONTENT_TYPE, + contentType = VIRTUAL_ACCOUNT_CONTENT_TYPE, + ) { + VirtualAccountMainBlockContent( + state = state, + isBalanceHidden = isBalanceHidden, + modifier = modifier.animateContentSize(), + ) + } + } + + @AssistedFactory + interface Factory : VirtualAccountMainBlockComponent.Factory { + override fun create(context: AppComponentContext, params: Unit): DefaultVirtualAccountMainBlockComponent + } +} \ No newline at end of file diff --git a/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/di/VirtualAccountMainModule.kt b/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/di/VirtualAccountMainModule.kt new file mode 100644 index 0000000000..ce1f344d7e --- /dev/null +++ b/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/di/VirtualAccountMainModule.kt @@ -0,0 +1,17 @@ +package com.tangem.features.virtualaccount.main.di + +import com.tangem.features.virtualaccount.main.component.DefaultVirtualAccountMainBlockComponent +import com.tangem.features.virtualaccount.main.component.VirtualAccountMainBlockComponent +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent + +@Module +@InstallIn(SingletonComponent::class) +internal interface VirtualAccountMainModule { + @Binds + fun bindVirtualAccountMainBlockComponent( + factory: DefaultVirtualAccountMainBlockComponent.Factory, + ): VirtualAccountMainBlockComponent.Factory +} \ No newline at end of file diff --git a/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/ui/VirtualAccountMainBlockContent.kt b/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/ui/VirtualAccountMainBlockContent.kt new file mode 100644 index 0000000000..418e81bcb9 --- /dev/null +++ b/features/virtual-accounts/main/impl/src/main/kotlin/com/tangem/features/virtualaccount/main/ui/VirtualAccountMainBlockContent.kt @@ -0,0 +1,284 @@ +package com.tangem.features.virtualaccount.main.ui + +import android.content.res.Configuration +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider +import androidx.compose.ui.unit.dp +import com.tangem.common.ui.account.AccountIcon +import com.tangem.common.ui.account.AccountIconUM +import com.tangem.core.ui.components.CircleShimmer +import com.tangem.core.ui.components.TextShimmer +import com.tangem.core.ui.components.account.AccountIconSize +import com.tangem.core.ui.components.text.applyBladeBrush +import com.tangem.core.ui.ds.row.TangemRowContainer +import com.tangem.core.ui.ds.row.TangemRowLayoutId +import com.tangem.core.ui.extensions.* +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreviewRedesign +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM +import com.tangem.utils.StringsSigns.DASH_SIGN +import com.tangem.core.ui.R as CoreUiR + +@Composable +internal fun VirtualAccountMainBlockContent( + state: VirtualAccountMainUM, + isBalanceHidden: Boolean, + modifier: Modifier = Modifier, +) { + when (state) { + is VirtualAccountMainUM.Empty -> Unit + is VirtualAccountMainUM.Loading -> VirtualAccountMainLoading(modifier) + is VirtualAccountMainUM.UnderReview -> VirtualAccountStateRow( + subtitle = state.subtitle, + modifier = modifier, + onClick = state.onClick, + ) + is VirtualAccountMainUM.Provisioning -> VirtualAccountStateRow( + subtitle = stringReference("Setting up your account"), + modifier = modifier, + onClick = state.onClick, + ) + is VirtualAccountMainUM.CountryNotSupported -> VirtualAccountStateRow( + subtitle = stringReference("Not available in your region"), + modifier = modifier, + onClick = state.onClick, + ) + is VirtualAccountMainUM.Content -> VirtualAccountMainContent(state, isBalanceHidden, modifier) + is VirtualAccountMainUM.TemporaryUnavailable -> VirtualAccountStateRow( + subtitle = stringReference(DASH_SIGN), + modifier = modifier, + isEnabled = false, + ) + is VirtualAccountMainUM.SyncNeeded -> VirtualAccountStateRow( + subtitle = stringReference("Virtual account session expired"), + modifier = modifier, + isEnabled = false, + ) + is VirtualAccountMainUM.ExposedDevice -> VirtualAccountStateRow( + subtitle = stringReference("Unable to use on rooted devices"), + modifier = modifier, + ) + } +} + +@Composable +private fun VirtualAccountMainContent( + state: VirtualAccountMainUM.Content, + isBalanceHidden: Boolean, + modifier: Modifier = Modifier, +) { + TangemRowContainer( + modifier = modifier + .clip(RoundedCornerShape(size = 18.dp)) + .background(TangemTheme.colors2.surface.level3) + .clickableSingle(onClick = state.onClick), + ) { + AccountIcon( + name = TextReference.EMPTY, + icon = AccountIconUM.Virtual, + size = AccountIconSize.RedesignedDefault, + modifier = Modifier + .layoutId(TangemRowLayoutId.HEAD) + .padding(end = TangemTheme.dimens2.x2), + ) + Text( + text = "Virtual account", + color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography2.bodySemibold16, + modifier = Modifier.layoutId(TangemRowLayoutId.START_TOP), + ) + Text( + text = state.subtitle.resolveReference(), + color = TangemTheme.colors2.text.neutral.secondary, + style = TangemTheme.typography2.captionSemibold12, + modifier = Modifier.layoutId(TangemRowLayoutId.START_BOTTOM), + ) + VirtualAccountFiatAmount( + text = state.balance.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(), + isBalanceFlickering = state.isBalanceFlickering, + isBalanceFromCache = state.shouldShowOnlyCacheWarning, + modifier = Modifier.layoutId(TangemRowLayoutId.END_TOP), + ) + Text( + text = state.balanceSubtitle.resolveReference(), + color = TangemTheme.colors2.text.neutral.secondary, + style = TangemTheme.typography2.captionSemibold12, + modifier = Modifier.layoutId(TangemRowLayoutId.END_BOTTOM), + ) + } +} + +@Composable +private fun VirtualAccountStateRow( + subtitle: TextReference, + modifier: Modifier = Modifier, + onClick: (() -> Unit)? = null, + isEnabled: Boolean = true, +) { + TangemRowContainer( + modifier = modifier + .clip(RoundedCornerShape(size = 18.dp)) + .background(TangemTheme.colors2.surface.level3) + .conditional(onClick != null && isEnabled) { clickableSingle(onClick = requireNotNull(onClick)) }, + ) { + AccountIcon( + name = TextReference.EMPTY, + icon = AccountIconUM.Virtual, + size = AccountIconSize.RedesignedDefault, + modifier = Modifier + .layoutId(TangemRowLayoutId.HEAD) + .padding(end = TangemTheme.dimens2.x2), + ) + Text( + text = "Virtual account", + color = if (isEnabled) { + TangemTheme.colors2.text.neutral.primary + } else { + TangemTheme.colors2.text.status.disabled + }, + style = TangemTheme.typography2.bodySemibold16, + modifier = Modifier.layoutId(TangemRowLayoutId.START_TOP), + ) + Text( + text = subtitle.resolveReference(), + color = if (isEnabled) { + TangemTheme.colors2.text.neutral.secondary + } else { + TangemTheme.colors2.text.status.disabled + }, + style = TangemTheme.typography2.captionSemibold12, + modifier = Modifier.layoutId(TangemRowLayoutId.START_BOTTOM), + ) + } +} + +@Composable +private fun VirtualAccountFiatAmount( + text: AnnotatedString, + isBalanceFlickering: Boolean, + isBalanceFromCache: Boolean, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + ) { + AnimatedVisibility(isBalanceFromCache) { + Row( + modifier = Modifier.padding(horizontal = 4.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + Icon( + modifier = Modifier.size(12.dp), + painter = painterResource(CoreUiR.drawable.ic_error_sync_24), + tint = TangemTheme.colors2.graphic.neutral.secondary, + contentDescription = null, + ) + } + } + + Text( + text = text, + style = TangemTheme.typography2.bodySemibold16.applyBladeBrush( + isEnabled = isBalanceFlickering, + textColor = TangemTheme.colors2.text.neutral.primary, + ), + textAlign = TextAlign.End, + ) + } +} + +@Composable +private fun VirtualAccountMainLoading(modifier: Modifier = Modifier) { + TangemRowContainer( + modifier = modifier + .clip(RoundedCornerShape(size = 18.dp)) + .background(TangemTheme.colors2.surface.level3), + ) { + CircleShimmer( + modifier = Modifier + .layoutId(TangemRowLayoutId.HEAD) + .padding(end = TangemTheme.dimens2.x2) + .size(TangemTheme.dimens2.x10), + ) + TextShimmer( + style = TangemTheme.typography2.bodySemibold16, + radius = TangemTheme.dimens2.x25, + modifier = Modifier + .layoutId(TangemRowLayoutId.START_TOP) + .width(TangemTheme.dimens2.x25), + ) + TextShimmer( + style = TangemTheme.typography2.captionSemibold12, + radius = TangemTheme.dimens2.x25, + modifier = Modifier + .layoutId(TangemRowLayoutId.START_BOTTOM) + .width(TangemTheme.dimens2.x11), + ) + TextShimmer( + style = TangemTheme.typography2.bodyRegular16, + radius = TangemTheme.dimens2.x25, + modifier = Modifier + .layoutId(TangemRowLayoutId.END_TOP) + .width(TangemTheme.dimens2.x20), + ) + TextShimmer( + style = TangemTheme.typography2.bodyRegular16, + radius = TangemTheme.dimens2.x25, + modifier = Modifier + .layoutId(TangemRowLayoutId.END_BOTTOM) + .width(TangemTheme.dimens2.x11), + ) + } +} + +// region Preview +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun VirtualAccountMainBlockContent_Preview( + @PreviewParameter(VirtualAccountMainBlockContentPreviewParameterProvider::class) + state: VirtualAccountMainUM, +) { + TangemThemePreviewRedesign { + VirtualAccountMainBlockContent(state = state, isBalanceHidden = false) + } +} + +private class VirtualAccountMainBlockContentPreviewParameterProvider : + CollectionPreviewParameterProvider( + collection = listOf( + VirtualAccountMainUM.Loading, + VirtualAccountMainUM.SyncNeeded, + VirtualAccountMainUM.TemporaryUnavailable, + VirtualAccountMainUM.ExposedDevice, + VirtualAccountMainUM.Provisioning(onClick = {}), + VirtualAccountMainUM.CountryNotSupported(onClick = {}), + VirtualAccountMainUM.UnderReview(subtitle = TextReference.Str("KYC in progress"), onClick = {}), + VirtualAccountMainUM.Content( + subtitle = TextReference.Str("USDC"), + isBalanceFlickering = true, + balance = TextReference.Str("$ 101.56"), + balanceSubtitle = TextReference.Str("USDC"), + onClick = {}, + shouldShowOnlyCacheWarning = true, + ), + ), + ) +// endregion \ No newline at end of file diff --git a/features/wallet/impl/build.gradle.kts b/features/wallet/impl/build.gradle.kts index 5e5d98d1d6..9e06c9a21b 100644 --- a/features/wallet/impl/build.gradle.kts +++ b/features/wallet/impl/build.gradle.kts @@ -153,6 +153,7 @@ dependencies { implementation(projects.features.promoBanners.api) implementation(projects.features.tangempay.main.api) implementation(projects.features.tangempay.details.api) + implementation(projects.features.virtualAccounts.main.api) /** Common modules */ implementation(projects.common) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/WalletComponent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/WalletComponent.kt index 3c96432264..724052b15f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/WalletComponent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/WalletComponent.kt @@ -26,7 +26,6 @@ import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.feature.wallet.child.managetokens.AddAndManageBottomSheetComponent import com.tangem.feature.wallet.child.organizetokens.OrganizeTokensComponent import com.tangem.features.commonfeatures.api.addfunds.AddFundsComponent -import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorComponent import com.tangem.feature.wallet.child.tokenActions.DefaultTokenActionsComponent import com.tangem.feature.wallet.child.tokenActions.TokenActionsComponent import com.tangem.feature.wallet.child.wallet.model.WalletModel @@ -37,6 +36,7 @@ import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen2 import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejectedComponent import com.tangem.feature.walletsettings.component.RenameWalletComponent import com.tangem.features.biometry.AskBiometryComponent +import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorComponent import com.tangem.features.feed.entry.components.FeedEntryComponent import com.tangem.features.promobanners.api.PromoBannersBlockComponent import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent @@ -45,6 +45,7 @@ import com.tangem.features.send.api.NetworkSelectionComponent import com.tangem.features.tangempay.component.TangemPayMainBlockComponent import com.tangem.features.tangempay.components.TangemPayTransactionBottomSheetComponent import com.tangem.features.tokenreceive.TokenReceiveComponent +import com.tangem.features.virtualaccount.main.component.VirtualAccountMainBlockComponent import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -58,6 +59,7 @@ internal class WalletComponent @AssistedInject constructor( @Assisted navigate: (WalletRoute) -> Unit, feedEntryComponentFactory: FeedEntryComponent.Factory, tangemPayMainBlockComponentFactory: TangemPayMainBlockComponent.Factory, + virtualAccountMainBlockComponentFactory: VirtualAccountMainBlockComponent.Factory, private val tangemPayTransactionBottomSheetComponentFactory: TangemPayTransactionBottomSheetComponent.Factory, private val renameWalletComponentFactory: RenameWalletComponent.Factory, private val askBiometryComponentFactory: AskBiometryComponent.Factory, @@ -86,6 +88,12 @@ internal class WalletComponent @AssistedInject constructor( params = Unit, ) } + private val virtualAccountMainBlockComponent by lazy { + virtualAccountMainBlockComponentFactory.create( + context = child("virtualAccountMainBlockComponent"), + params = Unit, + ) + } private val promoBannersBlockComponent: PromoBannersBlockComponent by lazy { promoBannersBlockComponentFactory.create( @@ -282,6 +290,7 @@ internal class WalletComponent @AssistedInject constructor( WalletScreen2( state = uiState, tangemPayComponent = tangemPayMainBlockComponent, + virtualAccountComponent = virtualAccountMainBlockComponent, bottomSheetContent = { onExpandSheet -> BottomSheetContent( bottomSheetState = bottomSheetState, @@ -298,6 +307,7 @@ internal class WalletComponent @AssistedInject constructor( state = uiState, promoBannersBlockComponent = promoBannersBlockComponent, tangemPayComponent = tangemPayMainBlockComponent, + virtualAccountComponent = virtualAccountMainBlockComponent, bottomSheetContent = { onExpandSheet -> BottomSheetContent( bottomSheetState = bottomSheetState, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt index b98fa31b13..dc74a14fe9 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt @@ -19,6 +19,7 @@ import com.tangem.feature.wallet.presentation.preview.WalletBalancePreview import com.tangem.feature.wallet.presentation.preview.WalletPreviewData import com.tangem.feature.wallet.presentation.wallet.state.model.* import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM import kotlinx.collections.immutable.persistentListOf internal object WalletScreenPreviewData { @@ -179,6 +180,7 @@ internal object WalletScreenPreviewData { onItemClick = {}, ), tangemPayMainUM = TangemPayMainUM.Loading, + virtualAccountMainUM = VirtualAccountMainUM.Loading, ) private val walletEmpty = WalletUM.Content( @@ -194,6 +196,7 @@ internal object WalletScreenPreviewData { tokensListUM = WalletTokensListUM.Empty(onEmptyClick = {}), nftState = WalletNFTItemUM.Hidden, tangemPayMainUM = TangemPayMainUM.Empty, + virtualAccountMainUM = VirtualAccountMainUM.Empty, ) private val walletAccountDefault = walletDefault.copy( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletState.kt index 6ee912f8fc..769401d0c9 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletState.kt @@ -11,6 +11,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.holder.LockedWa import com.tangem.feature.wallet.presentation.wallet.state.model.holder.TxHistoryStateHolder import com.tangem.feature.wallet.presentation.wallet.state.model.holder.WalletStateHolder import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.PersistentList @@ -25,6 +26,7 @@ internal sealed interface WalletState : WalletStateHolder { abstract val nftState: WalletNFTItemUM abstract val type: WalletType abstract val tangemPayMainUM: TangemPayMainUM + abstract val virtualAccountMainUM: VirtualAccountMainUM abstract val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM data class Content( @@ -37,6 +39,7 @@ internal sealed interface WalletState : WalletStateHolder { override val nftState: WalletNFTItemUM, override val type: WalletType, override val tangemPayMainUM: TangemPayMainUM, + override val virtualAccountMainUM: VirtualAccountMainUM = VirtualAccountMainUM.Empty, override val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle, ) : MultiCurrency() @@ -57,6 +60,7 @@ internal sealed interface WalletState : WalletStateHolder { override val tokensListState = WalletTokensListState.ContentState.Locked override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty + override val virtualAccountMainUM: VirtualAccountMainUM = VirtualAccountMainUM.Empty override val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletUM.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletUM.kt index fd25cf396e..907a2a76fa 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletUM.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletUM.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig import com.tangem.core.ui.ds.button.TangemButtonUM import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf @@ -26,6 +27,8 @@ internal sealed interface WalletUM { val tangemPayMainUM: TangemPayMainUM + val virtualAccountMainUM: VirtualAccountMainUM + data class Content( override val pullToRefreshConfig: PullToRefreshConfig, override val walletsBalanceUM: WalletBalanceUM, @@ -36,6 +39,7 @@ internal sealed interface WalletUM { override val nftState: WalletNFTItemUM, override val type: WalletType, override val tangemPayMainUM: TangemPayMainUM, + override val virtualAccountMainUM: VirtualAccountMainUM, ) : WalletUM data class Locked( @@ -49,5 +53,6 @@ internal sealed interface WalletUM { override val tokensListUM: WalletTokensListUM = WalletTokensListUM.Locked override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty + override val virtualAccountMainUM: VirtualAccountMainUM = VirtualAccountMainUM.Empty } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt index 17f7d3238e..12f45f5b42 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt @@ -12,6 +12,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.converte import com.tangem.feature.wallet.presentation.wallet.state.utils.disableButtons import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM import com.tangem.utils.logging.TangemLogger import java.math.BigDecimal @@ -36,6 +37,12 @@ internal class SetTokenListTransformer( ) } + private val virtualAccountConverter by lazy { + VirtualAccountMainBlockConverter( + isRedesignEnabled = isRedesignEnabled, + ) + } + override fun transform(prevState: WalletState): WalletState { return when (prevState) { is WalletState.MultiCurrency.Content -> { @@ -43,6 +50,7 @@ internal class SetTokenListTransformer( walletCardState = prevState.walletCardState.toLoadedState(), tokensListState = prevState.tokensListState.toLoadedState(), tangemPayMainUM = prevState.tangemPayMainUM.toLoadedState(), + virtualAccountMainUM = prevState.virtualAccountMainUM.toLoadedVirtualState(), buttons = prevState.enableButtons(), ) } @@ -65,6 +73,7 @@ internal class SetTokenListTransformer( walletUM.copy( walletsBalanceUM = walletUM.walletsBalanceUM.toLoadedState2(), tangemPayMainUM = walletUM.tangemPayMainUM.toLoadedState(), + virtualAccountMainUM = walletUM.virtualAccountMainUM.toLoadedVirtualState(), tokensListUM = tokensListUM, buttons = if (tokensListUM is WalletTokensListUM.Empty) { walletUM.disableButtons() @@ -127,6 +136,17 @@ internal class SetTokenListTransformer( return tangemPayConverter.convert(paymentAccountStatus) } + private fun VirtualAccountMainUM.toLoadedVirtualState(): VirtualAccountMainUM { + val virtualAccountStatus = when (params) { + is TokenConverterParams.Account -> params.accountList.accountStatuses + .filterIsInstance() + .firstOrNull() + is TokenConverterParams.Wallet -> return VirtualAccountMainUM.Empty + } ?: return this + + return virtualAccountConverter.convert(virtualAccountStatus) + } + private fun toLoadedState(): WalletTokensListUM { if (params !is TokenConverterParams.Account) { return WalletTokensListUM.Empty( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VirtualAccountMainBlockConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VirtualAccountMainBlockConverter.kt new file mode 100644 index 0000000000..3d6eeccfc1 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VirtualAccountMainBlockConverter.kt @@ -0,0 +1,86 @@ +package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter + +import androidx.compose.ui.text.SpanStyle +import com.tangem.common.ui.R +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.format.bigdecimal.fiat +import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.core.ui.format.bigdecimal.formatStyled +import com.tangem.core.ui.format.bigdecimal.getJavaCurrencyByCode +import com.tangem.core.ui.res.TangemTheme +import com.tangem.domain.models.StatusSource +import com.tangem.domain.models.account.AccountStatus +import com.tangem.domain.models.account.VirtualAccountStatusValue +import com.tangem.domain.models.kyc.KycStatus +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM +import com.tangem.utils.converter.Converter +import java.math.BigDecimal + +internal class VirtualAccountMainBlockConverter( + private val isRedesignEnabled: Boolean, +) : Converter { + + override fun convert(value: AccountStatus.Virtual): VirtualAccountMainUM { + return when (val statusValue = value.value) { + is VirtualAccountStatusValue.Empty -> VirtualAccountMainUM.Empty + is VirtualAccountStatusValue.NotCreated -> VirtualAccountMainUM.Empty + is VirtualAccountStatusValue.Loading -> VirtualAccountMainUM.Loading + is VirtualAccountStatusValue.UnderReview -> VirtualAccountMainUM.UnderReview( + subtitle = when (statusValue.kycStatus) { + KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed) + else -> TextReference.Res(R.string.tangempay_kyc_in_progress) + }, + onClick = { + // TODO([REDACTED_TASK_KEY]): navigate to VA screen + }, + ) + is VirtualAccountStatusValue.Provisioning -> VirtualAccountMainUM.Provisioning( + onClick = { + // TODO([REDACTED_TASK_KEY]): navigate to VA screen + }, + ) + is VirtualAccountStatusValue.CountryNotSupported -> VirtualAccountMainUM.CountryNotSupported( + onClick = { + // TODO([REDACTED_TASK_KEY]): navigate to VA screen + }, + ) + is VirtualAccountStatusValue.Active -> VirtualAccountMainUM.Content( + subtitle = stringReference(statusValue.cryptoCurrency.symbol), + isBalanceFlickering = statusValue.source == StatusSource.CACHE, + balance = getBalanceText( + currencyCode = statusValue.fiatBalance.currency, + balance = statusValue.fiatBalance.availableBalance, + ), + balanceSubtitle = stringReference(statusValue.cryptoCurrency.symbol), + shouldShowOnlyCacheWarning = statusValue.source == StatusSource.ONLY_CACHE, + onClick = { + // TODO([REDACTED_TASK_KEY]): navigate to VA screen + }, + ) + is VirtualAccountStatusValue.Error.Unavailable -> VirtualAccountMainUM.TemporaryUnavailable + is VirtualAccountStatusValue.Error.NotSynced -> VirtualAccountMainUM.SyncNeeded + is VirtualAccountStatusValue.Error.ExposedDevice -> VirtualAccountMainUM.ExposedDevice + } + } + + private fun getBalanceText(currencyCode: String, balance: BigDecimal): TextReference { + val currency = getJavaCurrencyByCode(currencyCode) + val formattedBalance = if (isRedesignEnabled) { + balance.formatStyled { + fiat( + fiatCurrencyCode = currency.currencyCode, + fiatCurrencySymbol = currency.symbol, + spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) }, + ) + } + } else { + stringReference( + balance.format { + fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol) + }, + ) + } + return formattedBalance + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt index 51f9bfe3ed..08d096da53 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt @@ -18,6 +18,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfo import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver import com.tangem.feature.wallet.presentation.wallet.state.model.* import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM import com.tangem.utils.extensions.addIf import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.PersistentList @@ -70,6 +71,7 @@ internal class WalletLoadingStateFactory( is UserWallet.Hot -> WalletType.Hot }, tangemPayMainUM = TangemPayMainUM.Empty, + virtualAccountMainUM = VirtualAccountMainUM.Empty, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index b3b103e1f9..3b467d4542 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -85,15 +85,19 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrenc import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator import com.tangem.features.tangempay.component.TangemPayMainBlockComponent import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.component.VirtualAccountMainBlockComponent +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlin.math.roundToInt +@Suppress("LongParameterList") @Composable internal fun WalletScreen( state: WalletScreenState, tangemPayComponent: TangemPayMainBlockComponent, + virtualAccountComponent: VirtualAccountMainBlockComponent, promoBannersBlockComponent: ComposableContentComponent? = null, bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit, bottomSheetHeaderHeightProvider: () -> Dp, @@ -109,6 +113,7 @@ internal fun WalletScreen( WalletContent( state = state, tangemPayComponent = tangemPayComponent, + virtualAccountComponent = virtualAccountComponent, walletsListState = walletsListState, snackbarHostState = snackbarHostState, isAutoScroll = isAutoScroll, @@ -132,6 +137,7 @@ internal fun WalletScreen( private fun WalletContent( state: WalletScreenState, tangemPayComponent: TangemPayMainBlockComponent, + virtualAccountComponent: VirtualAccountMainBlockComponent, walletsListState: LazyListState, snackbarHostState: SnackbarHostState, isAutoScroll: State, @@ -231,6 +237,13 @@ private fun WalletContent( tangemPayComponent = tangemPayComponent, ) + virtualAccountItem( + modifier = itemModifier, + state = selectedWallet, + isHidingMode = state.isHidingMode, + virtualAccountComponent = virtualAccountComponent, + ) + (selectedWallet as? WalletState.SingleCurrency)?.let { walletState -> walletState.marketPriceBlockState?.let { marketPriceBlockState -> marketPriceBlock(state = marketPriceBlockState, modifier = itemModifier) @@ -758,6 +771,23 @@ internal fun LazyListScope.tangemPayItem( } } +internal fun LazyListScope.virtualAccountItem( + state: WalletState, + isHidingMode: Boolean, + virtualAccountComponent: VirtualAccountMainBlockComponent, + modifier: Modifier = Modifier, +) { + if (state !is WalletState.MultiCurrency) return + + with(virtualAccountComponent) { + virtualAccountMainContent( + modifier = modifier, + state = state.virtualAccountMainUM, + isBalanceHidden = isHidingMode, + ) + } +} + @Composable private fun ShowBottomSheet(bottomSheetConfig: TangemBottomSheetConfig?) { if (bottomSheetConfig != null) { @@ -784,6 +814,14 @@ private fun WalletScreen_Preview(@PreviewParameter(WalletScreenPreviewProvider:: ) { } }, + virtualAccountComponent = object : VirtualAccountMainBlockComponent { + override fun LazyListScope.virtualAccountMainContent( + state: VirtualAccountMainUM, + isBalanceHidden: Boolean, + modifier: Modifier, + ) { + } + }, bottomSheetContent = { Text("Markets Content") }, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt index 304af18a54..9d5c452aa7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt @@ -75,6 +75,8 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.common.Wallet import com.tangem.feature.wallet.presentation.wallet.ui.utils.lazyListStateMapSaver import com.tangem.features.tangempay.component.TangemPayMainBlockComponent import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.component.VirtualAccountMainBlockComponent +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM import dev.chrisbanes.haze.HazeProgressive import dev.chrisbanes.haze.HazeTint import kotlinx.coroutines.launch @@ -83,10 +85,12 @@ import kotlin.math.abs private const val MARKET_HINT_THRESHOLD = 0.5f @OptIn(ExperimentalDecomposeApi::class) +@Suppress("LongParameterList") @Composable internal fun WalletScreen2( state: WalletScreenState, tangemPayComponent: TangemPayMainBlockComponent, + virtualAccountComponent: VirtualAccountMainBlockComponent, modifier: Modifier = Modifier, bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit, bottomSheetHeaderHeightProvider: () -> Dp, @@ -132,6 +136,7 @@ internal fun WalletScreen2( state = state, walletsPagerState = walletsPagerState, tangemPayComponent = tangemPayComponent, + virtualAccountComponent = virtualAccountComponent, behavior = behavior, bottomSheetContent = bottomSheetContent, bottomSheetHeaderHeightProvider = bottomSheetHeaderHeightProvider, @@ -159,6 +164,7 @@ private fun WalletContent2( state: WalletScreenState, walletsPagerState: PagerState, tangemPayComponent: TangemPayMainBlockComponent, + virtualAccountComponent: VirtualAccountMainBlockComponent, behavior: TangemCollapsingAppBarBehavior, listStates: Map, modifier: Modifier = Modifier, @@ -330,6 +336,7 @@ private fun WalletContent2( isBalanceHidden = state.isHidingMode, contentPadding = contentPadding, tangemPayComponent = tangemPayComponent, + virtualAccountComponent = virtualAccountComponent, modifier = Modifier .fillMaxSize() .nestedScroll(behavior.nestedScrollConnection), @@ -655,6 +662,14 @@ private fun WalletScreen2_Preview(@PreviewParameter(WalletScreen2PreviewProvider ) { } }, + virtualAccountComponent = object : VirtualAccountMainBlockComponent { + override fun LazyListScope.virtualAccountMainContent( + state: VirtualAccountMainUM, + isBalanceHidden: Boolean, + modifier: Modifier, + ) { + } + }, bottomSheetContent = { Text("Markets Content") }, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletItemBlocks.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletItemBlocks.kt index 809832496e..05924d40c5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletItemBlocks.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletItemBlocks.kt @@ -10,6 +10,8 @@ import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM import com.tangem.features.tangempay.component.TangemPayMainBlockComponent import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.component.VirtualAccountMainBlockComponent +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM internal fun LazyListScope.nftCollections2(state: WalletUM, itemModifier: Modifier) { (state as? WalletUM.Content)?.let { content -> @@ -51,4 +53,15 @@ internal fun LazyListScope.tangemPay( with(tangemPayComponent) { tangemPayMainContent(modifier = modifier, state = tangemPayUM, isBalanceHidden = isBalanceHidden) } +} + +internal fun LazyListScope.virtualAccount( + virtualAccountComponent: VirtualAccountMainBlockComponent, + virtualAccountUM: VirtualAccountMainUM, + isBalanceHidden: Boolean, + modifier: Modifier = Modifier, +) { + with(virtualAccountComponent) { + virtualAccountMainContent(modifier = modifier, state = virtualAccountUM, isBalanceHidden = isBalanceHidden) + } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt index d3d84ed899..e3bcda5ec0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt @@ -24,15 +24,19 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency import com.tangem.feature.wallet.presentation.wallet.ui.components.nftCollections2 import com.tangem.feature.wallet.presentation.wallet.ui.components.organizeTokens2 import com.tangem.feature.wallet.presentation.wallet.ui.components.tangemPay +import com.tangem.feature.wallet.presentation.wallet.ui.components.virtualAccount import com.tangem.features.tangempay.component.TangemPayMainBlockComponent +import com.tangem.features.virtualaccount.main.component.VirtualAccountMainBlockComponent import kotlinx.collections.immutable.toPersistentList +@Suppress("LongParameterList") @Composable internal fun WalletListContent( currentWallet: WalletUM, isBalanceHidden: Boolean, listState: LazyListState, tangemPayComponent: TangemPayMainBlockComponent, + virtualAccountComponent: VirtualAccountMainBlockComponent, contentPadding: PaddingValues, modifier: Modifier = Modifier, ) { @@ -66,6 +70,13 @@ internal fun WalletListContent( modifier = itemModifier, ) + virtualAccount( + virtualAccountComponent = virtualAccountComponent, + virtualAccountUM = currentWallet.virtualAccountMainUM, + isBalanceHidden = isBalanceHidden, + modifier = itemModifier, + ) + tokensListItems2( walletTokensListUM = currentWallet.tokensListUM, modifier = movableItemModifier, diff --git a/features/wallet/impl/src/test/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformerTest.kt b/features/wallet/impl/src/test/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformerTest.kt index 9472894a06..c4cc530219 100644 --- a/features/wallet/impl/src/test/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformerTest.kt +++ b/features/wallet/impl/src/test/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformerTest.kt @@ -26,6 +26,7 @@ import com.tangem.domain.models.wallet.UserWalletId import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents import com.tangem.feature.wallet.presentation.wallet.state.model.* import com.tangem.features.tangempay.entity.TangemPayMainUM +import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM import io.mockk.every import io.mockk.mockk import kotlinx.collections.immutable.persistentListOf @@ -133,6 +134,7 @@ class SetTokenListTransformerTest { nftState = WalletNFTItemUM.Hidden, type = WalletType.Hot, tangemPayMainUM = TangemPayMainUM.Empty, + virtualAccountMainUM = VirtualAccountMainUM.Empty, ) private fun createToken(): CryptoCurrency.Token {