Updated on 2026-08-14
This commit is contained in:
parent
46cf9b8b08
commit
210ba5ca59
22 changed files with 303 additions and 90 deletions
|
|
@ -18,6 +18,7 @@ import com.tangem.domain.models.wallet.isMultiCurrency
|
|||
import com.tangem.domain.nft.ObserveAndClearNFTCacheIfNeedUseCase
|
||||
import com.tangem.domain.notifications.GetIsHuaweiDeviceWithoutGoogleServicesUseCase
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.pay.usecase.TangemPayIssueOrderUseCase
|
||||
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
|
||||
import com.tangem.domain.settings.*
|
||||
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
|
||||
|
|
@ -51,6 +52,8 @@ import kotlinx.coroutines.flow.*
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val TANGEM_PAY_UPDATE_INTERVAL = 60000L
|
||||
|
||||
@Suppress("LongParameterList", "LargeClass")
|
||||
@Stable
|
||||
@ModelScoped
|
||||
|
|
@ -88,6 +91,7 @@ internal class WalletModel @Inject constructor(
|
|||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase,
|
||||
private val tangemPayIssueOrderUseCase: TangemPayIssueOrderUseCase,
|
||||
private val tangemPayStateConverter: TangemPayStateConverter,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
|
|
@ -105,6 +109,8 @@ internal class WalletModel @Inject constructor(
|
|||
|
||||
private var expressTxStatusTaskScheduler = SingleTaskScheduler<Unit>()
|
||||
|
||||
private var updateTangemPayJob: Job? = null
|
||||
|
||||
init {
|
||||
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.MainScreen.ScreenOpened)
|
||||
|
||||
|
|
@ -323,20 +329,44 @@ internal class WalletModel @Inject constructor(
|
|||
private fun subscribeToTangemPayInfo() {
|
||||
/**
|
||||
* Update state each time a user opens/returns to wallet screen
|
||||
* and every minute while user stays on the main screen
|
||||
*/
|
||||
screenLifecycleProvider.isBackgroundState.onEach { isBackground ->
|
||||
if (!isBackground) { updateTangemPayInfo() }
|
||||
screenLifecycleProvider.isBackgroundState.onEach { inBackground ->
|
||||
if (!inBackground && tangemPayFeatureToggles.isTangemPayEnabled) {
|
||||
updateTangemPayJob = modelScope.launch {
|
||||
refreshTangemPayInfo()
|
||||
while (isActive) {
|
||||
delay(TANGEM_PAY_UPDATE_INTERVAL)
|
||||
refreshTangemPayInfo()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateTangemPayJob?.cancel()
|
||||
updateTangemPayJob = null
|
||||
}
|
||||
}.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun updateTangemPayInfo() {
|
||||
if (tangemPayFeatureToggles.isTangemPayEnabled) {
|
||||
modelScope.launch {
|
||||
tangemPayMainScreenCustomerInfoUseCase()?.let { info ->
|
||||
stateHolder.update {
|
||||
it.copy(tangemPayState = tangemPayStateConverter.convert(info))
|
||||
}
|
||||
}
|
||||
private suspend fun refreshTangemPayInfo() {
|
||||
val newState = withContext(dispatchers.io) {
|
||||
tangemPayMainScreenCustomerInfoUseCase()?.let { info ->
|
||||
tangemPayStateConverter.convert(
|
||||
value = info,
|
||||
onIssueOrderClick = ::issueOrder,
|
||||
onContinueKycClick = innerWalletRouter::openTangemPayOnboarding,
|
||||
)
|
||||
}
|
||||
} ?: return
|
||||
stateHolder.update { it.copy(tangemPayState = newState) }
|
||||
}
|
||||
|
||||
private fun issueOrder() {
|
||||
modelScope.launch {
|
||||
stateHolder.update { it.copy(tangemPayState = tangemPayStateConverter.getIssueProgress()) }
|
||||
withContext(dispatchers.io) {
|
||||
tangemPayIssueOrderUseCase()
|
||||
} ?: stateHolder.update {
|
||||
it.copy(tangemPayState = tangemPayStateConverter.getIssueState(::issueOrder))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,4 +107,8 @@ internal class DefaultWalletRouter @Inject constructor(
|
|||
configuration = WalletDialogConfig.TokenReceive(tokenReceiveConfig),
|
||||
)
|
||||
}
|
||||
|
||||
override fun openTangemPayOnboarding() {
|
||||
router.push(AppRoute.TangemPayOnboarding(AppRoute.TangemPayOnboarding.Mode.ContinueOnboarding))
|
||||
}
|
||||
}
|
||||
|
|
@ -58,4 +58,6 @@ internal interface InnerWalletRouter {
|
|||
fun openNFT(userWallet: UserWallet)
|
||||
|
||||
fun openTokenReceiveBottomSheet(tokenReceiveConfig: TokenReceiveConfig)
|
||||
|
||||
fun openTangemPayOnboarding()
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ internal sealed class TangemPayState {
|
|||
val buttonText: TextReference,
|
||||
@DrawableRes val iconRes: Int,
|
||||
val onButtonClick: () -> Unit,
|
||||
val showProgress: Boolean = false,
|
||||
) : TangemPayState()
|
||||
|
||||
data class Card(
|
||||
|
|
|
|||
|
|
@ -1,48 +1,64 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
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.CustomerInfo
|
||||
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.utils.converter.Converter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState.Progress
|
||||
import java.util.Currency
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class TangemPayStateConverter @Inject constructor(
|
||||
private val router: Router,
|
||||
) : Converter<CustomerInfo, TangemPayState> {
|
||||
internal class TangemPayStateConverter @Inject constructor() {
|
||||
|
||||
override fun convert(value: CustomerInfo): TangemPayState {
|
||||
val route = AppRoute.TangemPayOnboarding(AppRoute.TangemPayOnboarding.Mode.ContinueOnboarding)
|
||||
val cardInfo = value.cardInfo
|
||||
fun convert(
|
||||
value: MainScreenCustomerInfo,
|
||||
onIssueOrderClick: () -> Unit,
|
||||
onContinueKycClick: () -> Unit,
|
||||
): TangemPayState {
|
||||
val cardInfo = value.info.cardInfo
|
||||
return when {
|
||||
!value.isKycApproved() -> 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 = { router.push(route) },
|
||||
)
|
||||
!value.isProductInstanceActive() -> TangemPayState.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 = { router.push(route) },
|
||||
)
|
||||
!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 -> TangemPayState.Empty
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
|
@ -16,31 +15,31 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState.Progress
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TangemPayCardMainBlock
|
||||
|
||||
@Composable
|
||||
internal fun TangemPayMainScreenBlock(state: TangemPayState, modifier: Modifier = Modifier) {
|
||||
AnimatedVisibility(state !is TangemPayState.Empty) {
|
||||
when (state) {
|
||||
is TangemPayState.Progress -> {
|
||||
Notification(
|
||||
modifier = modifier
|
||||
.fillMaxWidth(),
|
||||
config = NotificationConfig(
|
||||
title = state.title,
|
||||
iconSize = 36.dp,
|
||||
subtitle = TextReference.EMPTY,
|
||||
iconResId = state.iconRes,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = state.buttonText,
|
||||
onClick = state.onButtonClick,
|
||||
),
|
||||
when (state) {
|
||||
is Progress -> {
|
||||
Notification(
|
||||
modifier = modifier
|
||||
.fillMaxWidth(),
|
||||
config = NotificationConfig(
|
||||
title = state.title,
|
||||
iconSize = 36.dp,
|
||||
subtitle = TextReference.EMPTY,
|
||||
iconResId = state.iconRes,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = state.buttonText,
|
||||
onClick = state.onButtonClick,
|
||||
showProgress = state.showProgress,
|
||||
),
|
||||
)
|
||||
}
|
||||
is TangemPayState.Card -> TangemPayCardMainBlock(state, modifier)
|
||||
is TangemPayState.Empty -> Unit
|
||||
),
|
||||
)
|
||||
}
|
||||
is TangemPayState.Card -> TangemPayCardMainBlock(state, modifier)
|
||||
is TangemPayState.Empty -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +50,7 @@ private fun ResetCardScreenPreview() {
|
|||
TangemThemePreview {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
|
||||
TangemPayMainScreenBlock(
|
||||
TangemPayState.Progress(
|
||||
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,
|
||||
|
|
@ -60,7 +59,7 @@ private fun ResetCardScreenPreview() {
|
|||
)
|
||||
|
||||
TangemPayMainScreenBlock(
|
||||
TangemPayState.Progress(
|
||||
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,
|
||||
|
|
@ -68,6 +67,16 @@ private fun ResetCardScreenPreview() {
|
|||
),
|
||||
)
|
||||
|
||||
TangemPayMainScreenBlock(
|
||||
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,
|
||||
),
|
||||
)
|
||||
|
||||
TangemPayMainScreenBlock(
|
||||
TangemPayState.Card(
|
||||
lastFourDigits = TextReference.Str("*1234"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue