Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-29 16:40:30 +04:00
parent 210ba5ca59
commit a89f2c7225
5 changed files with 124 additions and 103 deletions

View file

@ -35,7 +35,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent.DemonstrateWalletsScrollPreview.Direction
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
import com.tangem.feature.wallet.presentation.wallet.state.transformers.*
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TangemPayStateConverter
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import com.tangem.features.biometry.AskBiometryComponent
@ -52,7 +51,7 @@ import kotlinx.coroutines.flow.*
import timber.log.Timber
import javax.inject.Inject
private const val TANGEM_PAY_UPDATE_INTERVAL = 60000L
private const val TANGEM_PAY_UPDATE_INTERVAL = 60_000L
@Suppress("LongParameterList", "LargeClass")
@Stable
@ -92,7 +91,6 @@ internal class WalletModel @Inject constructor(
private val userWalletsListRepository: UserWalletsListRepository,
private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase,
private val tangemPayIssueOrderUseCase: TangemPayIssueOrderUseCase,
private val tangemPayStateConverter: TangemPayStateConverter,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
val screenLifecycleProvider: ScreenLifecycleProvider,
val innerWalletRouter: InnerWalletRouter,
@ -106,11 +104,10 @@ internal class WalletModel @Inject constructor(
private val refreshWalletJobHolder = JobHolder()
private var needToRefreshWallet = false
private val clearNFTCacheJobHolder = JobHolder()
private val updateTangemPayJobHolder = JobHolder()
private var expressTxStatusTaskScheduler = SingleTaskScheduler<Unit>()
private var updateTangemPayJob: Job? = null
init {
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.MainScreen.ScreenOpened)
@ -332,17 +329,15 @@ internal class WalletModel @Inject constructor(
* and every minute while user stays on the main screen
*/
screenLifecycleProvider.isBackgroundState.onEach { inBackground ->
updateTangemPayJobHolder.cancel()
if (!inBackground && tangemPayFeatureToggles.isTangemPayEnabled) {
updateTangemPayJob = modelScope.launch {
modelScope.launch {
refreshTangemPayInfo()
while (isActive) {
delay(TANGEM_PAY_UPDATE_INTERVAL)
refreshTangemPayInfo()
}
}
} else {
updateTangemPayJob?.cancel()
updateTangemPayJob = null
}.saveIn(updateTangemPayJobHolder)
}
}.launchIn(modelScope)
}
@ -350,11 +345,11 @@ internal class WalletModel @Inject constructor(
private suspend fun refreshTangemPayInfo() {
val newState = withContext(dispatchers.io) {
tangemPayMainScreenCustomerInfoUseCase()?.let { info ->
tangemPayStateConverter.convert(
TangemPayStateTransformer(
value = info,
onIssueOrderClick = ::issueOrder,
onContinueKycClick = innerWalletRouter::openTangemPayOnboarding,
)
).transform(stateHolder.uiState.value.tangemPayState)
}
} ?: return
stateHolder.update { it.copy(tangemPayState = newState) }
@ -362,11 +357,19 @@ internal class WalletModel @Inject constructor(
private fun issueOrder() {
modelScope.launch {
stateHolder.update { it.copy(tangemPayState = tangemPayStateConverter.getIssueProgress()) }
stateHolder.update {
it.copy(
tangemPayState = TangemPayStateTransformer(issueProgressState = true)
.transform(it.tangemPayState),
)
}
withContext(dispatchers.io) {
tangemPayIssueOrderUseCase()
} ?: stateHolder.update {
it.copy(tangemPayState = tangemPayStateConverter.getIssueState(::issueOrder))
it.copy(
tangemPayState = TangemPayStateTransformer(issueState = true, onIssueOrderClick = ::issueOrder)
.transform(it.tangemPayState),
)
}
}
}

View file

@ -0,0 +1,74 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.common.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.domain.pay.model.CustomerInfo.CardInfo
import com.tangem.domain.pay.model.MainScreenCustomerInfo
import com.tangem.domain.pay.model.OrderStatus.NOT_ISSUED
import com.tangem.domain.pay.model.OrderStatus.CANCELED
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState.Progress
import com.tangem.utils.transformer.Transformer
import java.util.Currency
internal class TangemPayStateTransformer(
private val value: MainScreenCustomerInfo? = null,
private val onIssueOrderClick: () -> Unit = {},
private val onContinueKycClick: () -> Unit = {},
private val issueProgressState: Boolean = false,
private val issueState: Boolean = false,
) : Transformer<TangemPayState> {
override fun transform(prevState: TangemPayState): TangemPayState = when {
issueProgressState -> createIssueProgressState()
issueState -> createIssueState()
else -> createInitialState()
}
private fun createInitialState(): TangemPayState {
val cardInfo = value?.info?.cardInfo
return when {
value == null -> TangemPayState.Empty
!value.info.isKycApproved() -> createKycInProgressState(onContinueKycClick)
value.orderStatus == NOT_ISSUED || value.orderStatus == CANCELED -> createIssueState()
cardInfo != null -> getCardInfoState(cardInfo)
else -> createIssueProgressState()
}
}
private fun createIssueProgressState(): TangemPayState = Progress(
title = TextReference.Res(R.string.tangempay_issue_card_notification_title),
buttonText = TextReference.EMPTY,
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
onButtonClick = {},
showProgress = true,
)
private fun createIssueState() = Progress(
title = TextReference.Res(R.string.tangempay_issue_card_notification_title),
buttonText = TextReference.Res(R.string.common_continue),
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
onButtonClick = onIssueOrderClick,
)
private fun createKycInProgressState(onContinueKycClick: () -> Unit): TangemPayState = Progress(
title = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_title),
buttonText = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_button),
iconRes = R.drawable.ic_promo_kyc_36,
onButtonClick = onContinueKycClick,
)
private fun getCardInfoState(cardInfo: CardInfo): TangemPayState = TangemPayState.Card(
lastFourDigits = TextReference.Str("*${cardInfo.lastFourDigits}"),
balanceText = TextReference.Str(getBalanceText(cardInfo)),
)
private fun getBalanceText(cardInfo: CardInfo): String {
val currency = Currency.getInstance(cardInfo.currencyCode)
return cardInfo.balance.format {
fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol)
}
}
}

View file

@ -1,68 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
import com.tangem.common.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.domain.pay.model.CustomerInfo.CardInfo
import com.tangem.domain.pay.model.MainScreenCustomerInfo
import com.tangem.domain.pay.model.OrderStatus
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState.Progress
import java.util.Currency
import javax.inject.Inject
internal class TangemPayStateConverter @Inject constructor() {
fun convert(
value: MainScreenCustomerInfo,
onIssueOrderClick: () -> Unit,
onContinueKycClick: () -> Unit,
): TangemPayState {
val cardInfo = value.info.cardInfo
return when {
!value.info.isKycApproved() -> {
Progress(
title = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_title),
buttonText = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_button),
iconRes = R.drawable.ic_promo_kyc_36,
onButtonClick = onContinueKycClick,
)
}
value.orderStatus == OrderStatus.NOT_ISSUED || value.orderStatus == OrderStatus.CANCELED -> {
getIssueState(onIssueOrderClick)
}
cardInfo != null -> {
TangemPayState.Card(
lastFourDigits = TextReference.Str("*${cardInfo.lastFourDigits}"),
balanceText = TextReference.Str(getBalanceText(cardInfo)),
)
}
else -> {
getIssueProgress()
}
}
}
fun getIssueProgress(): TangemPayState = Progress(
title = TextReference.Res(R.string.tangempay_issue_card_notification_title),
buttonText = TextReference.EMPTY,
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
onButtonClick = {},
showProgress = true,
)
fun getIssueState(onIssueOrderClick: () -> Unit) = Progress(
title = TextReference.Res(R.string.tangempay_issue_card_notification_title),
buttonText = TextReference.Res(R.string.common_continue),
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
onButtonClick = onIssueOrderClick,
)
private fun getBalanceText(cardInfo: CardInfo): String {
val currency = Currency.getInstance(cardInfo.currencyCode)
return cardInfo.balance.format {
fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol)
}
}
}