From f74c37a080392697ea8a67654377f04bd2c2af72 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 13 Jul 2026 02:20:35 -0700 Subject: [PATCH] Updated on 2026-08-14 --- .../pay/models/response/CustomerMeResponse.kt | 1 + .../entity/PaymentAccountStatusValueDM.kt | 7 +++ .../PaymentAccountStatusValueDMConverter.kt | 31 ++++++++++-- .../DefaultPaymentAccountStatusFetcher.kt | 2 + .../data/pay/util/CustomerInfoConverter.kt | 9 ++++ .../DefaultPaymentAccountStatusFetcherTest.kt | 1 + .../tangem/data/pay/flow/StableOrderTest.kt | 1 + .../tangem/domain/models/pay/TangemPayCard.kt | 13 +++-- .../tangem/domain/pay/model/CustomerInfo.kt | 2 + .../TangemPayCardDetailsBlockStateFactory.kt | 2 + .../entity/TangemPayDetailsStateFactory.kt | 2 + .../tangempay/entity/TangemPayDetailsUM.kt | 2 + .../TangemPayCardDetailsController.kt | 3 ++ .../tiers/select/TangemPaySelectPlanScreen.kt | 48 +++++++++---------- .../ui/TangemPayAddToWalletScreen.kt | 1 + .../ui/TangemPayAddToWalletScreenV2.kt | 1 + .../tangempay/ui/TangemPayCardDetailsBlock.kt | 25 +++++++++- .../tangempay/ui/TangemPayCardPageScreen.kt | 1 + .../tangempay/ui/TangemPayDetailsScreen.kt | 3 ++ .../tangempay/ui/TangemPayDetailsScreenV2.kt | 1 + .../ui/components/TangemPayCardView.kt | 33 +++++++++++-- .../tangempay/TangemPayTestFixtures.kt | 1 + .../setup/TangemPayCardLimitSetupModelTest.kt | 2 + .../TangemPayEditDisplayNameModelTest.kt | 1 + .../TangemPayCardDetailsControllerTest.kt | 1 + 25 files changed, 154 insertions(+), 40 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/pay/models/response/CustomerMeResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/pay/models/response/CustomerMeResponse.kt index 9b90eb277d..f7c7644e42 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/pay/models/response/CustomerMeResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/pay/models/response/CustomerMeResponse.kt @@ -165,5 +165,6 @@ data class CustomerMeResponse( @Json(name = "card_status") val cardStatus: String, @Json(name = "card_number_end") val cardNumberEnd: String, @Json(name = "is_pin_set") val isPinSet: Boolean?, + @Json(name = "images") val images: List?, ) } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/visa/entity/PaymentAccountStatusValueDM.kt b/core/datasource/src/main/java/com/tangem/datasource/local/visa/entity/PaymentAccountStatusValueDM.kt index 0aef21ab21..9344d05f6e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/visa/entity/PaymentAccountStatusValueDM.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/visa/entity/PaymentAccountStatusValueDM.kt @@ -93,6 +93,13 @@ sealed interface PaymentAccountStatusValueDM { @Json(name = "admin_daily_limit") val adminDailyLimit: SerializedBigDecimal?, @Json(name = "frozen_state") val frozenState: String, @Json(name = "last_digits") val lastDigits: String, + @Json(name = "images") val images: List, @Json(name = "state") val state: String, ) + + @JsonClass(generateAdapter = true) + data class ImageDM( + @Json(name = "type") val type: String, + @Json(name = "url") val url: String, + ) } \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverter.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverter.kt index 5f184ef3ce..f988866ea2 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverter.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverter.kt @@ -5,6 +5,7 @@ import com.tangem.datasource.local.visa.entity.PaymentAccountStatusValueDM import com.tangem.domain.models.StatusSource import com.tangem.domain.models.account.CardDisplayName import com.tangem.domain.models.account.PaymentAccountStatusValue +import com.tangem.domain.models.account.TangemPayTariffPlan import com.tangem.domain.models.pay.* import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.pay.TangemPayCurrencyFactory @@ -51,6 +52,12 @@ internal class PaymentAccountStatusValueDMConverter @Inject constructor( adminDailyLimit = card.limit?.adminCardLimit?.amount, frozenState = card.frozenState.toString(), lastDigits = card.lastDigits, + images = card.images.map { image -> + PaymentAccountStatusValueDM.ImageDM( + type = image.type.name, + url = image.url, + ) + }, state = card.state.toString(), ) }, @@ -91,11 +98,7 @@ internal class PaymentAccountStatusValueDMConverter @Inject constructor( source = StatusSource.CACHE, customerId = value.customerId, depositAddress = value.depositAddress, - balance = PaymentAccountStatusValue.Balance( - fiatBalance = value.fiatBalance.toDomain(), - cryptoBalance = value.cryptoBalance.toDomain(), - availableForWithdrawal = value.availableForWithdrawal, - ), + balance = value.getBalance(), cryptoCurrency = cryptoCurrency, fiatRate = value.fiatRate, cards = value.cards.map { card -> @@ -115,6 +118,7 @@ internal class PaymentAccountStatusValueDMConverter @Inject constructor( ), frozenState = TangemPayCardFrozenState.fromString(card.frozenState), lastDigits = card.lastDigits, + images = card.getImages(), state = TangemPayCardState.fromString(card.state), ) }, @@ -160,6 +164,14 @@ internal class PaymentAccountStatusValueDMConverter @Inject constructor( ) } + private fun PaymentAccountStatusValueDM.ActiveAccount.getBalance(): PaymentAccountStatusValue.Balance { + return PaymentAccountStatusValue.Balance( + fiatBalance = fiatBalance.toDomain(), + cryptoBalance = cryptoBalance.toDomain(), + availableForWithdrawal = availableForWithdrawal, + ) + } + private fun PaymentAccountStatusValueDM.FiatBalanceDM.toDomain(): PaymentAccountStatusValue.FiatBalance { return PaymentAccountStatusValue.FiatBalance( availableBalance = availableBalance, @@ -176,4 +188,13 @@ internal class PaymentAccountStatusValueDMConverter @Inject constructor( balance = balance, ) } + + private fun PaymentAccountStatusValueDM.TangemPayCard.getImages(): List { + return images.map { image -> + TangemPayTariffPlan.Image( + type = TangemPayTariffPlan.Image.Type.fromString(image.type), + url = image.url, + ) + } + } } \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/flow/DefaultPaymentAccountStatusFetcher.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/flow/DefaultPaymentAccountStatusFetcher.kt index a99062d362..6d932fd36b 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/flow/DefaultPaymentAccountStatusFetcher.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/flow/DefaultPaymentAccountStatusFetcher.kt @@ -360,6 +360,7 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor( productInstance.frozenState }, lastDigits = cardInfo.lastFourDigits, + images = cardInfo.images, state = getCardState(cardId, userWalletId), ) } @@ -509,6 +510,7 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor( limit = null, frozenState = TangemPayCardFrozenState.Unfrozen, lastDigits = "", + images = emptyList(), state = TangemPayCardState.Issuing, ) diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/util/CustomerInfoConverter.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/util/CustomerInfoConverter.kt index 60aeb7b986..81b291df0d 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/util/CustomerInfoConverter.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/util/CustomerInfoConverter.kt @@ -92,6 +92,15 @@ internal object CustomerInfoConverter : Converter, @SerialName("state") val state: TangemPayCardState, ) { - - /** Backend card status — unknown values map to [UNDEFINED] without crashing. */ @Serializable enum class Status { @SerialName("ACTIVE") @@ -65,4 +66,10 @@ data class TangemPayCard( } val TangemPayCard.isFrozen - get() = frozenState == TangemPayCardFrozenState.Frozen \ No newline at end of file + get() = frozenState == TangemPayCardFrozenState.Frozen + +val TangemPayCard.thumbnailUrl: String? + get() = images.firstOrNull { it.type == TangemPayTariffPlan.Image.Type.THUMBNAIL }?.url + +val TangemPayCard.mainImageUrl: String? + get() = images.firstOrNull { it.type == TangemPayTariffPlan.Image.Type.MAIN }?.url \ No newline at end of file diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/CustomerInfo.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/CustomerInfo.kt index c21292ea94..0a624312bc 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/CustomerInfo.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/CustomerInfo.kt @@ -3,6 +3,7 @@ package com.tangem.domain.pay.model import com.tangem.domain.models.account.CardDisplayName import com.tangem.domain.models.account.PaymentAccountStatusValue import com.tangem.domain.models.account.TangemPayCustomerTariffPlan +import com.tangem.domain.models.account.TangemPayTariffPlan import com.tangem.domain.models.kyc.KycStatus import com.tangem.domain.models.pay.TangemPayCard import com.tangem.domain.models.pay.TangemPayCardFrozenState @@ -103,5 +104,6 @@ data class CustomerInfo( val cardStatus: TangemPayCard.Status, val lastFourDigits: String, val isPinSet: Boolean, + val images: List, ) } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardDetailsBlockStateFactory.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardDetailsBlockStateFactory.kt index 51ffdfc7f1..faa00087e3 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardDetailsBlockStateFactory.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardDetailsBlockStateFactory.kt @@ -13,6 +13,7 @@ internal class TangemPayCardDetailsBlockStateFactory( private val displayName: CardDisplayName?, private val isEditingNameEnabled: Boolean, private val cardState: TangemPayCardState, + private val cardImageUrl: String?, private val onEditNameClick: () -> Unit, private val onReveal: () -> Unit, private val onCopy: (String, CardDataType) -> Unit, @@ -41,6 +42,7 @@ internal class TangemPayCardDetailsBlockStateFactory( }, shouldShowCardDetailsButtonOnCard = shouldShowCardDetailsButtonOnCard, cardState = cardState, + cardImageUrl = cardImageUrl, ) } } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt index dfda075cd1..7aff06b034 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt @@ -18,6 +18,7 @@ import com.tangem.domain.models.pay.TangemPayCard import com.tangem.domain.models.pay.TangemPayCardFrozenState import com.tangem.domain.models.pay.TangemPayCardState import com.tangem.domain.models.pay.isFrozen +import com.tangem.domain.models.pay.thumbnailUrl import com.tangem.features.tangempay.details.impl.R import com.tangem.features.tangempay.utils.TangemPayDetailIntents import com.tangem.features.tangempay.utils.hasWithdrawableAmount @@ -102,6 +103,7 @@ internal class TangemPayDetailsStateFactory( .map { cardItem -> TangemPayDetailsBalanceBlockState.Card( lastDigits = cardItem.lastDigits, + imageUrl = cardItem.thumbnailUrl, onClick = { intents.onCardClick(cardItem.id) }, isEnabled = status.error == null, isFrozen = cardItem.isFrozen, diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt index 5363e0b205..9200676a5b 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt @@ -36,6 +36,7 @@ internal data class TangemPayCardDetailsUM( val isLoading: Boolean = false, val cardFrozenState: TangemPayCardFrozenState, val displayNameState: DisplayNameState?, + val cardImageUrl: String?, val isActionsAvailable: Boolean = false, val shouldShowCardDetailsButtonOnCard: Boolean = false, val cardState: TangemPayCardState = TangemPayCardState.Active, @@ -111,6 +112,7 @@ internal sealed class TangemPayDetailsBalanceBlockState { data class Card( val lastDigits: String, + val imageUrl: String?, val onClick: () -> Unit, val state: TangemPayCardUiState, val isFrozen: Boolean, diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/controller/TangemPayCardDetailsController.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/controller/TangemPayCardDetailsController.kt index 7f089402ee..360a2dc717 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/controller/TangemPayCardDetailsController.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/controller/TangemPayCardDetailsController.kt @@ -12,6 +12,7 @@ import com.tangem.domain.models.account.findCardWithId import com.tangem.domain.models.pay.TangemPayCard import com.tangem.domain.models.pay.TangemPayCardFrozenState import com.tangem.domain.models.pay.TangemPayCardState +import com.tangem.domain.models.pay.mainImageUrl import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository @@ -78,6 +79,7 @@ internal class TangemPayCardDetailsController @AssistedInject constructor( onCopy = ::copyData, shouldShowCardDetailsButtonOnCard = config.shouldShowCardDetailsButtonOnCard, cardState = card.state, + cardImageUrl = card.mainImageUrl, ) val uiState: StateFlow @@ -119,6 +121,7 @@ internal class TangemPayCardDetailsController @AssistedInject constructor( cardFrozenState = card.frozenState, isActionsAvailable = card.state == TangemPayCardState.Active, cardState = card.state, + cardImageUrl = card.mainImageUrl, ) } subscribeToCardFrozenState(card.id) diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanScreen.kt index adad1adb87..44afa15780 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanScreen.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanScreen.kt @@ -2,12 +2,12 @@ package com.tangem.features.tangempay.tiers.select import android.content.res.Configuration import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Icon import androidx.compose.material3.Text @@ -16,7 +16,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource @@ -26,7 +25,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import coil.compose.SubcomposeAsyncImage import coil.request.ImageRequest -import com.tangem.core.ui.components.RectangleShimmer import com.tangem.core.ui.ds.TangemPagerIndicator import com.tangem.core.ui.ds.topbar.TangemTopBar import com.tangem.core.ui.ds2.button.Back @@ -268,31 +266,29 @@ private fun ConfirmFooter(content: TangemPaySelectPlanUM.Content.Confirm, modifi @Suppress("MagicNumber") @Composable private fun PlanCard(imageUrl: String?, modifier: Modifier = Modifier) { - SubcomposeAsyncImage( + Box( modifier = modifier .fillMaxWidth() - .aspectRatio(ratio = 266f / 172f) - .clip(RoundedCornerShape(12.dp)), - model = ImageRequest.Builder(LocalContext.current) - .data(imageUrl) - .crossfade(true) - .build(), - loading = { - RectangleShimmer( - modifier = Modifier.fillMaxSize(), - radius = 12.dp, - ) - }, - error = { - Box( - modifier = Modifier - .fillMaxSize() - .background(TangemTheme.colors3.bg.secondary), - ) - }, - contentScale = ContentScale.Crop, - contentDescription = null, - ) + .aspectRatio(ratio = 266f / 172f), + ) { + Image( + modifier = Modifier.matchParentSize(), + painter = painterResource(R.drawable.img_tangem_pay_visa_reissuing), + contentDescription = null, + contentScale = ContentScale.FillBounds, + ) + SubcomposeAsyncImage( + modifier = Modifier.matchParentSize(), + model = ImageRequest.Builder(LocalContext.current) + .data(imageUrl) + .crossfade(true) + .build(), + loading = {}, + error = {}, + contentScale = ContentScale.FillBounds, + contentDescription = null, + ) + } } @Preview(showBackground = true, device = Devices.PIXEL_7_PRO) diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletScreen.kt index 8548f52212..cfebd48a78 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletScreen.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletScreen.kt @@ -186,6 +186,7 @@ private fun PreviewTangemPayAddToWalletScreen() { buttonText = TextReference.Res(R.string.tangempay_card_details_hide_text), cardFrozenState = TangemPayCardFrozenState.Unfrozen, displayNameState = null, + cardImageUrl = null, ), ) } diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletScreenV2.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletScreenV2.kt index 7a962e03e9..684f15d2e0 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletScreenV2.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletScreenV2.kt @@ -220,6 +220,7 @@ private fun PreviewTangemPayAddToWalletScreen() { buttonText = TextReference.Res(R.string.tangempay_card_details_hide_text), cardFrozenState = TangemPayCardFrozenState.Unfrozen, displayNameState = null, + cardImageUrl = null, ), ) } diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt index f20d332c8d..6b333d950a 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt @@ -28,6 +28,7 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.SubcomposeLayout +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource @@ -46,6 +47,8 @@ import androidx.constraintlayout.compose.ConstrainedLayoutReference import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.ConstraintLayoutScope import androidx.constraintlayout.compose.Dimension +import coil.compose.SubcomposeAsyncImage +import coil.request.ImageRequest import com.tangem.core.ui.components.SpacerH import com.tangem.core.ui.components.SpacerWMax import com.tangem.core.ui.components.buttons.common.TangemButton @@ -123,6 +126,7 @@ private fun TangemPayCardDetailsHiddenBlock(state: TangemPayCardDetailsUM, modif .zIndex(0f), cardFrozenState = state.cardFrozenState, cardState = state.cardState, + cardImageUrl = state.cardImageUrl, ) Box( @@ -219,6 +223,7 @@ private fun TangemPayCardDetailsHiddenBlock(state: TangemPayCardDetailsUM, modif private fun TangemPayCardBackground( cardState: TangemPayCardState, cardFrozenState: TangemPayCardFrozenState, + cardImageUrl: String?, modifier: Modifier = Modifier, ) { val isFrozen = cardFrozenState == TangemPayCardFrozenState.Frozen @@ -233,7 +238,7 @@ private fun TangemPayCardBackground( Box(modifier = modifier.fillMaxSize()) { Image( - modifier = Modifier.fillMaxSize(), + modifier = Modifier.matchParentSize(), painter = when (cardState) { TangemPayCardState.Active, -> painterResource(R.drawable.img_tangem_pay_visa) @@ -245,7 +250,19 @@ private fun TangemPayCardBackground( contentDescription = null, contentScale = ContentScale.FillBounds, ) - + if (cardImageUrl != null && cardState == TangemPayCardState.Active) { + SubcomposeAsyncImage( + modifier = Modifier.matchParentSize(), + model = ImageRequest.Builder(LocalContext.current) + .data(cardImageUrl) + .crossfade(true) + .build(), + loading = {}, + error = {}, + contentScale = ContentScale.FillBounds, + contentDescription = null, + ) + } if (isFrozen || freezeProgress > 0f) { Image( modifier = Modifier @@ -756,6 +773,7 @@ private class TangemPayCardDetailsUMProvider : CollectionPreviewParameterProvide cvv = "", buttonText = resourceReference(R.string.tangempay_card_details_show_details), onCopy = { _, _ -> }, + cardImageUrl = null, isHidden = true, cardFrozenState = TangemPayCardFrozenState.Frozen, displayNameState = DisplayNameState.Editing( @@ -776,6 +794,7 @@ private class TangemPayCardDetailsUMProvider : CollectionPreviewParameterProvide cvv = "", buttonText = resourceReference(R.string.tangempay_card_details_show_details), onCopy = { _, _ -> }, + cardImageUrl = null, isHidden = true, cardFrozenState = TangemPayCardFrozenState.Unfrozen, displayNameState = DisplayNameState.Editing( @@ -796,6 +815,7 @@ private class TangemPayCardDetailsUMProvider : CollectionPreviewParameterProvide cvv = "", buttonText = resourceReference(R.string.tangempay_card_details_show_details), onCopy = { _, _ -> }, + cardImageUrl = null, isHidden = true, cardFrozenState = TangemPayCardFrozenState.Pending, displayNameState = DisplayNameState.Display( @@ -809,6 +829,7 @@ private class TangemPayCardDetailsUMProvider : CollectionPreviewParameterProvide onClick = {}, buttonText = resourceReference(R.string.tangempay_card_details_hide_details), onCopy = { _, _ -> }, + cardImageUrl = null, isHidden = false, number = "1234 5678 9012 3456", numberShort = "*3456", diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt index 230a6ac5cb..d8899867a7 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt @@ -428,6 +428,7 @@ private fun previewCardDetailsState(): TangemPayCardDetailsUM = TangemPayCardDet onClick = {}, isEditingEnabled = false, ), + cardImageUrl = null, ) @Preview diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt index c2ebc93549..ca85d48501 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt @@ -491,6 +491,7 @@ internal class TangemPayDetailsUMProvider : CollectionPreviewParameterProvider Unit, isFrozen: Boolean, modifier: Modifier = Modifier, @@ -58,6 +64,7 @@ internal fun TangemPayCardView( .testTag(TangemPayTestTags.PAYMENT_ACCOUNT_CARD_BUTTON), isIssueInProgress = isIssueInProgress, isEnabled = isEnabled, + imageUrl = imageUrl, onClick = onClick, ) { Row( @@ -78,7 +85,6 @@ internal fun TangemPayCardView( tint = TangemTheme.colors3.icon.staticDark, contentDescription = null, ) - Icon( modifier = Modifier.size(height = TangemTheme.dimens2.x2, width = 22.dp), imageVector = ImageVector.vectorResource(R.drawable.ic_visa_logo), @@ -126,6 +132,7 @@ internal fun TangemPayAddCardView(onClick: () -> Unit, isEnabled: Boolean, modif private fun CardBackground( isIssueInProgress: Boolean, isEnabled: Boolean, + imageUrl: String?, onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit, @@ -137,7 +144,6 @@ private fun CardBackground( Color(DEFAULT_CARD_BG) } } - Box( modifier = modifier .alpha(if (isEnabled) 1f else DISABLED_ALPHA) @@ -171,8 +177,22 @@ private fun CardBackground( shape = RoundedCornerShape(6.dp), ) .clickableSingle(onClick = onClick, enabled = isEnabled), - content = content, - ) + ) { + if (imageUrl != null) { + SubcomposeAsyncImage( + modifier = Modifier.matchParentSize(), + model = ImageRequest.Builder(LocalContext.current) + .data(imageUrl) + .crossfade(true) + .build(), + loading = {}, + error = {}, + contentScale = ContentScale.Crop, + contentDescription = null, + ) + } + content() + } } @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.PIXEL_7_PRO) @@ -189,6 +209,7 @@ private fun CardBackgroundPreview() { onClick = {}, content = {}, isEnabled = true, + imageUrl = null, ) SpacerH(TangemTheme.dimens2.x4) CardBackground( @@ -197,6 +218,7 @@ private fun CardBackgroundPreview() { width = TangemTheme.dimens2.x14, ), isIssueInProgress = true, + imageUrl = null, onClick = {}, content = {}, isEnabled = true, @@ -206,6 +228,7 @@ private fun CardBackgroundPreview() { isIssueInProgress = false, onClick = {}, lastDigits = "1234", + imageUrl = null, isEnabled = true, isFrozen = false, ) @@ -214,6 +237,7 @@ private fun CardBackgroundPreview() { isIssueInProgress = true, onClick = {}, lastDigits = "", + imageUrl = null, isEnabled = true, isFrozen = false, ) @@ -224,6 +248,7 @@ private fun CardBackgroundPreview() { isIssueInProgress = false, onClick = {}, lastDigits = "1234", + imageUrl = null, isEnabled = true, isFrozen = true, ) diff --git a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/TangemPayTestFixtures.kt b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/TangemPayTestFixtures.kt index 1c7e5f6f68..7b002b4db4 100644 --- a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/TangemPayTestFixtures.kt +++ b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/TangemPayTestFixtures.kt @@ -58,5 +58,6 @@ internal fun tangemPayCard( limit = null, frozenState = frozenState, lastDigits = lastDigits, + images = emptyList(), state = state, ) \ No newline at end of file diff --git a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/limit/setup/TangemPayCardLimitSetupModelTest.kt b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/limit/setup/TangemPayCardLimitSetupModelTest.kt index 265fc69e44..048c7a5396 100644 --- a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/limit/setup/TangemPayCardLimitSetupModelTest.kt +++ b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/limit/setup/TangemPayCardLimitSetupModelTest.kt @@ -47,6 +47,7 @@ internal class TangemPayCardLimitSetupModelTest { frozenState = TangemPayCardFrozenState.Unfrozen, lastDigits = "1234", limit = null, + images = emptyList(), state = TangemPayCardState.Active, ) @@ -72,6 +73,7 @@ internal class TangemPayCardLimitSetupModelTest { ) } ), + images = emptyList(), state = TangemPayCardState.Active, ) val statusWithLimit: PaymentAccountStatusValue.Loaded = mockk(relaxed = true) { diff --git a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/TangemPayEditDisplayNameModelTest.kt b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/TangemPayEditDisplayNameModelTest.kt index 9cf134e92b..3f80cc0a72 100644 --- a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/TangemPayEditDisplayNameModelTest.kt +++ b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/TangemPayEditDisplayNameModelTest.kt @@ -162,6 +162,7 @@ internal class TangemPayEditDisplayNameModelTest { limit = null, frozenState = TangemPayCardFrozenState.Unfrozen, lastDigits = "1234", + images = emptyList(), state = TangemPayCardState.Active, ) } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/controller/TangemPayCardDetailsControllerTest.kt b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/controller/TangemPayCardDetailsControllerTest.kt index 85ec2057e1..3492526949 100644 --- a/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/controller/TangemPayCardDetailsControllerTest.kt +++ b/features/tangempay/details/impl/src/test/kotlin/com/tangem/features/tangempay/model/controller/TangemPayCardDetailsControllerTest.kt @@ -238,6 +238,7 @@ internal class TangemPayCardDetailsControllerTest { limit = null, frozenState = frozenState, lastDigits = lastDigits, + images = emptyList(), state = state, )