Updated on 2026-08-14
This commit is contained in:
parent
65d2e84c6e
commit
9e986a6cb3
21 changed files with 180 additions and 77 deletions
|
|
@ -2020,6 +2020,7 @@
|
||||||
<string name="tangempay_onboarding_title">Get your Tangem Pay Card in minutes</string>
|
<string name="tangempay_onboarding_title">Get your Tangem Pay Card in minutes</string>
|
||||||
<string name="tangempay_pay_support">Pay Support</string>
|
<string name="tangempay_pay_support">Pay Support</string>
|
||||||
<string name="tangempay_main_select_plan">Select plan</string>
|
<string name="tangempay_main_select_plan">Select plan</string>
|
||||||
|
<string name="tangempay_status_inactive">Inactive</string>
|
||||||
<string name="tangempay_payment_account">Payment account</string>
|
<string name="tangempay_payment_account">Payment account</string>
|
||||||
<string name="tangempay_payment_account_sync_needed">Session expired</string>
|
<string name="tangempay_payment_account_sync_needed">Session expired</string>
|
||||||
<string name="tangempay_pin_validation_error_message">Invalid PIN: avoid sequences or repeats</string>
|
<string name="tangempay_pin_validation_error_message">Invalid PIN: avoid sequences or repeats</string>
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ internal class PaymentAccountStatusValueDMConverter @Inject constructor(
|
||||||
// Transient statuses are not persisted
|
// Transient statuses are not persisted
|
||||||
is PaymentAccountStatusValue.Loading,
|
is PaymentAccountStatusValue.Loading,
|
||||||
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
||||||
|
is PaymentAccountStatusValue.Inactive,
|
||||||
is PaymentAccountStatusValue.Error.ExposedDevice,
|
is PaymentAccountStatusValue.Error.ExposedDevice,
|
||||||
is PaymentAccountStatusValue.Error.Unavailable,
|
is PaymentAccountStatusValue.Error.Unavailable,
|
||||||
is PaymentAccountStatusValue.Error.NotSynced,
|
is PaymentAccountStatusValue.Error.NotSynced,
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,28 @@ internal class PaymentAccountStatusValueDMConverterTest {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
val domain = PaymentAccountStatusValue.AwaitingPlanSelection(
|
val domain = PaymentAccountStatusValue.AwaitingPlanSelection(
|
||||||
source = StatusSource.ACTUAL,
|
source = StatusSource.ACTUAL,
|
||||||
tariffPlan = null,
|
cryptoCurrency = cryptoCurrency,
|
||||||
|
tariffPlan = mockk(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
val result = converter.convert(domain)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
assertThat(result).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN domain Inactive WHEN convert THEN returns null (transient, not persisted)`() {
|
||||||
|
// GIVEN
|
||||||
|
val domain = PaymentAccountStatusValue.Inactive(
|
||||||
|
source = StatusSource.ACTUAL,
|
||||||
|
fiatBalance = PaymentAccountStatusValue.FiatBalance(
|
||||||
|
availableBalance = BigDecimal("100"),
|
||||||
|
currency = "USD",
|
||||||
|
),
|
||||||
|
cryptoCurrency = cryptoCurrency,
|
||||||
|
tariffPlan = mockk(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// WHEN
|
// WHEN
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ class IsAccountsModeEnabledUseCase(
|
||||||
is PaymentAccountStatusValue.Error,
|
is PaymentAccountStatusValue.Error,
|
||||||
is PaymentAccountStatusValue.IssuingCard,
|
is PaymentAccountStatusValue.IssuingCard,
|
||||||
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
||||||
|
is PaymentAccountStatusValue.Inactive,
|
||||||
is PaymentAccountStatusValue.Loaded,
|
is PaymentAccountStatusValue.Loaded,
|
||||||
is PaymentAccountStatusValue.Loading,
|
is PaymentAccountStatusValue.Loading,
|
||||||
is PaymentAccountStatusValue.UnderReview,
|
is PaymentAccountStatusValue.UnderReview,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ sealed class PaymentAccountStatusValue {
|
||||||
is Error,
|
is Error,
|
||||||
is IssuingCard,
|
is IssuingCard,
|
||||||
is AwaitingPlanSelection,
|
is AwaitingPlanSelection,
|
||||||
|
is Inactive,
|
||||||
is Empty,
|
is Empty,
|
||||||
is NotCreated,
|
is NotCreated,
|
||||||
is UnderReview,
|
is UnderReview,
|
||||||
|
|
@ -56,6 +57,7 @@ sealed class PaymentAccountStatusValue {
|
||||||
is Deactivated -> copy(source = source, error = error ?: this.error)
|
is Deactivated -> copy(source = source, error = error ?: this.error)
|
||||||
is Loading,
|
is Loading,
|
||||||
is AwaitingPlanSelection,
|
is AwaitingPlanSelection,
|
||||||
|
is Inactive,
|
||||||
is Empty,
|
is Empty,
|
||||||
is NotCreated,
|
is NotCreated,
|
||||||
is Error,
|
is Error,
|
||||||
|
|
@ -107,13 +109,30 @@ sealed class PaymentAccountStatusValue {
|
||||||
* Represents a state where KYC is approved but no tariff plan has been selected yet
|
* Represents a state where KYC is approved but no tariff plan has been selected yet
|
||||||
*
|
*
|
||||||
* @property source The source of the status information.
|
* @property source The source of the status information.
|
||||||
* @property tariffPlan Current tariff plan (fallback Basic) if the backend already returns one
|
* @property cryptoCurrency The crypto currency held by the account.
|
||||||
* Transient: not persisted in the local cache.
|
* @property tariffPlan Current tariff plan
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AwaitingPlanSelection(
|
data class AwaitingPlanSelection(
|
||||||
override val source: StatusSource,
|
override val source: StatusSource,
|
||||||
val tariffPlan: TangemPayCustomerTariffPlan?,
|
val cryptoCurrency: CryptoCurrency.Token,
|
||||||
|
val tariffPlan: TangemPayCustomerTariffPlan,
|
||||||
|
) : PaymentAccountStatusValue()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a state where a tariff plan has been selected and the card is being issued
|
||||||
|
*
|
||||||
|
* @property source The source of the status information.
|
||||||
|
* @property fiatBalance The fiat balance of state.
|
||||||
|
* @property cryptoCurrency The crypto currency held by the account.
|
||||||
|
* @property tariffPlan Current tariff plan
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class Inactive(
|
||||||
|
override val source: StatusSource,
|
||||||
|
val fiatBalance: FiatBalance,
|
||||||
|
val cryptoCurrency: CryptoCurrency.Token,
|
||||||
|
val tariffPlan: TangemPayTariffPlanState,
|
||||||
) : PaymentAccountStatusValue()
|
) : PaymentAccountStatusValue()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ internal class ChooseTokenListItemConverter(
|
||||||
is PaymentAccountStatusValue.Error,
|
is PaymentAccountStatusValue.Error,
|
||||||
is PaymentAccountStatusValue.IssuingCard,
|
is PaymentAccountStatusValue.IssuingCard,
|
||||||
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
||||||
|
is PaymentAccountStatusValue.Inactive,
|
||||||
PaymentAccountStatusValue.NotCreated,
|
PaymentAccountStatusValue.NotCreated,
|
||||||
is PaymentAccountStatusValue.UnderReview,
|
is PaymentAccountStatusValue.UnderReview,
|
||||||
PaymentAccountStatusValue.Loading,
|
PaymentAccountStatusValue.Loading,
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
import com.tangem.domain.models.pay.isFrozen
|
import com.tangem.domain.models.pay.isFrozen
|
||||||
import com.tangem.domain.models.pay.thumbnailUrl
|
import com.tangem.domain.models.pay.thumbnailUrl
|
||||||
import com.tangem.features.tangempay.details.impl.R
|
import com.tangem.features.tangempay.details.impl.R
|
||||||
|
import com.tangem.features.tangempay.model.transformers.DetailsBalanceTransformer
|
||||||
import com.tangem.features.tangempay.utils.TangemPayDetailIntents
|
import com.tangem.features.tangempay.utils.TangemPayDetailIntents
|
||||||
import com.tangem.features.tangempay.utils.hasWithdrawableAmount
|
import com.tangem.features.tangempay.utils.hasWithdrawableAmount
|
||||||
import com.tangem.features.tangempay.utils.isFresh
|
import com.tangem.features.tangempay.utils.isFresh
|
||||||
|
|
@ -28,7 +29,7 @@ import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import com.tangem.core.ui.R as CoreUiR
|
import com.tangem.core.ui.R as CoreUiR
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList", "LargeClass")
|
||||||
internal class TangemPayDetailsStateFactory(
|
internal class TangemPayDetailsStateFactory(
|
||||||
private val onBack: () -> Unit,
|
private val onBack: () -> Unit,
|
||||||
private val onOpenMenu: () -> Unit,
|
private val onOpenMenu: () -> Unit,
|
||||||
|
|
@ -159,6 +160,51 @@ internal class TangemPayDetailsStateFactory(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getInactiveState(status: PaymentAccountStatusValue.Inactive): TangemPayDetailsUM {
|
||||||
|
val notification = notificationFactory.createAwaitingDepositConfig(status.tariffPlan)
|
||||||
|
return TangemPayDetailsUM(
|
||||||
|
topBarConfig = TangemPayDetailsTopBarConfig(
|
||||||
|
onBackClick = onBack,
|
||||||
|
onOpenMenu = onOpenMenu,
|
||||||
|
items = getTopBarMenuItems(),
|
||||||
|
itemsV2 = getTopBarMenuItemsV2(tariffPlan = null),
|
||||||
|
),
|
||||||
|
pullToRefreshConfig = PullToRefreshConfig(
|
||||||
|
isRefreshing = false,
|
||||||
|
onRefresh = intents::onRefreshSwipe,
|
||||||
|
),
|
||||||
|
balanceBlockState = TangemPayDetailsBalanceBlockState.Content(
|
||||||
|
actionButtons = getActionButtonsConfig(
|
||||||
|
isAddFundsEnabled = true,
|
||||||
|
isWithdrawEnabled = false,
|
||||||
|
),
|
||||||
|
cardsBlockState = TangemPayDetailsBalanceBlockState.CardsBlockState(
|
||||||
|
cards = persistentListOf(
|
||||||
|
TangemPayDetailsBalanceBlockState.Card(
|
||||||
|
lastDigits = "",
|
||||||
|
imageUrl = null,
|
||||||
|
onClick = {},
|
||||||
|
isEnabled = false,
|
||||||
|
isFrozen = false,
|
||||||
|
state = TangemPayCardUiState.InProgress,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onAddCardClick = intents::onAddCardClick,
|
||||||
|
isAddCardEnabled = false,
|
||||||
|
),
|
||||||
|
fiatBalance = DetailsBalanceTransformer.getFiatBalanceText(status.fiatBalance),
|
||||||
|
isInactive = true,
|
||||||
|
isNegative = false,
|
||||||
|
isBalanceFlickering = false,
|
||||||
|
),
|
||||||
|
isBalanceHidden = false,
|
||||||
|
addToWalletBlockState = null,
|
||||||
|
errorNotificationConfig = notification,
|
||||||
|
accountDeactivatedNotificationConfig = null,
|
||||||
|
cashbackBlockState = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getTopBarMenuItems(): ImmutableList<TangemDropdownMenuItem> {
|
private fun getTopBarMenuItems(): ImmutableList<TangemDropdownMenuItem> {
|
||||||
return persistentListOf(
|
return persistentListOf(
|
||||||
TangemDropdownMenuItem(
|
TangemDropdownMenuItem(
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ internal sealed class TangemPayDetailsBalanceBlockState {
|
||||||
val fiatBalance: TextReference,
|
val fiatBalance: TextReference,
|
||||||
val isBalanceFlickering: Boolean,
|
val isBalanceFlickering: Boolean,
|
||||||
val isNegative: Boolean,
|
val isNegative: Boolean,
|
||||||
|
val isInactive: Boolean,
|
||||||
val isMuted: Boolean = false,
|
val isMuted: Boolean = false,
|
||||||
) : TangemPayDetailsBalanceBlockState()
|
) : TangemPayDetailsBalanceBlockState()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ import com.tangem.features.tangempay.entity.TangemPayDetailsStateFactory
|
||||||
import com.tangem.features.tangempay.entity.TangemPayDetailsUM
|
import com.tangem.features.tangempay.entity.TangemPayDetailsUM
|
||||||
import com.tangem.features.tangempay.model.transformers.*
|
import com.tangem.features.tangempay.model.transformers.*
|
||||||
import com.tangem.features.tangempay.navigation.TangemPayAccountDetailsInnerRoute
|
import com.tangem.features.tangempay.navigation.TangemPayAccountDetailsInnerRoute
|
||||||
|
import com.tangem.features.tangempay.tiers.feeCurrency
|
||||||
import com.tangem.features.tangempay.utils.*
|
import com.tangem.features.tangempay.utils.*
|
||||||
import com.tangem.features.tokendetails.ExpressTransactionsEvent
|
import com.tangem.features.tokendetails.ExpressTransactionsEvent
|
||||||
import com.tangem.features.tokendetails.ExpressTransactionsEventListener
|
import com.tangem.features.tokendetails.ExpressTransactionsEventListener
|
||||||
|
|
@ -171,6 +172,9 @@ internal class TangemPayDetailsModel @Inject constructor(
|
||||||
)
|
)
|
||||||
uiState.update { balanceTransformer.transform(stateFactory.getLoadedState(state)) }
|
uiState.update { balanceTransformer.transform(stateFactory.getLoadedState(state)) }
|
||||||
}
|
}
|
||||||
|
is PaymentAccountStatusValue.Inactive -> uiState.update {
|
||||||
|
stateFactory.getInactiveState(state)
|
||||||
|
}
|
||||||
else -> uiState.update { stateFactory.getLoadingState() }
|
else -> uiState.update { stateFactory.getLoadingState() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -484,11 +488,6 @@ internal class TangemPayDetailsModel @Inject constructor(
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val activeCardsCount = currentStatus.value.ifLoadedOrNull { loaded -> loaded.cards.count() } ?: 0
|
|
||||||
if (activeCardsCount >= ALLOWED_MAX_CARDS_COUNT) {
|
|
||||||
uiMessageSender.send(TangemPayMessagesFactory.createMaximumCardsIssued(maxCards = ALLOWED_MAX_CARDS_COUNT))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
modelScope.launch {
|
modelScope.launch {
|
||||||
val offer = getCustomerOffers.additionalCardOffer(userWalletId).getOrNull()
|
val offer = getCustomerOffers.additionalCardOffer(userWalletId).getOrNull()
|
||||||
if (offer == null) {
|
if (offer == null) {
|
||||||
|
|
@ -569,8 +568,4 @@ internal class TangemPayDetailsModel @Inject constructor(
|
||||||
private fun showBottomSheetError(type: TangemPayDetailsErrorType) {
|
private fun showBottomSheetError(type: TangemPayDetailsErrorType) {
|
||||||
uiMessageSender.send(message = TangemPayMessagesFactory.createErrorMessage(errorType = type))
|
uiMessageSender.send(message = TangemPayMessagesFactory.createErrorMessage(errorType = type))
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
|
||||||
const val ALLOWED_MAX_CARDS_COUNT = 3
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ import java.util.Currency
|
||||||
|
|
||||||
internal class DetailsBalanceTransformer(
|
internal class DetailsBalanceTransformer(
|
||||||
private val fiatBalance: PaymentAccountStatusValue.FiatBalance,
|
private val fiatBalance: PaymentAccountStatusValue.FiatBalance,
|
||||||
|
private val isInactive: Boolean = false,
|
||||||
private val isMuted: Boolean = false,
|
private val isMuted: Boolean = false,
|
||||||
) : Transformer<TangemPayDetailsUM> {
|
) : Transformer<TangemPayDetailsUM> {
|
||||||
|
|
||||||
|
|
@ -23,18 +24,21 @@ internal class DetailsBalanceTransformer(
|
||||||
cardsBlockState = prevState.balanceBlockState.cardsBlockState,
|
cardsBlockState = prevState.balanceBlockState.cardsBlockState,
|
||||||
isMuted = isMuted,
|
isMuted = isMuted,
|
||||||
isNegative = fiatBalance.availableBalance.signum() < 0,
|
isNegative = fiatBalance.availableBalance.signum() < 0,
|
||||||
|
isInactive = isInactive,
|
||||||
)
|
)
|
||||||
return prevState.copy(balanceBlockState = balance)
|
return prevState.copy(balanceBlockState = balance)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFiatBalanceText(fiatBalance: PaymentAccountStatusValue.FiatBalance): TextReference {
|
companion object {
|
||||||
val currency = Currency.getInstance(fiatBalance.currency)
|
fun getFiatBalanceText(fiatBalance: PaymentAccountStatusValue.FiatBalance): TextReference {
|
||||||
return fiatBalance.availableBalance.formatStyled {
|
val currency = Currency.getInstance(fiatBalance.currency)
|
||||||
fiat(
|
return fiatBalance.availableBalance.formatStyled {
|
||||||
fiatCurrencyCode = currency.currencyCode,
|
fiat(
|
||||||
fiatCurrencySymbol = currency.symbol,
|
fiatCurrencyCode = currency.currencyCode,
|
||||||
spanStyleReference = { TangemTheme.typography3.heading.medium.toSpanStyle() },
|
fiatCurrencySymbol = currency.symbol,
|
||||||
)
|
spanStyleReference = { TangemTheme.typography3.heading.medium.toSpanStyle() },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,9 @@ import com.tangem.domain.models.account.TangemPayCustomerTariffPlan
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlan
|
import com.tangem.domain.models.account.TangemPayTariffPlan
|
||||||
import org.joda.time.format.DateTimeFormatter
|
import org.joda.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
val TangemPayTariffPlan.feeCurrency: String?
|
||||||
|
get() = fees.firstOrNull()?.currency
|
||||||
|
|
||||||
fun TangemPayTariffPlan.formatRecurringFeeOrNull(): String? {
|
fun TangemPayTariffPlan.formatRecurringFeeOrNull(): String? {
|
||||||
val fee = fees.find { it.type == TangemPayTariffPlan.Fee.Type.RECURRING } ?: return null
|
val fee = fees.find { it.type == TangemPayTariffPlan.Fee.Type.RECURRING } ?: return null
|
||||||
val currency = getJavaCurrencyByCode(fee.currency)
|
val currency = getJavaCurrencyByCode(fee.currency)
|
||||||
|
|
|
||||||
|
|
@ -510,6 +510,7 @@ internal class TangemPayDetailsUMProvider : CollectionPreviewParameterProvider<T
|
||||||
isAddCardEnabled = true,
|
isAddCardEnabled = true,
|
||||||
),
|
),
|
||||||
isNegative = false,
|
isNegative = false,
|
||||||
|
isInactive = false,
|
||||||
),
|
),
|
||||||
isBalanceHidden = false,
|
isBalanceHidden = false,
|
||||||
addToWalletBlockState = AddToWalletBlockState(
|
addToWalletBlockState = AddToWalletBlockState(
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import com.tangem.core.ui.components.topFade
|
||||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.core.ui.ds.button.*
|
import com.tangem.core.ui.ds.button.*
|
||||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
|
import com.tangem.core.ui.ds2.badge.TangemBadge
|
||||||
import com.tangem.core.ui.ds.message.TangemMessage
|
import com.tangem.core.ui.ds.message.TangemMessage
|
||||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
||||||
|
|
@ -359,39 +360,7 @@ private fun BalanceBlock(
|
||||||
fadeOut(animationSpec = tween(durationMillis = 90))
|
fadeOut(animationSpec = tween(durationMillis = 90))
|
||||||
},
|
},
|
||||||
) { animatedState ->
|
) { animatedState ->
|
||||||
when (animatedState) {
|
BalanceValue(animatedState, isBalanceHidden)
|
||||||
is TangemPayDetailsBalanceBlockState.Loading -> TangemShimmer(
|
|
||||||
style = TangemTheme.typography3.heading.medium,
|
|
||||||
)
|
|
||||||
is TangemPayDetailsBalanceBlockState.Content -> {
|
|
||||||
val balanceColor = when {
|
|
||||||
animatedState.isMuted -> TangemTheme.colors3.text.secondary
|
|
||||||
animatedState.isNegative -> TangemTheme.colors3.text.status.error
|
|
||||||
else -> TangemTheme.colors3.text.primary
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
modifier = Modifier.testTag(TangemPayTestTags.PAYMENT_ACCOUNT_BALANCE),
|
|
||||||
text = animatedState.fiatBalance.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
|
||||||
style = TangemTheme.typography3.display.medium.applyBladeBrush(
|
|
||||||
isEnabled = animatedState.isBalanceFlickering,
|
|
||||||
textColor = balanceColor,
|
|
||||||
),
|
|
||||||
color = balanceColor,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
autoSize = TextAutoSize.StepBased(
|
|
||||||
minFontSize = TangemTheme.typography3.heading.medium.fontSize,
|
|
||||||
maxFontSize = TangemTheme.typography3.display.medium.fontSize,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is TangemPayDetailsBalanceBlockState.Error -> Text(
|
|
||||||
modifier = Modifier.testTag(TangemPayTestTags.PAYMENT_ACCOUNT_BALANCE),
|
|
||||||
text = DASH_SIGN.orMaskWithStars(isBalanceHidden),
|
|
||||||
style = TangemTheme.typography3.display.medium,
|
|
||||||
color = TangemTheme.colors3.text.primary,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
|
|
@ -400,6 +369,58 @@ private fun BalanceBlock(
|
||||||
color = TangemTheme.colors3.text.secondary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
style = TangemTheme.typography3.caption.medium,
|
style = TangemTheme.typography3.caption.medium,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
when (state) {
|
||||||
|
is TangemPayDetailsBalanceBlockState.Loading -> Unit
|
||||||
|
is TangemPayDetailsBalanceBlockState.Content -> {
|
||||||
|
TangemBadge(
|
||||||
|
modifier = Modifier.padding(vertical = TangemTheme.dimens2.x1),
|
||||||
|
text = resourceReference(R.string.tangempay_status_inactive),
|
||||||
|
variant = TangemBadge.Variant.Outline,
|
||||||
|
status = TangemBadge.Status.Warning,
|
||||||
|
size = TangemBadge.Size.X6,
|
||||||
|
iconStart = TangemIconUM.Icon(iconRes = CoreUiR.drawable.ic_information_24),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TangemPayDetailsBalanceBlockState.Error -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BalanceValue(state: TangemPayDetailsBalanceBlockState, isBalanceHidden: Boolean) {
|
||||||
|
when (state) {
|
||||||
|
is TangemPayDetailsBalanceBlockState.Loading -> TangemShimmer(
|
||||||
|
style = TangemTheme.typography3.heading.medium,
|
||||||
|
)
|
||||||
|
is TangemPayDetailsBalanceBlockState.Content -> {
|
||||||
|
val balanceColor = when {
|
||||||
|
state.isMuted -> TangemTheme.colors3.text.secondary
|
||||||
|
state.isNegative -> TangemTheme.colors3.text.status.error
|
||||||
|
else -> TangemTheme.colors3.text.primary
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.testTag(TangemPayTestTags.PAYMENT_ACCOUNT_BALANCE),
|
||||||
|
text = state.fiatBalance.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
||||||
|
style = TangemTheme.typography3.display.medium.applyBladeBrush(
|
||||||
|
isEnabled = state.isBalanceFlickering,
|
||||||
|
textColor = balanceColor,
|
||||||
|
),
|
||||||
|
color = balanceColor,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
autoSize = TextAutoSize.StepBased(
|
||||||
|
minFontSize = TangemTheme.typography3.heading.medium.fontSize,
|
||||||
|
maxFontSize = TangemTheme.typography3.display.medium.fontSize,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TangemPayDetailsBalanceBlockState.Error -> Text(
|
||||||
|
modifier = Modifier.testTag(TangemPayTestTags.PAYMENT_ACCOUNT_BALANCE),
|
||||||
|
text = DASH_SIGN.orMaskWithStars(isBalanceHidden),
|
||||||
|
style = TangemTheme.typography3.display.medium,
|
||||||
|
color = TangemTheme.colors3.text.primary,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ internal val AccountStatus.Payment.cryptoCurrency: CryptoCurrency.Token
|
||||||
get() = when (val v = value) {
|
get() = when (val v = value) {
|
||||||
is PaymentAccountStatusValue.Loaded -> v.cryptoCurrency
|
is PaymentAccountStatusValue.Loaded -> v.cryptoCurrency
|
||||||
is PaymentAccountStatusValue.Deactivated -> v.cryptoCurrency
|
is PaymentAccountStatusValue.Deactivated -> v.cryptoCurrency
|
||||||
|
is PaymentAccountStatusValue.Inactive -> v.cryptoCurrency
|
||||||
|
is PaymentAccountStatusValue.AwaitingPlanSelection -> v.cryptoCurrency
|
||||||
else -> error("TangemPayDetails opened with unsupported status: $v")
|
else -> error("TangemPayDetails opened with unsupported status: $v")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,10 @@ import com.tangem.core.ui.components.bottomsheets.message.*
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
import com.tangem.core.ui.extensions.wrappedList
|
|
||||||
import com.tangem.core.ui.message.BottomSheetMessage
|
import com.tangem.core.ui.message.BottomSheetMessage
|
||||||
import com.tangem.core.ui.message.DialogMessage
|
import com.tangem.core.ui.message.DialogMessage
|
||||||
import com.tangem.core.ui.message.bottomSheetMessage
|
import com.tangem.core.ui.message.bottomSheetMessage
|
||||||
import com.tangem.core.ui.res.generated.icons.Icons
|
import com.tangem.core.ui.res.generated.icons.Icons
|
||||||
import com.tangem.core.ui.res.generated.icons.ic_error_28
|
|
||||||
import com.tangem.core.ui.res.generated.icons.ic_snowflake_20
|
import com.tangem.core.ui.res.generated.icons.ic_snowflake_20
|
||||||
import com.tangem.core.ui.res.generated.icons.ic_sun_20
|
import com.tangem.core.ui.res.generated.icons.ic_sun_20
|
||||||
import com.tangem.features.tangempay.entity.TangemPayDetailsErrorType
|
import com.tangem.features.tangempay.entity.TangemPayDetailsErrorType
|
||||||
|
|
@ -151,26 +149,6 @@ internal object TangemPayMessagesFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createMaximumCardsIssued(maxCards: Int): BottomSheetMessage {
|
|
||||||
return bottomSheetMessage {
|
|
||||||
infoBlock {
|
|
||||||
vector(Icons.ic_error_28) {
|
|
||||||
type = MessageBottomSheetUM.Vector.Type.Attention
|
|
||||||
backgroundType = MessageBottomSheetUM.Vector.BackgroundType.Attention
|
|
||||||
}
|
|
||||||
title = resourceReference(R.string.tangempay_maximum_cards_issued_title)
|
|
||||||
body = resourceReference(
|
|
||||||
id = R.string.tangempay_maximum_cards_issued_description,
|
|
||||||
formatArgs = wrappedList(maxCards),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
primaryButton {
|
|
||||||
text = resourceReference(R.string.common_got_it)
|
|
||||||
onClick { closeBs() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
// TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
||||||
fun createStayOnPlanMessage(
|
fun createStayOnPlanMessage(
|
||||||
planName: String,
|
planName: String,
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,7 @@ internal class CashbackBlockTransformerTest {
|
||||||
fiatBalance = TextReference.EMPTY,
|
fiatBalance = TextReference.EMPTY,
|
||||||
isBalanceFlickering = false,
|
isBalanceFlickering = false,
|
||||||
isNegative = false,
|
isNegative = false,
|
||||||
|
isInactive = false,
|
||||||
),
|
),
|
||||||
addToWalletBlockState = null,
|
addToWalletBlockState = null,
|
||||||
isBalanceHidden = false,
|
isBalanceHidden = false,
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ internal class TangemPayActionButtonsTransformerTest {
|
||||||
fiatBalance = TextReference.EMPTY,
|
fiatBalance = TextReference.EMPTY,
|
||||||
isBalanceFlickering = false,
|
isBalanceFlickering = false,
|
||||||
isNegative = false,
|
isNegative = false,
|
||||||
|
isInactive = false,
|
||||||
),
|
),
|
||||||
addToWalletBlockState = null,
|
addToWalletBlockState = null,
|
||||||
isBalanceHidden = false,
|
isBalanceHidden = false,
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ internal class WalletTangemPayAnalyticsEventSender @Inject constructor(
|
||||||
PaymentAccountStatusValue.NotCreated,
|
PaymentAccountStatusValue.NotCreated,
|
||||||
is PaymentAccountStatusValue.UnderReview,
|
is PaymentAccountStatusValue.UnderReview,
|
||||||
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
||||||
|
is PaymentAccountStatusValue.Inactive,
|
||||||
is PaymentAccountStatusValue.Deactivated,
|
is PaymentAccountStatusValue.Deactivated,
|
||||||
-> return
|
-> return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -237,6 +237,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
||||||
is PaymentAccountStatusValue.Error.ExposedDevice,
|
is PaymentAccountStatusValue.Error.ExposedDevice,
|
||||||
is PaymentAccountStatusValue.IssuingCard,
|
is PaymentAccountStatusValue.IssuingCard,
|
||||||
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
||||||
|
is PaymentAccountStatusValue.Inactive,
|
||||||
is PaymentAccountStatusValue.Loaded,
|
is PaymentAccountStatusValue.Loaded,
|
||||||
is PaymentAccountStatusValue.Loading,
|
is PaymentAccountStatusValue.Loading,
|
||||||
is PaymentAccountStatusValue.UnderReview,
|
is PaymentAccountStatusValue.UnderReview,
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,7 @@ internal class GetWalletNotificationsFactory @Inject constructor(
|
||||||
is PaymentAccountStatusValue.Error.ExposedDevice,
|
is PaymentAccountStatusValue.Error.ExposedDevice,
|
||||||
is PaymentAccountStatusValue.IssuingCard,
|
is PaymentAccountStatusValue.IssuingCard,
|
||||||
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
is PaymentAccountStatusValue.AwaitingPlanSelection,
|
||||||
|
is PaymentAccountStatusValue.Inactive,
|
||||||
is PaymentAccountStatusValue.Loaded,
|
is PaymentAccountStatusValue.Loaded,
|
||||||
is PaymentAccountStatusValue.Loading,
|
is PaymentAccountStatusValue.Loading,
|
||||||
is PaymentAccountStatusValue.UnderReview,
|
is PaymentAccountStatusValue.UnderReview,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ internal class TangemPayMainBlockConverter(
|
||||||
is PaymentAccountStatusValue.AwaitingPlanSelection -> TangemPayMainUM.SelectPlan(
|
is PaymentAccountStatusValue.AwaitingPlanSelection -> TangemPayMainUM.SelectPlan(
|
||||||
onClick = { tangemPayClickIntents.onSelectPlanClicked(value) },
|
onClick = { tangemPayClickIntents.onSelectPlanClicked(value) },
|
||||||
)
|
)
|
||||||
|
is PaymentAccountStatusValue.Inactive -> TangemPayMainUM.IssuingCard(
|
||||||
|
onClick = { tangemPayClickIntents.openDetails(value) },
|
||||||
|
)
|
||||||
is PaymentAccountStatusValue.UnderReview -> TangemPayMainUM.UnderReview(
|
is PaymentAccountStatusValue.UnderReview -> TangemPayMainUM.UnderReview(
|
||||||
subtitle = when (statusValue.kycStatus) {
|
subtitle = when (statusValue.kycStatus) {
|
||||||
KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed)
|
KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue