Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-04 16:45:10 +03:00
parent 4fe3bc5401
commit b17ed42664
5 changed files with 119 additions and 63 deletions

View file

@ -19,13 +19,9 @@ 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.model.MainScreenCustomerInfo
import com.tangem.domain.pay.model.TangemPayCustomerInfoError
import com.tangem.domain.pay.repository.OnboardingRepository
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
import com.tangem.domain.settings.*
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
import com.tangem.domain.visa.model.TangemPayCardFrozenState
import com.tangem.domain.wallets.usecase.*
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyUpdateUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
@ -98,7 +94,6 @@ internal class WalletModel @Inject constructor(
private val tangemPayOnboardingRepository: OnboardingRepository,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
private val accountsFeatureToggles: AccountsFeatureToggles,
private val cardDetailsRepository: TangemPayCardDetailsRepository,
private val tangemPayMainInfoManager: TangemPayMainInfoManager,
val screenLifecycleProvider: ScreenLifecycleProvider,
val innerWalletRouter: InnerWalletRouter,
@ -137,7 +132,6 @@ internal class WalletModel @Inject constructor(
subscribeToScreenBackgroundState()
subscribeOnPushNotificationsPermission()
subscribeTangemPayOnWalletState()
subscribeOnTangemPayInfoUpdates()
enableNotificationsIfNeeded()
clickIntents.initialize(innerWalletRouter, modelScope)
@ -387,62 +381,6 @@ internal class WalletModel @Inject constructor(
}.launchIn(modelScope)
}
private fun subscribeOnTangemPayInfoUpdates() {
if (!tangemPayFeatureToggles.isTangemPayEnabled) return
tangemPayMainInfoManager.mainScreenCustomerInfo
.filterNotNull()
.distinctUntilChanged()
.onEach { (userWalletId, mainInfoData) ->
mainInfoData.onLeft { tangemPayError ->
when (tangemPayError) {
TangemPayCustomerInfoError.RefreshNeededError -> {
stateHolder.update(
transformer = TangemPayRefreshNeededStateTransformer(
userWalletId = userWalletId,
onRefreshClick = { clickIntents.onRefreshPayToken(userWalletId) },
),
)
}
TangemPayCustomerInfoError.UnavailableError -> {
stateHolder.update(
transformer = TangemPayUnavailableStateTransformer(userWalletId),
)
}
else -> {
// hide TangemPay block
Timber.e("Failed when loading main screen TangemPay info: $tangemPayError")
stateHolder.update(
transformer = TangemPayHiddenStateTransformer(userWalletId),
)
}
}
}.onRight { data -> updateTangemPay(data, userWalletId) }
}
.launchIn(modelScope)
}
private suspend fun updateTangemPay(data: MainScreenCustomerInfo, userWalletId: UserWalletId) {
val cardFrozenState =
data.info.productInstance?.cardId?.let { cardDetailsRepository.cardFrozenStateSync(it) }
?: TangemPayCardFrozenState.Unfrozen
stateHolder.update(
transformer = TangemPayUpdateInfoStateTransformer(
userWalletId = userWalletId,
value = data,
cardFrozenState = cardFrozenState,
onClickKyc = innerWalletRouter::openTangemPayOnboarding,
onIssuingCard = clickIntents::onIssuingCardClicked,
onIssuingFailed = clickIntents::onIssuingFailedClicked,
openDetails = { config ->
innerWalletRouter.openTangemPayDetails(
userWalletId = userWalletId,
config = config,
)
},
),
)
}
private fun needToRefreshTimer() {
modelScope.launch {
delay(REFRESH_WALLET_BACKGROUND_TIMER_MILLIS)

View file

@ -21,6 +21,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsCheck
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.tangempay.TangemPayFeatureToggles
@Suppress("LongParameterList")
@Deprecated("Use MultiWalletContentLoaderV2 instead")
@ -45,6 +46,8 @@ internal class MultiWalletContentLoader(
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
private val stakingApyFlowUseCase: StakingApyFlowUseCase,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
private val tangemPayMainSubscriberFactory: TangemPayMainSubscriber.Factory,
) : WalletContentLoader(id = userWallet.walletId) {
override fun create(): List<WalletSubscriber> {
@ -92,6 +95,10 @@ internal class MultiWalletContentLoader(
clickIntents = clickIntents,
hotWalletFeatureToggles = hotWalletFeatureToggles,
).let(::add)
if (tangemPayFeatureToggles.isTangemPayEnabled) {
add(tangemPayMainSubscriberFactory.create(userWallet))
}
}
}
}

View file

@ -19,7 +19,9 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.subscribers.TangemPayMainSubscriber
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.tangempay.TangemPayFeatureToggles
import javax.inject.Inject
@Suppress("LongParameterList")
@ -43,6 +45,8 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
private val stakingApyFlowUseCase: StakingApyFlowUseCase,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
private val tangemPayMainSubscriberFactory: TangemPayMainSubscriber.Factory,
) {
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): WalletContentLoader {
@ -66,6 +70,8 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
stakingApyFlowUseCase = stakingApyFlowUseCase,
hotWalletFeatureToggles = hotWalletFeatureToggles,
tangemPayFeatureToggles = tangemPayFeatureToggles,
tangemPayMainSubscriberFactory = tangemPayMainSubscriberFactory,
)
}
}

View file

@ -10,6 +10,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.tangempay.TangemPayFeatureToggles
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -28,9 +29,11 @@ internal class MultiWalletContentLoaderV2 @AssistedInject constructor(
private val getStoryContentUseCase: GetStoryContentUseCase,
private val checkWalletWithFundsSubscriberFactory: CheckWalletWithFundsSubscriber.Factory,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
private val tangemPayMainSubscriberFactory: TangemPayMainSubscriber.Factory,
) : WalletContentLoader(id = userWallet.walletId) {
override fun create(): List<WalletSubscriber> = listOf(
override fun create(): List<WalletSubscriber> = listOfNotNull(
accountListSubscriberFactory.create(userWallet = userWallet),
walletNFTListSubscriberV2Factory.create(userWallet = userWallet),
checkWalletWithFundsSubscriberFactory.create(userWallet = userWallet),
@ -53,6 +56,12 @@ internal class MultiWalletContentLoaderV2 @AssistedInject constructor(
clickIntents = clickIntents,
hotWalletFeatureToggles = hotWalletFeatureToggles,
),
if (tangemPayFeatureToggles.isTangemPayEnabled) {
tangemPayMainSubscriberFactory.create(userWallet)
} else {
null
},
)
@AssistedFactory

View file

@ -0,0 +1,96 @@
package com.tangem.feature.wallet.presentation.wallet.subscribers
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.model.MainScreenCustomerInfo
import com.tangem.domain.pay.model.TangemPayCustomerInfoError
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
import com.tangem.domain.visa.model.TangemPayCardFrozenState
import com.tangem.feature.wallet.child.wallet.model.TangemPayMainInfoManager
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayHiddenStateTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayRefreshNeededStateTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayUnavailableStateTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayUpdateInfoStateTransformer
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.*
import timber.log.Timber
internal class TangemPayMainSubscriber @AssistedInject constructor(
@Assisted private val userWallet: UserWallet,
private val stateController: WalletStateController,
private val clickIntents: WalletClickIntents,
private val innerWalletRouter: InnerWalletRouter,
private val cardDetailsRepository: TangemPayCardDetailsRepository,
private val tangemPayMainInfoManager: TangemPayMainInfoManager,
) : WalletSubscriber() {
override fun create(coroutineScope: CoroutineScope): Flow<*> {
return subscribeOnTangemPayInfoUpdates()
}
private fun subscribeOnTangemPayInfoUpdates(): Flow<*> {
return tangemPayMainInfoManager.mainScreenCustomerInfo
.filterNotNull()
.filter { it.first == userWallet.walletId }
.distinctUntilChanged()
.onEach { (userWalletId, mainInfoData) ->
mainInfoData.onLeft { tangemPayError ->
when (tangemPayError) {
TangemPayCustomerInfoError.RefreshNeededError -> {
stateController.update(
transformer = TangemPayRefreshNeededStateTransformer(
userWalletId = userWalletId,
onRefreshClick = { clickIntents.onRefreshPayToken(userWalletId) },
),
)
}
TangemPayCustomerInfoError.UnavailableError -> {
stateController.update(
transformer = TangemPayUnavailableStateTransformer(userWalletId),
)
}
else -> {
// hide TangemPay block
Timber.e("Failed when loading main screen TangemPay info: $tangemPayError")
stateController.update(
transformer = TangemPayHiddenStateTransformer(userWalletId),
)
}
}
}.onRight { data -> updateTangemPay(data, userWalletId) }
}
}
private suspend fun updateTangemPay(data: MainScreenCustomerInfo, userWalletId: UserWalletId) {
val cardFrozenState =
data.info.productInstance?.cardId?.let { cardDetailsRepository.cardFrozenStateSync(it) }
?: TangemPayCardFrozenState.Unfrozen
stateController.update(
transformer = TangemPayUpdateInfoStateTransformer(
userWalletId = userWalletId,
value = data,
cardFrozenState = cardFrozenState,
onClickKyc = innerWalletRouter::openTangemPayOnboarding,
onIssuingCard = clickIntents::onIssuingCardClicked,
onIssuingFailed = clickIntents::onIssuingFailedClicked,
openDetails = { config ->
innerWalletRouter.openTangemPayDetails(
userWalletId = userWalletId,
config = config,
)
},
),
)
}
@AssistedFactory
interface Factory {
fun create(userWallet: UserWallet): TangemPayMainSubscriber
}
}