Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-23 06:38:34 -07:00
parent eda701fed9
commit 06cb9620e9
13 changed files with 64 additions and 41 deletions

View file

@ -87,6 +87,9 @@ data class TangemPayTariffPlan(
@SerialName("BANNER")
BANNER,
@SerialName("BACKGROUND")
BACKGROUND,
@SerialName("UNKNOWN")
UNKNOWN,
;
@ -96,6 +99,7 @@ data class TangemPayTariffPlan(
"THUMBNAIL" -> THUMBNAIL
"MAIN" -> MAIN
"BANNER" -> BANNER
"BACKGROUND" -> BACKGROUND
else -> UNKNOWN
}
}

View file

@ -73,3 +73,6 @@ val TangemPayCard.thumbnailUrl: String?
val TangemPayCard.mainImageUrl: String?
get() = images.firstOrNull { it.type == TangemPayTariffPlan.Image.Type.MAIN }?.url
val TangemPayCard.backgroundImageUrl: String?
get() = images.firstOrNull { it.type == TangemPayTariffPlan.Image.Type.BACKGROUND }?.url

View file

@ -14,6 +14,7 @@ internal class TangemPayCardDetailsBlockStateFactory(
private val isEditingNameEnabled: Boolean,
private val cardState: TangemPayCardState,
private val cardImageUrl: String?,
private val cardBackgroundImageUrl: String?,
private val onEditNameClick: () -> Unit,
private val onReveal: () -> Unit,
private val onCopy: (String, CardDataType) -> Unit,
@ -43,6 +44,7 @@ internal class TangemPayCardDetailsBlockStateFactory(
shouldShowCardDetailsButtonOnCard = shouldShowCardDetailsButtonOnCard,
cardState = cardState,
cardImageUrl = cardImageUrl,
cardBackgroundImageUrl = cardBackgroundImageUrl,
)
}
}

View file

@ -52,6 +52,7 @@ internal data class TangemPayCardDetailsUM(
val cardFrozenState: TangemPayCardFrozenState,
val displayNameState: DisplayNameState?,
val cardImageUrl: String?,
val cardBackgroundImageUrl: String?,
val isActionsAvailable: Boolean = false,
val shouldShowCardDetailsButtonOnCard: Boolean = false,
val cardState: TangemPayCardState = TangemPayCardState.Active,

View file

@ -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.backgroundImageUrl
import com.tangem.domain.models.pay.mainImageUrl
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
@ -80,6 +81,7 @@ internal class TangemPayCardDetailsController @AssistedInject constructor(
shouldShowCardDetailsButtonOnCard = config.shouldShowCardDetailsButtonOnCard,
cardState = card.state,
cardImageUrl = card.mainImageUrl,
cardBackgroundImageUrl = card.backgroundImageUrl,
)
val uiState: StateFlow<TangemPayCardDetailsUM>
@ -122,6 +124,7 @@ internal class TangemPayCardDetailsController @AssistedInject constructor(
isActionsAvailable = card.state == TangemPayCardState.Active,
cardState = card.state,
cardImageUrl = card.mainImageUrl,
cardBackgroundImageUrl = card.backgroundImageUrl,
)
}
subscribeToCardFrozenState(card.id)

View file

@ -221,6 +221,7 @@ private fun PreviewTangemPayAddToWalletScreen() {
cardFrozenState = TangemPayCardFrozenState.Unfrozen,
displayNameState = null,
cardImageUrl = null,
cardBackgroundImageUrl = null,
),
)
}

View file

@ -46,7 +46,7 @@ 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.compose.AsyncImage
import coil.request.ImageRequest
import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.components.SpacerWMax
@ -58,7 +58,10 @@ import com.tangem.core.ui.ds2.button.TangemButton
import com.tangem.core.ui.extensions.conditional
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.*
import com.tangem.core.ui.res.LocalIsInDarkTheme
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemThemeRedesign
import com.tangem.core.ui.test.TangemPayTestTags
import com.tangem.domain.models.pay.TangemPayCardFrozenState
import com.tangem.domain.models.pay.TangemPayCardState
@ -96,6 +99,7 @@ internal fun TangemPayCard(state: TangemPayCardDetailsUM, modifier: Modifier = M
rotateCardY = rotateCardY,
zAxisDistance = zAxisDistance,
shouldShowDetails = shouldShowDetails,
backgroundImageUrl = state.cardBackgroundImageUrl,
modifier = modifier,
front = { TangemPayCardDetailsHiddenBlock(state = state) },
back = {
@ -215,32 +219,18 @@ private fun TangemPayCardBackground(
)
Box(modifier = modifier.fillMaxSize()) {
Image(
AsyncImage(
modifier = Modifier.matchParentSize(),
painter = when (cardState) {
TangemPayCardState.Active,
-> painterResource(R.drawable.img_tangem_pay_visa)
TangemPayCardState.Reissuing,
TangemPayCardState.Closing,
TangemPayCardState.Issuing,
-> painterResource(R.drawable.img_tangem_pay_card_placeholder)
},
contentDescription = null,
model = ImageRequest.Builder(LocalContext.current)
.data(cardImageUrl.takeIf { cardState == TangemPayCardState.Active })
.crossfade(true)
.build(),
placeholder = painterResource(R.drawable.img_tangem_pay_card_placeholder),
error = painterResource(R.drawable.img_tangem_pay_card_placeholder),
fallback = painterResource(R.drawable.img_tangem_pay_card_placeholder),
contentScale = ContentScale.FillBounds,
contentDescription = null,
)
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
@ -254,17 +244,17 @@ private fun TangemPayCardBackground(
}
}
@Suppress("MagicNumber", "LongMethod")
@Suppress("MagicNumber", "LongMethod", "LongParameterList")
@Composable
private fun CardBgWrapper(
rotateCardY: Float,
zAxisDistance: Float,
shouldShowDetails: Boolean,
backgroundImageUrl: String?,
modifier: Modifier = Modifier,
back: @Composable () -> Unit,
front: @Composable () -> Unit,
) {
val shouldShowDetailsBg = shouldShowDetails
Box(
modifier = modifier
.fillMaxWidth()
@ -296,19 +286,20 @@ private fun CardBgWrapper(
.fillMaxSize()
.graphicsLayer { alpha = if (shouldShowDetails) 1f else 0f },
) {
if (shouldShowDetailsBg) {
Image(
modifier = Modifier
.matchParentSize()
.graphicsLayer {
rotationY = rotateCardY
cameraDistance = zAxisDistance
},
painter = painterResource(R.drawable.img_bg_card_details),
contentDescription = null,
contentScale = ContentScale.Crop,
)
}
AsyncImage(
modifier = Modifier
.matchParentSize()
.graphicsLayer { rotationY = 180f },
model = ImageRequest.Builder(LocalContext.current)
.data(backgroundImageUrl)
.crossfade(true)
.build(),
placeholder = painterResource(R.drawable.img_tangem_pay_details_placeholder),
error = painterResource(R.drawable.img_tangem_pay_details_placeholder),
fallback = painterResource(R.drawable.img_tangem_pay_details_placeholder),
contentDescription = null,
contentScale = ContentScale.Crop,
)
back()
}
},
@ -655,6 +646,7 @@ private class TangemPayCardDetailsUMProvider : CollectionPreviewParameterProvide
buttonText = resourceReference(R.string.tangempay_card_details_show_details),
onCopy = { _, _ -> },
cardImageUrl = null,
cardBackgroundImageUrl = null,
isHidden = true,
cardFrozenState = TangemPayCardFrozenState.Frozen,
displayNameState = DisplayNameState.Editing(
@ -676,6 +668,7 @@ private class TangemPayCardDetailsUMProvider : CollectionPreviewParameterProvide
buttonText = resourceReference(R.string.tangempay_card_details_show_details),
onCopy = { _, _ -> },
cardImageUrl = null,
cardBackgroundImageUrl = null,
isHidden = true,
cardFrozenState = TangemPayCardFrozenState.Unfrozen,
displayNameState = DisplayNameState.Editing(
@ -697,6 +690,7 @@ private class TangemPayCardDetailsUMProvider : CollectionPreviewParameterProvide
buttonText = resourceReference(R.string.tangempay_card_details_show_details),
onCopy = { _, _ -> },
cardImageUrl = null,
cardBackgroundImageUrl = null,
isHidden = true,
cardFrozenState = TangemPayCardFrozenState.Pending,
displayNameState = DisplayNameState.Display(
@ -711,6 +705,7 @@ private class TangemPayCardDetailsUMProvider : CollectionPreviewParameterProvide
buttonText = resourceReference(R.string.tangempay_card_details_hide_details),
onCopy = { _, _ -> },
cardImageUrl = null,
cardBackgroundImageUrl = null,
isHidden = false,
number = "1234 5678 9012 3456",
numberShort = "*3456",

View file

@ -312,6 +312,7 @@ private fun previewCardDetailsState(): TangemPayCardDetailsUM = TangemPayCardDet
isEditingEnabled = false,
),
cardImageUrl = null,
cardBackgroundImageUrl = null,
)
@Preview

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

View file

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="370dp"
android:height="238dp"
android:viewportWidth="370"
android:viewportHeight="238">
<path
android:fillAlpha="0.1"
android:fillColor="#0F0F0F"
android:pathData="M0,32C0,20.8 0,15.2 2.18,10.92C4.1,7.16 7.16,4.1 10.92,2.18C15.2,0 20.8,0 32,0L338,0C349.2,0 354.8,0 359.08,2.18C362.84,4.1 365.9,7.16 367.82,10.92C370,15.2 370,20.8 370,32V206C370,217.2 370,222.8 367.82,227.08C365.9,230.84 362.84,233.9 359.08,235.82C354.8,238 349.2,238 338,238L32,238C20.8,238 15.2,238 10.92,235.82C7.16,233.9 4.1,230.84 2.18,227.08C0,222.8 0,217.2 0,206L0,32Z" />
<path
android:fillColor="#0F0F0F"
android:pathData="M0,32C0,20.8 0,15.2 2.18,10.92C4.1,7.16 7.16,4.1 10.92,2.18C15.2,0 20.8,0 32,0L338,0C349.2,0 354.8,0 359.08,2.18C362.84,4.1 365.9,7.16 367.82,10.92C370,15.2 370,20.8 370,32V206C370,217.2 370,222.8 367.82,227.08C365.9,230.84 362.84,233.9 359.08,235.82C354.8,238 349.2,238 338,238L32,238C20.8,238 15.2,238 10.92,235.82C7.16,233.9 4.1,230.84 2.18,227.08C0,222.8 0,217.2 0,206L0,32Z" />
</vector>