Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-29 20:50:41 +05:00
parent f086d6bb74
commit 40fe8bb5cb
56 changed files with 82 additions and 1491 deletions

View file

@ -27,10 +27,6 @@
"name": "GASLESS_APPROVAL_ENABLED", "name": "GASLESS_APPROVAL_ENABLED",
"version": "5.37" "version": "5.37"
}, },
{
"name": "TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED",
"version": "5.37"
},
{ {
"name": "DYNAMIC_ADDRESSES_ENABLED", "name": "DYNAMIC_ADDRESSES_ENABLED",
"version": "undefined" "version": "undefined"

View file

@ -10,6 +10,6 @@ data class ReissueCardResponse(
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class Result( data class Result(
@Json(name = "order_id") val orderId: String, @Json(name = "order_id") val orderId: String,
@Json(name = "status") val status: String, @Json(name = "status") val status: OrderResponse.Result.Status,
) )
} }

View file

@ -36,8 +36,6 @@ dependencies {
api(projects.domain.visa) api(projects.domain.visa)
// endregion // endregion
implementation(projects.features.tangempay.details.api) // Remove after TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED
// region Project - Data // region Project - Data
implementation(projects.data.common) implementation(projects.data.common)
// endregion // endregion

View file

@ -11,7 +11,6 @@ import com.tangem.domain.common.wallets.getSyncStrict
import com.tangem.domain.core.flow.FlowProducerTools import com.tangem.domain.core.flow.FlowProducerTools
import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.Account
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.hot.sdk.model.HotWalletId import com.tangem.hot.sdk.model.HotWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.assisted.Assisted import dagger.assisted.Assisted
@ -36,7 +35,6 @@ internal class DefaultSingleAccountListProducer @AssistedInject constructor(
@Assisted val params: SingleAccountListProducer.Params, @Assisted val params: SingleAccountListProducer.Params,
override val flowProducerTools: FlowProducerTools, override val flowProducerTools: FlowProducerTools,
private val walletAccountListFlowFactory: WalletAccountListFlowFactory, private val walletAccountListFlowFactory: WalletAccountListFlowFactory,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
private val userWalletsListRepository: UserWalletsListRepository, private val userWalletsListRepository: UserWalletsListRepository,
private val dispatchers: CoroutineDispatcherProvider, private val dispatchers: CoroutineDispatcherProvider,
) : SingleAccountListProducer { ) : SingleAccountListProducer {
@ -45,16 +43,6 @@ internal class DefaultSingleAccountListProducer @AssistedInject constructor(
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
override fun produce(): Flow<AccountList> { override fun produce(): Flow<AccountList> {
val accountListFlow: Flow<AccountList> = if (tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled) {
combineWithPaymentAccount()
} else {
walletAccountListFlowFactory.create(userWalletId = params.userWalletId)
}
return accountListFlow.flowOn(dispatchers.default)
}
private fun combineWithPaymentAccount(): Flow<AccountList> {
return walletAccountListFlowFactory.create(params.userWalletId) return walletAccountListFlowFactory.create(params.userWalletId)
.map { accountList -> .map { accountList ->
val userWallet = userWalletsListRepository.getSyncStrict(id = params.userWalletId) val userWallet = userWalletsListRepository.getSyncStrict(id = params.userWalletId)
@ -66,6 +54,7 @@ internal class DefaultSingleAccountListProducer @AssistedInject constructor(
accountList accountList
} }
} }
.flowOn(dispatchers.default)
} }
private fun UserWallet.isPaymentAccountSupported(): Boolean = when (this) { private fun UserWallet.isPaymentAccountSupported(): Boolean = when (this) {

View file

@ -8,7 +8,7 @@ import com.tangem.domain.core.flow.FlowProducerTools
import com.tangem.domain.models.TokensSortType import com.tangem.domain.models.TokensSortType
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.features.tangempay.TangemPayFeatureToggles import com.tangem.hot.sdk.model.HotWalletId
import com.tangem.test.core.getEmittedValues import com.tangem.test.core.getEmittedValues
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.* import io.mockk.*
@ -31,21 +31,22 @@ class DefaultSingleAccountListProducerTest {
private val userWalletId = UserWalletId("011") private val userWalletId = UserWalletId("011")
private val flowProducerTools: FlowProducerTools = mockk() private val flowProducerTools: FlowProducerTools = mockk()
private val tangemPayFeatureToggles = mockk<TangemPayFeatureToggles> { private val userWallet = mockk<UserWallet.Hot> {
every { this@mockk.isTangemPayAccountsRefactorEnabled } returns false every { walletId } returns userWalletId
every { hotWalletId } returns mockk {
every { authType } returns HotWalletId.AuthType.NoPassword
}
} }
private val userWalletsListRepository = mockk<UserWalletsListRepository>() private val userWalletsListRepository = mockk<UserWalletsListRepository> {
private val userWallet = mockk<UserWallet> { every { userWallets } returns MutableStateFlow<List<UserWallet>?>(value = listOf(userWallet))
every { this@mockk.walletId } returns userWalletId
} }
private val producer = DefaultSingleAccountListProducer( private val producer = DefaultSingleAccountListProducer(
params = SingleAccountListProducer.Params(userWalletId = userWalletId), params = SingleAccountListProducer.Params(userWalletId = userWalletId),
walletAccountListFlowFactory = walletAccountListFlowFactory, walletAccountListFlowFactory = walletAccountListFlowFactory,
dispatchers = TestingCoroutineDispatcherProvider(),
flowProducerTools = flowProducerTools, flowProducerTools = flowProducerTools,
tangemPayFeatureToggles = tangemPayFeatureToggles,
userWalletsListRepository = userWalletsListRepository, userWalletsListRepository = userWalletsListRepository,
dispatchers = TestingCoroutineDispatcherProvider(),
) )
@AfterEach @AfterEach
@ -56,8 +57,6 @@ class DefaultSingleAccountListProducerTest {
@Test @Test
fun produce() = runTest { fun produce() = runTest {
// Arrange // Arrange
MutableStateFlow(listOf(userWallet))
val accountList = AccountList.empty(userWalletId) val accountList = AccountList.empty(userWalletId)
every { walletAccountListFlowFactory.create(userWalletId) } returns flowOf(accountList) every { walletAccountListFlowFactory.create(userWalletId) } returns flowOf(accountList)

View file

@ -11,7 +11,6 @@ import com.tangem.data.pay.converter.PaymentAccountStatusValueDMConverter
import com.tangem.data.pay.flow.DefaultPaymentAccountStatusFetcher import com.tangem.data.pay.flow.DefaultPaymentAccountStatusFetcher
import com.tangem.data.pay.flow.DefaultPaymentAccountStatusProducer import com.tangem.data.pay.flow.DefaultPaymentAccountStatusProducer
import com.tangem.data.pay.repository.* import com.tangem.data.pay.repository.*
import com.tangem.domain.pay.repository.TangemPayReissueCardRepository
import com.tangem.data.pay.store.PaymentAccountStatusesStore import com.tangem.data.pay.store.PaymentAccountStatusesStore
import com.tangem.data.pay.usecase.DefaultGetTangemPayCurrencyStatusUseCase import com.tangem.data.pay.usecase.DefaultGetTangemPayCurrencyStatusUseCase
import com.tangem.data.pay.usecase.DefaultGetTangemPayCustomerIdUseCase import com.tangem.data.pay.usecase.DefaultGetTangemPayCustomerIdUseCase
@ -30,12 +29,10 @@ import com.tangem.domain.pay.repository.*
import com.tangem.domain.pay.usecase.GetPaymentAccountCryptoCurrencyStatusUseCase import com.tangem.domain.pay.usecase.GetPaymentAccountCryptoCurrencyStatusUseCase
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
import com.tangem.domain.pay.usecase.SetTangemPayCardLimitUseCase import com.tangem.domain.pay.usecase.SetTangemPayCardLimitUseCase
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
import com.tangem.domain.tangempay.GetTangemPayCurrencyStatusUseCase import com.tangem.domain.tangempay.GetTangemPayCurrencyStatusUseCase
import com.tangem.domain.tangempay.GetTangemPayCustomerIdUseCase import com.tangem.domain.tangempay.GetTangemPayCustomerIdUseCase
import com.tangem.domain.tangempay.TangemPayWithdrawUseCase import com.tangem.domain.tangempay.TangemPayWithdrawUseCase
import com.tangem.domain.tangempay.repository.TangemPayTxHistoryRepository import com.tangem.domain.tangempay.repository.TangemPayTxHistoryRepository
import com.tangem.security.DeviceSecurityInfoProvider
import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.utils.coroutines.AppCoroutineScope
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Binds import dagger.Binds
@ -167,23 +164,6 @@ internal interface TangemPayDataModule {
return GetPaymentAccountCryptoCurrencyStatusUseCase(paymentAccountStatusSupplier) return GetPaymentAccountCryptoCurrencyStatusUseCase(paymentAccountStatusSupplier)
} }
@Provides
@Singleton
fun provideTangemPayMainScreenCustomerInfoUseCase(
repository: OnboardingRepository,
customerOrderRepository: CustomerOrderRepository,
tangemPayOnboardingRepository: OnboardingRepository,
eligibilityManager: TangemPayEligibilityManager,
deviceSecurity: DeviceSecurityInfoProvider,
): TangemPayMainScreenCustomerInfoUseCase {
return TangemPayMainScreenCustomerInfoUseCase(
onboardingRepository = repository,
customerOrderRepository = customerOrderRepository,
eligibilityManager = eligibilityManager,
deviceSecurity = deviceSecurity,
)
}
@Provides @Provides
@Singleton @Singleton
fun provideProduceTangemPayInitialDataUseCase( fun provideProduceTangemPayInitialDataUseCase(

View file

@ -11,8 +11,8 @@ import com.tangem.domain.models.account.PaymentAccountStatusValue
import com.tangem.domain.models.kyc.KycStatus import com.tangem.domain.models.kyc.KycStatus
import com.tangem.domain.models.pay.TangemPayCard import com.tangem.domain.models.pay.TangemPayCard
import com.tangem.domain.models.pay.TangemPayCardLimitData import com.tangem.domain.models.pay.TangemPayCardLimitData
import com.tangem.domain.pay.TangemPayEligibilityManager
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.TangemPayEligibilityManager
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
import com.tangem.domain.pay.model.CustomerInfo import com.tangem.domain.pay.model.CustomerInfo
import com.tangem.domain.pay.model.OrderData import com.tangem.domain.pay.model.OrderData
@ -188,7 +188,6 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
when (orderData.status) { when (orderData.status) {
OrderStatus.CANCELED -> handleCanceledOrder(account, orderData) OrderStatus.CANCELED -> handleCanceledOrder(account, orderData)
OrderStatus.COMPLETED -> handleCompletedOrder(account) OrderStatus.COMPLETED -> handleCompletedOrder(account)
OrderStatus.UNKNOWN -> PaymentAccountStatusValue.Error.Unavailable
OrderStatus.NEW, OrderStatus.NEW,
OrderStatus.PROCESSING, OrderStatus.PROCESSING,
-> { -> {
@ -228,7 +227,6 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
OrderStatus.COMPLETED -> return handleCompletedOrder(account) OrderStatus.COMPLETED -> return handleCompletedOrder(account)
OrderStatus.NEW, OrderStatus.NEW,
OrderStatus.PROCESSING, OrderStatus.PROCESSING,
OrderStatus.UNKNOWN,
-> Unit // Continue polling -> Unit // Continue polling
} }
}, },

View file

@ -1,8 +1,8 @@
package com.tangem.data.pay.repository package com.tangem.data.pay.repository
import arrow.core.Either import arrow.core.Either
import com.tangem.data.pay.util.OrderStatusConverter
import com.tangem.datasource.api.pay.TangemPayApi import com.tangem.datasource.api.pay.TangemPayApi
import com.tangem.datasource.api.pay.models.response.OrderResponse
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.model.OrderData import com.tangem.domain.pay.model.OrderData
import com.tangem.domain.pay.model.OrderStatus import com.tangem.domain.pay.model.OrderStatus
@ -19,13 +19,7 @@ internal class DefaultCustomerOrderRepository @Inject constructor(
return requestHelper.performRequest(userWalletId) { authHeader -> return requestHelper.performRequest(userWalletId) { authHeader ->
tangemPayApi.getOrder(authHeader = authHeader, orderId = orderId) tangemPayApi.getOrder(authHeader = authHeader, orderId = orderId)
}.map { response -> }.map { response ->
val status = when (response.result?.status) { val status = response.result?.status?.let(OrderStatusConverter::convert) ?: OrderStatus.PROCESSING
null -> OrderStatus.PROCESSING
OrderResponse.Result.Status.NEW -> OrderStatus.NEW
OrderResponse.Result.Status.PROCESSING -> OrderStatus.PROCESSING
OrderResponse.Result.Status.COMPLETED -> OrderStatus.COMPLETED
OrderResponse.Result.Status.CANCELED -> OrderStatus.CANCELED
}
OrderData( OrderData(
customerId = response.result?.customerId.orEmpty(), customerId = response.result?.customerId.orEmpty(),
status = status, status = status,

View file

@ -4,6 +4,7 @@ import arrow.core.Either
import arrow.core.raise.either import arrow.core.raise.either
import arrow.core.right import arrow.core.right
import com.tangem.core.error.UniversalError import com.tangem.core.error.UniversalError
import com.tangem.data.pay.util.OrderStatusConverter
import com.tangem.datasource.api.pay.TangemPayApi import com.tangem.datasource.api.pay.TangemPayApi
import com.tangem.datasource.api.pay.models.request.ReissueCardRequest import com.tangem.datasource.api.pay.models.request.ReissueCardRequest
import com.tangem.datasource.api.pay.models.response.OrderResponse import com.tangem.datasource.api.pay.models.response.OrderResponse
@ -59,8 +60,10 @@ internal class DefaultReissueCardRepository @Inject constructor(
body = ReissueCardRequest(cardId = cardId), body = ReissueCardRequest(cardId = cardId),
) )
}.bind() }.bind()
TangemPayReissueOrderInfo(
TangemPayReissueOrderInfo(response.result.orderId, OrderStatus.fromString(response.result.status)) orderId = response.result.orderId,
orderStatus = OrderStatusConverter.convert(response.result.status),
)
} }
override suspend fun storeReissueOrderId(cardId: String, orderId: String): Either<UniversalError, Unit> = override suspend fun storeReissueOrderId(cardId: String, orderId: String): Either<UniversalError, Unit> =

View file

@ -0,0 +1,16 @@
package com.tangem.data.pay.util
import com.tangem.datasource.api.pay.models.response.OrderResponse
import com.tangem.domain.pay.model.OrderStatus
import com.tangem.utils.converter.Converter
internal object OrderStatusConverter : Converter<OrderResponse.Result.Status, OrderStatus> {
override fun convert(value: OrderResponse.Result.Status): OrderStatus {
return when (value) {
OrderResponse.Result.Status.PROCESSING -> OrderStatus.PROCESSING
OrderResponse.Result.Status.COMPLETED -> OrderStatus.COMPLETED
OrderResponse.Result.Status.NEW -> OrderStatus.NEW
OrderResponse.Result.Status.CANCELED -> OrderStatus.CANCELED
}
}
}

View file

@ -1,7 +1,6 @@
package com.tangem.domain.tokens.wallet package com.tangem.domain.tokens.wallet
import arrow.core.Either import arrow.core.Either
import arrow.core.right
import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory
import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.UserWalletsListRepository
@ -147,18 +146,10 @@ class WalletBalanceFetcher internal constructor(
fetchExpressAssets(userWallet = userWallet, currencies = currencies) fetchExpressAssets(userWallet = userWallet, currencies = currencies)
fetcher.fetch( fetcher.fetch(userWalletId = userWalletId, currencies = currencies)
userWalletId = userWalletId,
currencies = currencies,
paymentAccountRefactorEnabled = params.isPaymentAccountRefactorEnabled,
)
} }
private suspend fun BaseWalletBalanceFetcher.fetch( private suspend fun BaseWalletBalanceFetcher.fetch(userWalletId: UserWalletId, currencies: Set<CryptoCurrency>) {
userWalletId: UserWalletId,
currencies: Set<CryptoCurrency>,
paymentAccountRefactorEnabled: Boolean,
) {
coroutineScope { coroutineScope {
// Fetch balance sources in parallel // Fetch balance sources in parallel
val balanceErrors = fetchingSources.filterIsInstance<WalletFetchingSource.Balance>() val balanceErrors = fetchingSources.filterIsInstance<WalletFetchingSource.Balance>()
@ -182,7 +173,7 @@ class WalletBalanceFetcher internal constructor(
// Fetch TangemPay separately — may run long-polling, so it must not block balance error checking // Fetch TangemPay separately — may run long-polling, so it must not block balance error checking
if (fetchingSources.any { it is WalletFetchingSource.TangemPay }) { if (fetchingSources.any { it is WalletFetchingSource.TangemPay }) {
fetchPaymentAccount(userWalletId, paymentAccountRefactorEnabled) paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
} }
} }
} }
@ -197,19 +188,10 @@ class WalletBalanceFetcher internal constructor(
expressServiceFetcher.fetch(userWallet = userWallet, assetIds = assetIds) expressServiceFetcher.fetch(userWallet = userWallet, assetIds = assetIds)
} }
private suspend fun fetchPaymentAccount(
userWalletId: UserWalletId,
paymentAccountRefactorEnabled: Boolean,
): Either<Throwable, Unit> {
if (!paymentAccountRefactorEnabled) return Unit.right()
return paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
}
/** /**
* Params of [WalletBalanceFetcher] * Params of [WalletBalanceFetcher]
* *
* @property userWalletId user wallet id * @property userWalletId user wallet id
*/ */
data class Params(val userWalletId: UserWalletId, val isPaymentAccountRefactorEnabled: Boolean) data class Params(val userWalletId: UserWalletId)
} }

View file

@ -96,7 +96,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -133,7 +132,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -171,7 +169,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -209,7 +206,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -260,7 +256,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -315,7 +310,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -376,7 +370,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -428,7 +421,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -479,7 +471,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -536,7 +527,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -607,7 +597,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -682,7 +671,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -743,7 +731,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -802,7 +789,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )
@ -869,7 +855,6 @@ internal class WalletBalanceFetcherTest {
val actual = fetcher( val actual = fetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = false,
), ),
) )

View file

@ -1,22 +1,8 @@
package com.tangem.domain.pay.model package com.tangem.domain.pay.model
import java.util.Locale
enum class OrderStatus { enum class OrderStatus {
UNKNOWN, // TODO remove it after TangemPay accounts refactor TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED
NEW, NEW,
PROCESSING, PROCESSING,
COMPLETED, COMPLETED,
CANCELED, CANCELED,
;
companion object {
fun fromString(value: String) = when (value.uppercase(Locale.US)) {
"NEW" -> NEW
"PROCESSING" -> PROCESSING
"COMPLETED" -> COMPLETED
"CANCELED" -> CANCELED
else -> UNKNOWN
}
}
} }

View file

@ -1,179 +0,0 @@
package com.tangem.domain.pay.usecase
import arrow.core.Either
import arrow.core.left
import arrow.core.right
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.TangemPayEligibilityManager
import com.tangem.domain.pay.model.*
import com.tangem.domain.pay.repository.CustomerOrderRepository
import com.tangem.domain.pay.repository.OnboardingRepository
import com.tangem.domain.visa.error.VisaApiError
import com.tangem.security.DeviceSecurityInfoProvider
import com.tangem.security.isSecurityExposed
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.flow.*
class TangemPayMainScreenCustomerInfoUseCase(
private val onboardingRepository: OnboardingRepository,
private val customerOrderRepository: CustomerOrderRepository,
private val eligibilityManager: TangemPayEligibilityManager,
private val deviceSecurity: DeviceSecurityInfoProvider,
) {
val state: StateFlow<Map<UserWalletId, Either<TangemPayCustomerInfoError, MainCustomerInfoContentState>>>
field = MutableStateFlow(value = mapOf())
private val logger = TangemLogger.withTag("TangemPayMainScreenCustomerInfoUseCase")
suspend fun fetch(userWalletId: UserWalletId) {
logger.i("fetch: ${userWalletId.stringValue}")
if (onboardingRepository.isTangemPayDeactivated(userWalletId)) {
updateState(userWalletId, MainCustomerInfoContentState.Empty.right())
return
}
if (deviceSecurity.isSecurityExposed()) {
logger.i("fetch security info: rooted: ${deviceSecurity.isRooted}")
logger.i("fetch security info: xposed: ${deviceSecurity.isXposed}")
logger.i("fetch security info: bootloader unlocked: ${deviceSecurity.isBootloaderUnlocked}")
updateState(userWalletId = userWalletId, either = TangemPayCustomerInfoError.ExposedDeviceError.left())
return // fast exit
}
onboardingRepository.hasTangemPayInWallet(userWalletId)
.fold(
ifLeft = { error ->
logger.e("Failed checkCustomerWallet for $userWalletId: ${error.javaClass.simpleName}")
if (error is VisaApiError.NotPaeraCustomer) {
showOnboardingBannerIfEligible(userWalletId)
} else {
updateState(userWalletId, TangemPayCustomerInfoError.UnknownError.left())
}
},
ifRight = { hasTangemPay ->
logger.i("checkCustomerWallet for $userWalletId: $hasTangemPay")
if (hasTangemPay) {
val oldResult = state.value[userWalletId]
if (oldResult == null) {
updateState(userWalletId, MainCustomerInfoContentState.Loading.right())
}
val result = proceedWithPaeraCustomerResult(userWalletId)
if (result.leftOrNull() is TangemPayCustomerInfoError.DeactivatedError) {
updateState(userWalletId, MainCustomerInfoContentState.Empty.right())
return
}
updateState(userWalletId, result.map(MainCustomerInfoContentState::Content))
} else {
// if there's no tangem pay, check eligibility and show onboarding banner
showOnboardingBannerIfEligible(userWalletId)
}
},
)
}
private suspend fun showOnboardingBannerIfEligible(userWalletId: UserWalletId) {
val tangemPayEntryPoint = TangemPayEntryPoint.BANNER
if (eligibilityManager.isPaeraCustomerForAnyWallet(tangemPayEntryPoint)) {
updateState(userWalletId, MainCustomerInfoContentState.Empty.right())
return
}
val isEligible = eligibilityManager
.getEligibleWallets(
shouldExcludePaeraCustomers = false,
entryPoint = tangemPayEntryPoint,
)
.any { it.walletId == userWalletId }
if (isEligible) {
if (onboardingRepository.getHideMainOnboardingBanner(userWalletId)) {
updateState(userWalletId, MainCustomerInfoContentState.Empty.right())
} else {
updateState(userWalletId, MainCustomerInfoContentState.OnboardingBanner.right())
}
} else {
updateState(userWalletId, MainCustomerInfoContentState.Empty.right())
}
}
operator fun invoke(
userWalletId: UserWalletId,
): Flow<Either<TangemPayCustomerInfoError, MainCustomerInfoContentState>> {
return state.mapNotNull { map -> map[userWalletId] }
}
private fun updateState(
userWalletId: UserWalletId,
either: Either<TangemPayCustomerInfoError, MainCustomerInfoContentState>,
) {
state.update { currentMap ->
currentMap.toMutableMap().apply { this[userWalletId] = either }
}
}
private suspend fun proceedWithPaeraCustomerResult(
userWalletId: UserWalletId,
): Either<TangemPayCustomerInfoError, MainScreenCustomerInfo> {
if (!onboardingRepository.isTangemPayInitialDataProduced(userWalletId)) {
return TangemPayCustomerInfoError.RefreshNeededError.left()
}
val orderId = onboardingRepository.getOrderId(userWalletId)
return if (orderId != null) {
proceedWithOrderId(userWalletId = userWalletId, orderId = orderId)
} else {
proceedWithoutOrder(userWalletId = userWalletId)
}
}
private suspend fun proceedWithoutOrder(
userWalletId: UserWalletId,
): Either<TangemPayCustomerInfoError, MainScreenCustomerInfo> {
return onboardingRepository.getCustomerInfo(userWalletId)
.mapLeft { error ->
logger.e("mapErrorForCustomer: $error")
error.mapErrorForCustomer()
}
.map { customerInfo ->
logger.i("customerInfo")
if (customerInfo.productInstance == null) {
onboardingRepository.createOrder(userWalletId)
MainScreenCustomerInfo(info = customerInfo, orderStatus = OrderStatus.NEW)
} else {
MainScreenCustomerInfo(info = customerInfo, orderStatus = OrderStatus.COMPLETED)
}
}
}
private suspend fun proceedWithOrderId(
userWalletId: UserWalletId,
orderId: String,
): Either<TangemPayCustomerInfoError, MainScreenCustomerInfo> {
return customerOrderRepository.getOrderData(userWalletId, orderId = orderId)
.fold(
ifLeft = { error ->
error.mapErrorForCustomer().left()
},
ifRight = { orderData ->
if (orderData.status in setOf(OrderStatus.COMPLETED, OrderStatus.UNKNOWN)) {
onboardingRepository.clearOrderId(userWalletId)
}
onboardingRepository.getCustomerInfo(userWalletId = userWalletId)
.mapLeft { it.mapErrorForCustomer() }
.map { customerInfo ->
MainScreenCustomerInfo(info = customerInfo, orderStatus = orderData.status)
}
},
)
}
private fun VisaApiError.mapErrorForCustomer(): TangemPayCustomerInfoError {
return when (this) {
is VisaApiError.RefreshTokenExpired -> TangemPayCustomerInfoError.RefreshNeededError
is VisaApiError.NotPaeraCustomer -> TangemPayCustomerInfoError.UnknownError
is VisaApiError.Deactivated -> TangemPayCustomerInfoError.DeactivatedError
else -> TangemPayCustomerInfoError.UnavailableError
}
}
}

View file

@ -19,7 +19,6 @@ dependencies {
implementation(projects.features.disclaimer.api) implementation(projects.features.disclaimer.api)
implementation(projects.features.tester.api) implementation(projects.features.tester.api)
implementation(projects.features.createWalletSelection.api) implementation(projects.features.createWalletSelection.api)
implementation(projects.features.tangempay.details.api)
implementation(projects.features.onboardingV2.api) implementation(projects.features.onboardingV2.api)
/* Project - Core */ /* Project - Core */

View file

@ -1,5 +1,3 @@
package com.tangem.features.tangempay package com.tangem.features.tangempay
interface TangemPayFeatureToggles { interface TangemPayFeatureToggles
val isTangemPayAccountsRefactorEnabled: Boolean
}

View file

@ -1,11 +1,3 @@
package com.tangem.features.tangempay package com.tangem.features.tangempay
import com.tangem.core.configtoggle.FeatureToggles internal class DefaultTangemPayFeatureToggles : TangemPayFeatureToggles
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
internal class DefaultTangemPayFeatureToggles(
private val featureTogglesManager: FeatureTogglesManager,
) : TangemPayFeatureToggles {
override val isTangemPayAccountsRefactorEnabled
get() = featureTogglesManager.isFeatureEnabled(FeatureToggles.TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED)
}

View file

@ -1,6 +1,5 @@
package com.tangem.features.tangempay.di package com.tangem.features.tangempay.di
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
import com.tangem.features.tangempay.DefaultTangemPayFeatureToggles import com.tangem.features.tangempay.DefaultTangemPayFeatureToggles
import com.tangem.features.tangempay.TangemPayFeatureToggles import com.tangem.features.tangempay.TangemPayFeatureToggles
import dagger.Module import dagger.Module
@ -15,7 +14,7 @@ internal object TangemPayDetailsModule {
@Provides @Provides
@Singleton @Singleton
fun provideTangemPayFeatureToggles(featureTogglesManager: FeatureTogglesManager): TangemPayFeatureToggles { fun provideTangemPayFeatureToggles(): TangemPayFeatureToggles {
return DefaultTangemPayFeatureToggles(featureTogglesManager) return DefaultTangemPayFeatureToggles()
} }
} }

View file

@ -303,7 +303,7 @@ internal class TangemPayCardPageModel @Inject constructor(
private fun onReissueOrderStatusReceived(orderStatus: OrderStatus) { private fun onReissueOrderStatusReceived(orderStatus: OrderStatus) {
when (orderStatus) { when (orderStatus) {
OrderStatus.NEW, OrderStatus.PROCESSING, OrderStatus.COMPLETED, OrderStatus.UNKNOWN -> { OrderStatus.NEW, OrderStatus.PROCESSING, OrderStatus.COMPLETED -> {
uiState.update { state -> uiState.update { state ->
state.copy( state.copy(
addToWalletBlockState = null, addToWalletBlockState = null,

View file

@ -111,7 +111,6 @@ dependencies {
implementation(projects.features.sendV2.api) implementation(projects.features.sendV2.api)
implementation(projects.features.tokenRecieve.api) implementation(projects.features.tokenRecieve.api)
implementation(projects.features.yieldSupply.api) implementation(projects.features.yieldSupply.api)
implementation(projects.features.tangempay.details.api)
implementation(deps.decompose.ext.compose) implementation(deps.decompose.ext.compose)

View file

@ -23,7 +23,6 @@ import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.SelectWalletUseCase import com.tangem.domain.wallets.usecase.SelectWalletUseCase
import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.features.tokendetails.deeplink.TokenDetailsDeepLinkHandler import com.tangem.features.tokendetails.deeplink.TokenDetailsDeepLinkHandler
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionTrigger import com.tangem.features.wallet.deeplink.WalletDeepLinkActionTrigger
import com.tangem.utils.logging.TangemLogger import com.tangem.utils.logging.TangemLogger
@ -47,7 +46,6 @@ internal class DefaultTokenDetailsDeepLinkHandler @AssistedInject constructor(
private val getUserWalletUseCase: GetUserWalletUseCase, private val getUserWalletUseCase: GetUserWalletUseCase,
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
private val walletBalanceFetcher: WalletBalanceFetcher, private val walletBalanceFetcher: WalletBalanceFetcher,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
private val singleAccountListSupplier: SingleAccountListSupplier, private val singleAccountListSupplier: SingleAccountListSupplier,
) : TokenDetailsDeepLinkHandler { ) : TokenDetailsDeepLinkHandler {
@ -133,10 +131,7 @@ internal class DefaultTokenDetailsDeepLinkHandler @AssistedInject constructor(
currency = cryptoCurrency, currency = cryptoCurrency,
) )
!isMultiCurrency -> walletBalanceFetcher( !isMultiCurrency -> walletBalanceFetcher(
params = WalletBalanceFetcher.Params( params = WalletBalanceFetcher.Params(userWalletId = userWallet.walletId),
userWalletId = userWallet.walletId,
isPaymentAccountRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
),
) )
} }
} }

View file

@ -25,7 +25,6 @@ import com.tangem.domain.wallets.models.GetUserWalletError
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.SelectWalletUseCase import com.tangem.domain.wallets.usecase.SelectWalletUseCase
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionTrigger import com.tangem.features.wallet.deeplink.WalletDeepLinkActionTrigger
import com.tangem.utils.logging.TangemLogger import com.tangem.utils.logging.TangemLogger
import io.mockk.* import io.mockk.*
@ -50,7 +49,6 @@ class DefaultTokenDetailsDeepLinkHandlerTest {
private val analyticsEventHandler: AnalyticsEventHandler = mockk() private val analyticsEventHandler: AnalyticsEventHandler = mockk()
private val getUserWalletUseCase: GetUserWalletUseCase = mockk() private val getUserWalletUseCase: GetUserWalletUseCase = mockk()
private val walletBalanceFetcher: WalletBalanceFetcher = mockk() private val walletBalanceFetcher: WalletBalanceFetcher = mockk()
private val tangemPayFeatureToggles: TangemPayFeatureToggles = mockk()
private val singleAccountListSupplier: SingleAccountListSupplier = mockk() private val singleAccountListSupplier: SingleAccountListSupplier = mockk()
@BeforeEach @BeforeEach
@ -443,12 +441,10 @@ class DefaultTokenDetailsDeepLinkHandlerTest {
userWalletId = userWalletId, userWalletId = userWalletId,
cryptoCurrencies = listOf(expectedCryptoCurrency), cryptoCurrencies = listOf(expectedCryptoCurrency),
) )
every { tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled } returns true
coEvery { coEvery {
walletBalanceFetcher.invoke( walletBalanceFetcher.invoke(
WalletBalanceFetcher.Params( WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = true
) )
) )
} returns mockk() } returns mockk()
@ -460,7 +456,6 @@ class DefaultTokenDetailsDeepLinkHandlerTest {
walletBalanceFetcher.invoke( walletBalanceFetcher.invoke(
WalletBalanceFetcher.Params( WalletBalanceFetcher.Params(
userWalletId = userWalletId, userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = true
) )
) )
} }
@ -483,7 +478,6 @@ class DefaultTokenDetailsDeepLinkHandlerTest {
analyticsEventHandler = analyticsEventHandler, analyticsEventHandler = analyticsEventHandler,
getUserWalletUseCase = getUserWalletUseCase, getUserWalletUseCase = getUserWalletUseCase,
walletBalanceFetcher = walletBalanceFetcher, walletBalanceFetcher = walletBalanceFetcher,
tangemPayFeatureToggles = tangemPayFeatureToggles,
singleAccountListSupplier = singleAccountListSupplier, singleAccountListSupplier = singleAccountListSupplier,
getSelectedWalletSyncUseCase = getSelectedWalletSync, getSelectedWalletSyncUseCase = getSelectedWalletSync,
) )

View file

@ -147,7 +147,6 @@ dependencies {
implementation(projects.features.kyc.api) implementation(projects.features.kyc.api)
implementation(projects.features.tokenRecieve.api) implementation(projects.features.tokenRecieve.api)
implementation(projects.features.yieldSupply.api) implementation(projects.features.yieldSupply.api)
implementation(projects.features.tangempay.details.api)
implementation(projects.features.feed.api) implementation(projects.features.feed.api)
implementation(projects.features.promoBanners.api) implementation(projects.features.promoBanners.api)
implementation(projects.features.tangempay.main.api) implementation(projects.features.tangempay.main.api)

View file

@ -14,12 +14,13 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.datasource.local.appsflyer.AppsFlyerStore import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.account.status.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.account.status.usecase.IsAccountsModeEnabledUseCase
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.apptheme.GetAppThemeModeUseCase import com.tangem.domain.apptheme.GetAppThemeModeUseCase
import com.tangem.domain.apptheme.model.AppThemeMode import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.models.wallet.* import com.tangem.domain.models.wallet.*
@ -27,7 +28,6 @@ import com.tangem.domain.notifications.GetIsHuaweiDeviceWithoutGoogleServicesUse
import com.tangem.domain.notifications.repository.NotificationsRepository import com.tangem.domain.notifications.repository.NotificationsRepository
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
import com.tangem.domain.pay.repository.OnboardingRepository import com.tangem.domain.pay.repository.OnboardingRepository
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
import com.tangem.domain.qrscanning.models.ClassifiedQrContent import com.tangem.domain.qrscanning.models.ClassifiedQrContent
import com.tangem.domain.qrscanning.models.QrResultSource import com.tangem.domain.qrscanning.models.QrResultSource
import com.tangem.domain.qrscanning.models.QrSendTarget import com.tangem.domain.qrscanning.models.QrSendTarget
@ -38,8 +38,6 @@ import com.tangem.domain.settings.*
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
import com.tangem.domain.walletconnect.WcPairService import com.tangem.domain.walletconnect.WcPairService
import com.tangem.domain.walletconnect.model.WcPairRequest import com.tangem.domain.walletconnect.model.WcPairRequest
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.domain.wallets.usecase.* import com.tangem.domain.wallets.usecase.*
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyUpdateUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyApyUpdateUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
@ -62,15 +60,15 @@ import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSend
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejectedCallbacks import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejectedCallbacks
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import com.tangem.features.biometry.AskBiometryComponent import com.tangem.features.biometry.AskBiometryComponent
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
import com.tangem.utils.Provider import com.tangem.utils.Provider
import com.tangem.utils.coroutines.* import com.tangem.utils.coroutines.*
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import com.tangem.utils.logging.TangemLogger
import javax.inject.Inject import javax.inject.Inject
private const val TANGEM_PAY_UPDATE_INTERVAL = 60_000L private const val TANGEM_PAY_UPDATE_INTERVAL = 60_000L
@ -108,7 +106,6 @@ internal class WalletModel @Inject constructor(
private val userWalletsListRepository: UserWalletsListRepository, private val userWalletsListRepository: UserWalletsListRepository,
private val yieldSupplyApyUpdateUseCase: YieldSupplyApyUpdateUseCase, private val yieldSupplyApyUpdateUseCase: YieldSupplyApyUpdateUseCase,
private val tangemPayOnboardingRepository: OnboardingRepository, private val tangemPayOnboardingRepository: OnboardingRepository,
private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase,
private val getAppThemeModeUseCase: GetAppThemeModeUseCase, private val getAppThemeModeUseCase: GetAppThemeModeUseCase,
private val trackingContextProxy: TrackingContextProxy, private val trackingContextProxy: TrackingContextProxy,
private val singleAccountListSupplier: SingleAccountListSupplier, private val singleAccountListSupplier: SingleAccountListSupplier,
@ -121,7 +118,6 @@ internal class WalletModel @Inject constructor(
private val wcPairService: WcPairService, private val wcPairService: WcPairService,
private val resolveQrSendTargetsUseCase: ResolveQrSendTargetsUseCase, private val resolveQrSendTargetsUseCase: ResolveQrSendTargetsUseCase,
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher, private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
private val uiMessageSender: UiMessageSender, private val uiMessageSender: UiMessageSender,
private val hotWalletFeatureToggles: HotWalletFeatureToggles, private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase, private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
@ -436,17 +432,14 @@ internal class WalletModel @Inject constructor(
if (isShouldLaunchPeriodicUpdate) { if (isShouldLaunchPeriodicUpdate) {
updateTangemPayJobHolder.cancel() updateTangemPayJobHolder.cancel()
modelScope.launch { modelScope.launch {
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId)) paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
while (isActive) { while (isActive) {
delay(TANGEM_PAY_UPDATE_INTERVAL) delay(TANGEM_PAY_UPDATE_INTERVAL)
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId)) paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
} }
}.saveIn(updateTangemPayJobHolder) }.saveIn(updateTangemPayJobHolder)
} else { } else {
// Don't refresh customer info periodically if the card was already issued, only update on swipe to refresh // Don't refresh customer info periodically if the card was already issued, only update on swipe to refresh
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId)) paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
} }
}.launchIn(modelScope) }.launchIn(modelScope)
@ -555,7 +548,6 @@ internal class WalletModel @Inject constructor(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
), ),
) )
@ -602,7 +594,6 @@ internal class WalletModel @Inject constructor(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
), ),
) )
} }
@ -624,7 +615,6 @@ internal class WalletModel @Inject constructor(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
), ),
) )
} }
@ -639,7 +629,6 @@ internal class WalletModel @Inject constructor(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
), ),
) )
@ -701,7 +690,6 @@ internal class WalletModel @Inject constructor(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
), ),
) )

View file

@ -22,11 +22,10 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.TangemPayDetailsConfig import com.tangem.domain.pay.TangemPayDetailsConfig
import com.tangem.domain.pay.TangemPayEligibilityManager import com.tangem.domain.pay.TangemPayEligibilityManager
import com.tangem.domain.pay.model.TangemPayEntryPoint
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
import com.tangem.domain.pay.model.TangemPayEntryPoint
import com.tangem.domain.pay.repository.OnboardingRepository import com.tangem.domain.pay.repository.OnboardingRepository
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig
@ -72,7 +71,6 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
private val produceInitialDataTangemPay: ProduceTangemPayInitialDataUseCase, private val produceInitialDataTangemPay: ProduceTangemPayInitialDataUseCase,
private val getWalletMetainfoUseCase: GetWalletMetaInfoUseCase, private val getWalletMetainfoUseCase: GetWalletMetaInfoUseCase,
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase,
private val tangemPayOnboardingRepository: OnboardingRepository, private val tangemPayOnboardingRepository: OnboardingRepository,
private val tangemPayEligibilityManager: TangemPayEligibilityManager, private val tangemPayEligibilityManager: TangemPayEligibilityManager,
private val uiMessageSender: UiMessageSender, private val uiMessageSender: UiMessageSender,
@ -85,7 +83,6 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
if (!onboardingRepository.isTangemPayInitialDataProduced(userWalletId)) { if (!onboardingRepository.isTangemPayInitialDataProduced(userWalletId)) {
return return
} }
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId)) paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
} }
@ -100,7 +97,6 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
modelScope.launch { modelScope.launch {
produceInitialDataTangemPay.invoke(userWallet.walletId) produceInitialDataTangemPay.invoke(userWallet.walletId)
.onRight { .onRight {
tangemPayMainScreenCustomerInfoUseCase.fetch(userWallet.walletId)
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWallet.walletId)) paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWallet.walletId))
} }
.onLeft { .onLeft {
@ -277,7 +273,6 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
modelScope.launch { modelScope.launch {
tangemPayOnboardingRepository.disableTangemPay(userWalletId) tangemPayOnboardingRepository.disableTangemPay(userWalletId)
.onRight { .onRight {
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId)) paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
} }
.onLeft { uiMessageSender.send(ToastMessage(resourceReference(R.string.common_something_went_wrong))) } .onLeft { uiMessageSender.send(ToastMessage(resourceReference(R.string.common_something_went_wrong))) }

View file

@ -217,15 +217,8 @@ internal object WalletScreenPreviewDataLegacy {
isFlickering = false, isFlickering = false,
onItemClick = { }, onItemClick = { },
), ),
tangemPayState = TangemPayState.Card(
lastFourDigits = stringReference("*1234"),
balanceText = stringReference("$10"),
balanceSymbol = stringReference("USDC"),
onClick = {},
),
type = WalletType.Cold, type = WalletType.Cold,
tangemPayMainUM = TangemPayMainUM.Empty, tangemPayMainUM = TangemPayMainUM.Empty,
isTangemPayRefactorEnabled = false,
) )
} }

View file

@ -2,9 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.analytics.utils
import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.di.ModelScoped
import com.tangem.domain.models.kyc.KycStatus import com.tangem.domain.models.account.PaymentAccountStatusValue
import com.tangem.domain.pay.model.MainScreenCustomerInfo
import com.tangem.domain.pay.model.OrderStatus
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import javax.inject.Inject import javax.inject.Inject
@ -15,26 +13,23 @@ internal class WalletTangemPayAnalyticsEventSender @Inject constructor(
private val screenLifecycleProvider: ScreenLifecycleProvider, private val screenLifecycleProvider: ScreenLifecycleProvider,
) { ) {
private val sentEvents = mutableSetOf<TangemPayAnalyticsEvents>() private val sentEvents = mutableSetOf<String>()
fun send(customerInfo: MainScreenCustomerInfo) { fun send(statusValue: PaymentAccountStatusValue) {
if (screenLifecycleProvider.isBackgroundState.value) return if (screenLifecycleProvider.isBackgroundState.value) return
val cardInfo = customerInfo.info.cardInfo val event = when (statusValue) {
val productInstance = customerInfo.info.productInstance is PaymentAccountStatusValue.IssuingCard -> TangemPayAnalyticsEvents.IssuingBannerDisplayed()
PaymentAccountStatusValue.Empty,
// TODO: TangemPay refactor analytics is PaymentAccountStatusValue.Error,
// when statement copied from TangemPayUpdateInfoStateTransformer. Be careful when editing is PaymentAccountStatusValue.Loaded,
val event = when { PaymentAccountStatusValue.Loading,
// ignore cancelled state on analytics PaymentAccountStatusValue.NotCreated,
customerInfo.orderStatus == OrderStatus.CANCELED -> return is PaymentAccountStatusValue.UnderReview,
// ignore kyc not approved state on analytics -> return
customerInfo.info.kycStatus != KycStatus.APPROVED -> return
cardInfo != null && productInstance != null -> return
else -> TangemPayAnalyticsEvents.IssuingBannerDisplayed()
} }
if (sentEvents.add(event)) { if (sentEvents.add(event.id)) {
analyticsEventHandler.send(event) analyticsEventHandler.send(event)
} }
} }

View file

@ -2,16 +2,15 @@ package com.tangem.feature.wallet.presentation.wallet.domain
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.tokens.wallet.WalletBalanceFetcher import com.tangem.domain.tokens.wallet.WalletBalanceFetcher
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveInAndJoin import com.tangem.utils.coroutines.saveInAndJoin
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import com.tangem.utils.logging.TangemLogger
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -28,7 +27,6 @@ import javax.inject.Singleton
internal class WalletContentFetcher @Inject constructor( internal class WalletContentFetcher @Inject constructor(
private val walletBalanceFetcher: WalletBalanceFetcher, private val walletBalanceFetcher: WalletBalanceFetcher,
private val dispatchers: CoroutineDispatcherProvider, private val dispatchers: CoroutineDispatcherProvider,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
) { ) {
private val fetchingJobMap = ConcurrentHashMap<UserWalletId, JobHolder>() private val fetchingJobMap = ConcurrentHashMap<UserWalletId, JobHolder>()
@ -66,12 +64,8 @@ internal class WalletContentFetcher @Inject constructor(
TangemLogger.d("Start fetching for $userWalletId") TangemLogger.d("Start fetching for $userWalletId")
val maybeResult = launch { val maybeResult = launch {
walletBalanceFetcher( walletBalanceFetcher(params = WalletBalanceFetcher.Params(userWalletId = userWalletId))
params = WalletBalanceFetcher.Params( .onLeft { TangemLogger.e("Error", it) }
userWalletId = userWalletId,
isPaymentAccountRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
),
).onLeft { TangemLogger.e("Error", it) }
} }
.saveInAndJoin(jobHolder) .saveInAndJoin(jobHolder)

View file

@ -1,49 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.model
import androidx.annotation.DrawableRes
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.extensions.TextReference
@Immutable
internal sealed class TangemPayState {
object Empty : TangemPayState()
data object Loading : TangemPayState()
data class OnboardingBanner(
val onClick: () -> Unit,
val closeOnClick: () -> Unit,
) : TangemPayState()
data class Progress(
val title: TextReference,
val description: TextReference,
val buttonText: TextReference,
@DrawableRes val iconRes: Int,
val onButtonClick: () -> Unit,
val showProgress: Boolean = false,
) : TangemPayState()
data class FailedIssue(
val title: TextReference,
val description: TextReference,
@DrawableRes val iconRes: Int,
val onButtonClick: () -> Unit,
) : TangemPayState()
data class Card(
val lastFourDigits: TextReference,
val balanceText: TextReference,
val balanceSymbol: TextReference,
val onClick: () -> Unit,
) : TangemPayState()
data class RefreshNeeded(
val notification: WalletNotification,
) : TangemPayState()
data class TemporaryUnavailable(val notification: WalletNotification) : TangemPayState()
data object ExposedDevice : TangemPayState()
}

View file

@ -24,9 +24,7 @@ internal sealed interface WalletState : WalletStateHolder {
abstract val tokensListState: WalletTokensListState abstract val tokensListState: WalletTokensListState
abstract val nftState: WalletNFTItemUM abstract val nftState: WalletNFTItemUM
abstract val type: WalletType abstract val type: WalletType
abstract val tangemPayState: TangemPayState
abstract val tangemPayMainUM: TangemPayMainUM abstract val tangemPayMainUM: TangemPayMainUM
abstract val isTangemPayRefactorEnabled: Boolean // TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED
abstract val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM abstract val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM
data class Content( data class Content(
@ -38,9 +36,7 @@ internal sealed interface WalletState : WalletStateHolder {
override val tokensListState: WalletTokensListState, override val tokensListState: WalletTokensListState,
override val nftState: WalletNFTItemUM, override val nftState: WalletNFTItemUM,
override val type: WalletType, override val type: WalletType,
override val tangemPayState: TangemPayState,
override val tangemPayMainUM: TangemPayMainUM, override val tangemPayMainUM: TangemPayMainUM,
override val isTangemPayRefactorEnabled: Boolean,
override val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle, override val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle,
) : MultiCurrency() ) : MultiCurrency()
@ -60,9 +56,7 @@ internal sealed interface WalletState : WalletStateHolder {
override val tokensListState = WalletTokensListState.ContentState.Locked override val tokensListState = WalletTokensListState.ContentState.Locked
override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden
override val tangemPayState: TangemPayState = TangemPayState.Empty
override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty
override val isTangemPayRefactorEnabled: Boolean = false
override val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle override val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle
} }
} }

View file

@ -13,7 +13,6 @@ internal class AddWalletTransformer(
private val clickIntents: WalletClickIntents, private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver, private val walletImageResolver: WalletImageResolver,
private val getWalletIconUseCase: GetWalletIconUseCase, private val getWalletIconUseCase: GetWalletIconUseCase,
private val isTangemPayRefactorEnabled: Boolean,
) : WalletScreenStateTransformer { ) : WalletScreenStateTransformer {
private val walletLoadingStateFactory by lazy { private val walletLoadingStateFactory by lazy {
@ -21,7 +20,6 @@ internal class AddWalletTransformer(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
) )
} }

View file

@ -27,7 +27,6 @@ internal class InitializeWalletsTransformer(
private val clickIntents: WalletClickIntents, private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver, private val walletImageResolver: WalletImageResolver,
private val getWalletIconUseCase: GetWalletIconUseCase, private val getWalletIconUseCase: GetWalletIconUseCase,
private val isTangemPayRefactorEnabled: Boolean,
) : WalletScreenStateTransformer { ) : WalletScreenStateTransformer {
private val walletLoadingStateFactory by lazy { private val walletLoadingStateFactory by lazy {
@ -35,7 +34,6 @@ internal class InitializeWalletsTransformer(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
) )
} }

View file

@ -24,7 +24,6 @@ internal class ReinitializeNewWalletTransformer(
private val clickIntents: WalletClickIntents, private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver, private val walletImageResolver: WalletImageResolver,
private val getWalletIconUseCase: GetWalletIconUseCase, private val getWalletIconUseCase: GetWalletIconUseCase,
private val isTangemPayRefactorEnabled: Boolean,
) : WalletScreenStateTransformer { ) : WalletScreenStateTransformer {
private val walletLoadingStateFactory by lazy { private val walletLoadingStateFactory by lazy {
@ -32,7 +31,6 @@ internal class ReinitializeNewWalletTransformer(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
) )
} }

View file

@ -20,7 +20,6 @@ internal class ReinitializeWalletTransformer(
private val clickIntents: WalletClickIntents, private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver, private val walletImageResolver: WalletImageResolver,
private val getWalletIconUseCase: GetWalletIconUseCase, private val getWalletIconUseCase: GetWalletIconUseCase,
private val isTangemPayRefactorEnabled: Boolean,
) : WalletStateTransformer(userWalletId = userWallet.walletId) { ) : WalletStateTransformer(userWalletId = userWallet.walletId) {
private val walletLoadingStateFactory by lazy { private val walletLoadingStateFactory by lazy {
@ -28,7 +27,6 @@ internal class ReinitializeWalletTransformer(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
) )
} }

View file

@ -1,22 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
internal class TangemPayExposedDeviceTransformer(
userWalletId: UserWalletId,
) : WalletStateTransformer(userWalletId) {
override fun transform(prevState: WalletState): WalletState {
return if (prevState is WalletState.MultiCurrency.Content) {
prevState.copy(tangemPayState = TangemPayState.ExposedDevice)
} else {
prevState
}
}
override fun transform(walletUM: WalletUM): WalletUM {
return walletUM // todo redesign main
}
}

View file

@ -1,23 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
internal class TangemPayHiddenStateTransformer(
userWalletId: UserWalletId,
) : WalletStateTransformer(userWalletId) {
override fun transform(prevState: WalletState): WalletState {
return if (prevState is WalletState.MultiCurrency.Content) {
prevState.copy(tangemPayState = TangemPayState.Empty)
} else {
prevState
}
}
override fun transform(walletUM: WalletUM): WalletUM {
return walletUM // todo redesign main
}
}

View file

@ -1,7 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
import com.tangem.features.tangempay.entity.TangemPayMainUM import com.tangem.features.tangempay.entity.TangemPayMainUM
@ -12,7 +11,7 @@ internal class TangemPayHideOnboardingStateTransformer(
override fun transform(prevState: WalletState): WalletState { override fun transform(prevState: WalletState): WalletState {
return if (prevState is WalletState.MultiCurrency.Content) { return if (prevState is WalletState.MultiCurrency.Content) {
prevState.copy(tangemPayState = TangemPayState.Empty, tangemPayMainUM = TangemPayMainUM.Empty) prevState.copy(tangemPayMainUM = TangemPayMainUM.Empty)
} else { } else {
prevState prevState
} }

View file

@ -1,20 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
internal class TangemPayLoadingStateTransformer(userWalletId: UserWalletId) : WalletStateTransformer(userWalletId) {
override fun transform(prevState: WalletState): WalletState {
return if (prevState is WalletState.MultiCurrency.Content) {
prevState.copy(tangemPayState = TangemPayState.Loading)
} else {
prevState
}
}
override fun transform(walletUM: WalletUM): WalletUM {
return walletUM // todo redesign main
}
}

View file

@ -1,30 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
internal class TangemPayOnboardingBannerStateTransformer(
userWalletId: UserWalletId,
private val onClick: (UserWalletId) -> Unit,
private val closeOnClick: (UserWalletId) -> Unit,
) : WalletStateTransformer(userWalletId) {
override fun transform(prevState: WalletState): WalletState {
return if (prevState is WalletState.MultiCurrency.Content) {
prevState.copy(
tangemPayState = TangemPayState.OnboardingBanner(
onClick = { onClick(userWalletId) },
closeOnClick = { closeOnClick(userWalletId) },
),
)
} else {
prevState
}
}
override fun transform(walletUM: WalletUM): WalletUM {
return walletUM // todo redesign main
}
}

View file

@ -1,39 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification.Warning.TangemPayRefreshNeeded
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
internal class TangemPayRefreshNeededStateTransformer(
userWalletId: UserWalletId,
private val userWallet: UserWallet,
private val onRefreshClick: () -> Unit,
) : WalletStateTransformer(userWalletId = userWalletId) {
override fun transform(prevState: WalletState): WalletState {
val tangemPayState = TangemPayState.RefreshNeeded(
notification = TangemPayRefreshNeeded(
buttonText = when (userWallet) {
is UserWallet.Cold -> resourceReference(id = R.string.home_button_scan)
is UserWallet.Hot -> resourceReference(id = R.string.tangempay_sync_needed_restore_access)
},
onRefreshClick = onRefreshClick,
shouldShowProgress = false,
),
)
return if (prevState is WalletState.MultiCurrency.Content) {
prevState.copy(tangemPayState = tangemPayState)
} else {
prevState
}
}
override fun transform(walletUM: WalletUM): WalletUM {
return walletUM // todo redesign main
}
}

View file

@ -1,7 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
@ -14,9 +13,6 @@ internal class TangemPayRefreshShowProgressTransformer(
override fun transform(prevState: WalletState): WalletState { override fun transform(prevState: WalletState): WalletState {
val multiContentState = prevState as? WalletState.MultiCurrency.Content ?: return prevState val multiContentState = prevState as? WalletState.MultiCurrency.Content ?: return prevState
val refreshNeededState = multiContentState.tangemPayState as? TangemPayState.RefreshNeeded ?: return prevState
val refreshNotification =
refreshNeededState.notification as? WalletNotification.Warning.TangemPayRefreshNeeded ?: return prevState
val newWarnings = prevState.warnings.map { warning -> val newWarnings = prevState.warnings.map { warning ->
if (warning is WalletNotification.Warning.TangemPayRefreshNeeded) { if (warning is WalletNotification.Warning.TangemPayRefreshNeeded) {
warning.copy(shouldShowProgress = shouldShowProgress) warning.copy(shouldShowProgress = shouldShowProgress)
@ -25,12 +21,7 @@ internal class TangemPayRefreshShowProgressTransformer(
} }
} }
return multiContentState.copy( return multiContentState.copy(warnings = newWarnings.toImmutableList())
tangemPayState = refreshNeededState.copy(
notification = refreshNotification.copy(shouldShowProgress = shouldShowProgress),
),
warnings = newWarnings.toImmutableList(),
)
} }
override fun transform(walletUM: WalletUM): WalletUM { override fun transform(walletUM: WalletUM): WalletUM {

View file

@ -1,28 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
internal class TangemPayUnavailableStateTransformer(
userWalletId: UserWalletId,
) : WalletStateTransformer(userWalletId) {
override fun transform(prevState: WalletState): WalletState {
return if (prevState is WalletState.MultiCurrency.Content) {
prevState.copy(
tangemPayState = TangemPayState.TemporaryUnavailable(
notification = WalletNotification.Warning.TangemPayUnreachable,
),
)
} else {
prevState
}
}
override fun transform(walletUM: WalletUM): WalletUM {
return walletUM // todo redesign main
}
}

View file

@ -1,130 +0,0 @@
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.extensions.stringReference
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.domain.models.kyc.KycStatus
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.TangemPayDetailsConfig
import com.tangem.domain.pay.model.CustomerInfo.CardInfo
import com.tangem.domain.pay.model.CustomerInfo.ProductInstance
import com.tangem.domain.pay.model.MainScreenCustomerInfo
import com.tangem.domain.pay.model.OrderStatus
import com.tangem.domain.visa.model.TangemPayCardFrozenState
import com.tangem.feature.wallet.child.wallet.model.intents.TangemPayIntents
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.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
import java.util.Currency
/**
* Hardcode Polygon chain id only for F&F.
* Later chain id will be fetched from BFF.
*/
private const val POLYGON_CHAIN_ID = 137
internal class TangemPayUpdateInfoStateTransformer(
userWalletId: UserWalletId,
private val value: MainScreenCustomerInfo,
private val cardFrozenState: TangemPayCardFrozenState,
private val tangemPayClickIntents: TangemPayIntents,
) : WalletStateTransformer(userWalletId = userWalletId) {
override fun transform(prevState: WalletState): WalletState {
val tangemPayState = createInitialState()
return if (prevState is WalletState.MultiCurrency.Content) {
prevState.copy(tangemPayState = tangemPayState)
} else {
prevState
}
}
override fun transform(walletUM: WalletUM): WalletUM {
return walletUM // todo redesign main
}
private fun createInitialState(): TangemPayState {
val cardInfo = value.info.cardInfo
val productInstance = value.info.productInstance
val customerId = value.info.customerId ?: "Unknown"
// when statement copied to WalletTangemPayAnalyticsEventSender. Be careful when editing.
return when {
value.info.kycStatus != KycStatus.APPROVED && !value.info.customerId.isNullOrEmpty() ->
createKycInProgressState(kycStatus = value.info.kycStatus, customerId = customerId)
value.orderStatus == OrderStatus.CANCELED -> createCancelledState(customerId)
cardInfo != null && productInstance != null && value.orderStatus == OrderStatus.COMPLETED ->
getCardInfoState(customerId, cardInfo, productInstance)
else -> createIssueProgressState()
}
}
private fun getCardInfoState(
customerId: String,
cardInfo: CardInfo,
productInstance: ProductInstance,
): TangemPayState = TangemPayState.Card(
lastFourDigits = TextReference.Str("*${cardInfo.lastFourDigits}"),
balanceText = TextReference.Str(getBalanceText(cardInfo)),
balanceSymbol = stringReference("USDC"), // TODO hardcode for now
onClick = {
tangemPayClickIntents.openDetails(
userWalletId,
TangemPayDetailsConfig(
customerId = customerId,
cardId = productInstance.cardId,
isPinSet = cardInfo.isPinSet,
cardFrozenState = cardFrozenState,
cardNumberEnd = cardInfo.lastFourDigits,
chainId = POLYGON_CHAIN_ID,
displayName = productInstance.displayName,
),
)
},
)
private fun getBalanceText(cardInfo: CardInfo): String {
val currency = Currency.getInstance(cardInfo.currencyCode)
return cardInfo.balance.format {
fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol)
}
}
private fun createKycInProgressState(kycStatus: KycStatus, customerId: String): TangemPayState = Progress(
title = TextReference.Res(R.string.tangempay_payment_account),
description = when (kycStatus) {
KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed)
else -> TextReference.Res(R.string.tangempay_kyc_in_progress)
},
buttonText = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_button),
iconRes = R.drawable.ic_promo_kyc_36,
onButtonClick = {
when (kycStatus) {
KycStatus.REJECTED -> tangemPayClickIntents.onKycRejectedClicked(
userWalletId = userWalletId,
customerId = customerId,
)
else -> tangemPayClickIntents.onKycProgressClicked(userWalletId)
}
},
)
private fun createIssueProgressState(): TangemPayState = Progress(
title = TextReference.Res(R.string.tangempay_payment_account),
description = TextReference.Res(R.string.tangempay_issuing_your_card),
buttonText = TextReference.EMPTY,
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
onButtonClick = tangemPayClickIntents::onIssuingCardClicked,
showProgress = true,
)
private fun createCancelledState(customerId: String): TangemPayState = TangemPayState.FailedIssue(
title = TextReference.Res(R.string.tangempay_payment_account),
description = TextReference.Res(R.string.tangempay_failed_to_issue_card),
iconRes = R.drawable.ic_alert_24,
onButtonClick = { tangemPayClickIntents.onIssuingFailedClicked(customerId) },
)
}

View file

@ -9,16 +9,15 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenSta
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
import com.tangem.utils.logging.TangemLogger
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentList
import com.tangem.utils.logging.TangemLogger
internal class UnlockWalletTransformer( internal class UnlockWalletTransformer(
private val unlockedWallets: List<UserWallet>, private val unlockedWallets: List<UserWallet>,
private val clickIntents: WalletClickIntents, private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver, private val walletImageResolver: WalletImageResolver,
private val getWalletIconUseCase: GetWalletIconUseCase, private val getWalletIconUseCase: GetWalletIconUseCase,
private val isTangemPayRefactorEnabled: Boolean,
) : WalletScreenStateTransformer { ) : WalletScreenStateTransformer {
private val walletLoadingStateFactory by lazy { private val walletLoadingStateFactory by lazy {
@ -26,7 +25,6 @@ internal class UnlockWalletTransformer(
clickIntents = clickIntents, clickIntents = clickIntents,
walletImageResolver = walletImageResolver, walletImageResolver = walletImageResolver,
getWalletIconUseCase = getWalletIconUseCase, getWalletIconUseCase = getWalletIconUseCase,
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
) )
} }

View file

@ -34,7 +34,6 @@ internal class WalletLoadingStateFactory(
private val clickIntents: WalletClickIntents, private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver, private val walletImageResolver: WalletImageResolver,
private val getWalletIconUseCase: GetWalletIconUseCase, private val getWalletIconUseCase: GetWalletIconUseCase,
private val isTangemPayRefactorEnabled: Boolean,
) { ) {
fun create(userWallet: UserWallet): WalletState { fun create(userWallet: UserWallet): WalletState {
@ -83,9 +82,7 @@ internal class WalletLoadingStateFactory(
tokensListState = WalletTokensListState.ContentState.Loading, tokensListState = WalletTokensListState.ContentState.Loading,
nftState = WalletNFTItemUM.Hidden, nftState = WalletNFTItemUM.Hidden,
type = WalletType.Hot, type = WalletType.Hot,
tangemPayState = TangemPayState.Empty,
tangemPayMainUM = TangemPayMainUM.Empty, tangemPayMainUM = TangemPayMainUM.Empty,
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
) )
} }
@ -99,9 +96,7 @@ internal class WalletLoadingStateFactory(
tokensListState = WalletTokensListState.ContentState.Loading, tokensListState = WalletTokensListState.ContentState.Loading,
nftState = WalletNFTItemUM.Hidden, nftState = WalletNFTItemUM.Hidden,
type = WalletType.Cold, type = WalletType.Cold,
tangemPayState = TangemPayState.Empty,
tangemPayMainUM = TangemPayMainUM.Empty, tangemPayMainUM = TangemPayMainUM.Empty,
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
) )
} }

View file

@ -1,122 +1,38 @@
package com.tangem.feature.wallet.presentation.wallet.subscribers package com.tangem.feature.wallet.presentation.wallet.subscribers
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
import com.tangem.domain.pay.model.MainCustomerInfoContentState
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.pay.repository.TangemPayWithdrawRepository import com.tangem.domain.pay.repository.TangemPayWithdrawRepository
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
import com.tangem.domain.visa.model.TangemPayCardFrozenState
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletTangemPayAnalyticsEventSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletTangemPayAnalyticsEventSender
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.transformers.*
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import com.tangem.utils.logging.TangemLogger
@Suppress("LongParameterList")
internal class TangemPayMainSubscriber @AssistedInject constructor( internal class TangemPayMainSubscriber @AssistedInject constructor(
@Assisted private val userWallet: UserWallet, @Assisted private val userWallet: UserWallet,
private val stateController: WalletStateController,
private val clickIntents: WalletClickIntents,
private val cardDetailsRepository: TangemPayCardDetailsRepository,
private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase,
private val tangemPayWithdrawRepository: TangemPayWithdrawRepository, private val tangemPayWithdrawRepository: TangemPayWithdrawRepository,
private val paymentAccountStatusSupplier: PaymentAccountStatusSupplier,
private val analytics: WalletTangemPayAnalyticsEventSender, private val analytics: WalletTangemPayAnalyticsEventSender,
) : WalletSubscriber() { ) : WalletSubscriber() {
override fun create(coroutineScope: CoroutineScope): Flow<*> { override fun create(coroutineScope: CoroutineScope): Flow<*> {
coroutineScope.launch { coroutineScope.launch {
// TODO: Doston move this logic to proper place(e.g. WalletBalanceFetcher)
tangemPayWithdrawRepository.pollWithdrawOrdersIfNeeds(userWallet) tangemPayWithdrawRepository.pollWithdrawOrdersIfNeeds(userWallet)
} }
return subscribeOnTangemPayInfoUpdates() subscribeToStatus(coroutineScope)
return emptyFlow<Any>()
} }
private fun subscribeOnTangemPayInfoUpdates(): Flow<*> { private fun subscribeToStatus(coroutineScope: CoroutineScope) {
return tangemPayMainScreenCustomerInfoUseCase(userWalletId = userWallet.walletId) paymentAccountStatusSupplier.invoke(userWalletId = userWallet.walletId)
.map { it.value }
.distinctUntilChanged() .distinctUntilChanged()
.onEach { mainInfoData -> .onEach(analytics::send)
val userWalletId = userWallet.walletId .launchIn(coroutineScope)
mainInfoData.onLeft { tangemPayError ->
when (tangemPayError) {
TangemPayCustomerInfoError.RefreshNeededError -> {
stateController.update(
transformer = TangemPayRefreshNeededStateTransformer(
userWalletId = userWalletId,
userWallet = userWallet,
onRefreshClick = { clickIntents.onRefreshPayToken(userWallet) },
),
)
}
TangemPayCustomerInfoError.UnavailableError -> {
stateController.update(
transformer = TangemPayUnavailableStateTransformer(userWalletId),
)
}
TangemPayCustomerInfoError.ExposedDeviceError -> {
stateController.update(TangemPayExposedDeviceTransformer(userWalletId))
}
TangemPayCustomerInfoError.DeactivatedError -> {
stateController.update(
transformer = TangemPayHiddenStateTransformer(userWalletId),
)
}
TangemPayCustomerInfoError.UnknownError -> {
// hide TangemPay block
TangemLogger.e("Failed when loading main screen TangemPay info: $tangemPayError")
stateController.update(
transformer = TangemPayHiddenStateTransformer(userWalletId),
)
}
}
}.onRight { contentState -> handleContentState(state = contentState) }
}
}
private suspend fun handleContentState(state: MainCustomerInfoContentState) {
val userWalletId = userWallet.walletId
when (state) {
MainCustomerInfoContentState.Loading -> stateController.update(
transformer = TangemPayLoadingStateTransformer(userWalletId),
)
is MainCustomerInfoContentState.Content -> {
updateTangemPay(data = state.info, userWalletId = userWalletId)
analytics.send(customerInfo = state.info)
}
is MainCustomerInfoContentState.OnboardingBanner -> stateController.update(
transformer = TangemPayOnboardingBannerStateTransformer(
userWalletId = userWalletId,
onClick = clickIntents::onOnboardingBannerClick,
closeOnClick = clickIntents::onOnboardingBannerCloseClick,
),
)
is MainCustomerInfoContentState.Empty -> stateController.update(
transformer = TangemPayHiddenStateTransformer(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,
tangemPayClickIntents = clickIntents,
),
)
} }
@AssistedFactory @AssistedFactory

View file

@ -82,7 +82,6 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.common.*
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.nftCollections import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.nftCollections
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.organizeTokensButton import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.organizeTokensButton
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.TangemPayMainScreenBlock
import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
import com.tangem.features.tangempay.entity.TangemPayMainUM import com.tangem.features.tangempay.entity.TangemPayMainUM
@ -752,14 +751,8 @@ internal fun LazyListScope.tangemPayItem(
) { ) {
if (state !is WalletState.MultiCurrency) return if (state !is WalletState.MultiCurrency) return
if (state.isTangemPayRefactorEnabled) { with(tangemPayComponent) {
with(tangemPayComponent) { tangemPayMainContent(modifier = modifier, state = state.tangemPayMainUM, isBalanceHidden = isHidingMode)
tangemPayMainContent(modifier = modifier, state = state.tangemPayMainUM, isBalanceHidden = isHidingMode)
}
} else {
item(key = "TangemPayMainScreenBlock", contentType = state.tangemPayState::class.java) {
TangemPayMainScreenBlock(modifier = modifier, state = state.tangemPayState, isBalanceHidden = isHidingMode)
}
} }
} }

View file

@ -1,103 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency
import android.content.res.Configuration
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.orMaskWithStars
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
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.ui.components.visa.TangemPayMainScreenBlock
@Composable
internal fun TangemPayCardMainBlock(
state: TangemPayState.Card,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
Surface(
modifier = modifier.fillMaxWidth(),
shape = TangemTheme.shapes.roundedCornersXMedium,
color = TangemTheme.colors.background.primary,
onClick = state.onClick,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(IntrinsicSize.Min)
.padding(horizontal = 12.dp, vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Image(
painter = painterResource(R.drawable.img_visa_36),
contentDescription = null,
modifier = Modifier.size(36.dp),
)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
Text(
text = stringResourceSafe(R.string.tangempay_payment_account),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
)
Text(
text = state.lastFourDigits.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
}
Column(
modifier = Modifier.fillMaxHeight(),
verticalArrangement = Arrangement.spacedBy(2.dp),
horizontalAlignment = Alignment.End,
) {
Text(
text = state.balanceText.resolveReference().orMaskWithStars(isBalanceHidden),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.primary1,
textAlign = TextAlign.End,
)
Text(
text = state.balanceSymbol.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
textAlign = TextAlign.End,
)
}
}
}
}
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun TangemPayCardMainBlockPreview() {
TangemThemePreview {
TangemPayMainScreenBlock(
TangemPayState.Card(
lastFourDigits = TextReference.Str("*1234"),
balanceText = TextReference.Str("$ 0.00"),
balanceSymbol = TextReference.Str("USDC"),
onClick = {},
),
isBalanceHidden = false,
)
}
}

View file

@ -1,41 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import com.tangem.core.ui.R
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.inputrow.InputRowImageBase
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.TangemTheme
private const val DISABLED_ALPHA = 0.6F
@Composable
internal fun TangemPayExposedDeviceState(modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary)
.alpha(DISABLED_ALPHA),
enabled = false,
onClick = {},
) {
InputRowImageBase(
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = resourceReference(R.string.tangem_pay_rooted_device_subtitle),
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
endIconTint = TangemTheme.colors.icon.warning,
)
}
}

View file

@ -1,36 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.inputrow.InputRowImageBase
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
@Composable
internal fun TangemPayFailedIssueState(state: TangemPayState.FailedIssue, modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
onClick = state.onButtonClick,
) {
InputRowImageBase(
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = state.title,
caption = state.description,
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = com.tangem.core.ui.R.drawable.img_visa_36,
iconEndRes = state.iconRes,
endIconTint = TangemTheme.colors.icon.warning,
)
}
}

View file

@ -1,37 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.CircleShimmer
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.res.TangemTheme
@Composable
internal fun TangemPayLoadingScreenBlock(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.background(color = TangemTheme.colors.background.primary, shape = TangemTheme.shapes.roundedCornersXMedium)
.padding(horizontal = 12.dp, vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
CircleShimmer(modifier = Modifier.size(36.dp))
Column(
modifier = Modifier.padding(start = 12.dp),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
RectangleShimmer(modifier = Modifier.padding(vertical = 4.dp).sizeIn(minWidth = 70.dp, minHeight = 12.dp))
RectangleShimmer(modifier = Modifier.padding(vertical = 2.dp).sizeIn(minWidth = 52.dp, minHeight = 12.dp))
}
SpacerWMax()
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
RectangleShimmer(modifier = Modifier.padding(vertical = 4.dp).sizeIn(minWidth = 40.dp, minHeight = 12.dp))
RectangleShimmer(modifier = Modifier.padding(vertical = 2.dp).sizeIn(minWidth = 40.dp, minHeight = 12.dp))
}
}
}

View file

@ -1,106 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.common.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
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.state.model.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification.Warning.TangemPayRefreshNeeded
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TangemPayCardMainBlock
@Composable
internal fun TangemPayMainScreenBlock(state: TangemPayState, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
when (state) {
is Progress -> TangemPayProgressState(state, modifier)
is TangemPayState.Card -> TangemPayCardMainBlock(state, isBalanceHidden, modifier)
is TangemPayState.Empty -> Unit
is TangemPayState.RefreshNeeded -> TangemPayRefreshBlock(state, modifier)
is TangemPayState.TemporaryUnavailable -> TangemPayUnavailableBlock(state, modifier)
is TangemPayState.FailedIssue -> TangemPayFailedIssueState(state, modifier)
is TangemPayState.OnboardingBanner -> TangemPayOnboardingBanner(state, modifier)
is TangemPayState.ExposedDevice -> TangemPayExposedDeviceState(modifier)
is TangemPayState.Loading -> TangemPayLoadingScreenBlock(modifier)
}
}
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun TangemPayMainScreenBlockPreview() {
TangemThemePreview {
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
TangemPayMainScreenBlock(state = TangemPayState.Loading, isBalanceHidden = false)
TangemPayMainScreenBlock(
state = TangemPayState.RefreshNeeded(
TangemPayRefreshNeeded(
buttonText = resourceReference(id = R.string.home_button_scan),
onRefreshClick = {},
shouldShowProgress = false,
),
),
isBalanceHidden = false,
)
TangemPayMainScreenBlock(
state = TangemPayState.TemporaryUnavailable(WalletNotification.Warning.TangemPayUnreachable),
isBalanceHidden = false,
)
TangemPayMainScreenBlock(
state = TangemPayState.OnboardingBanner(onClick = {}, closeOnClick = {}),
isBalanceHidden = false,
)
TangemPayMainScreenBlock(state = TangemPayState.ExposedDevice, isBalanceHidden = false)
TangemPayMainScreenBlock(
state = TangemPayState.FailedIssue(
title = TextReference.Res(R.string.tangempay_payment_account),
description = TextReference.Res(R.string.tangempay_failed_to_issue_card),
iconRes = R.drawable.ic_alert_24,
onButtonClick = { },
),
isBalanceHidden = false,
)
TangemPayMainScreenBlock(
Progress(
title = TextReference.Res(R.string.tangempay_payment_account),
description = TextReference.Res(R.string.tangempay_kyc_in_progress),
buttonText = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_button),
iconRes = R.drawable.ic_promo_kyc_36,
onButtonClick = {},
),
isBalanceHidden = false,
)
TangemPayMainScreenBlock(
Progress(
title = TextReference.Res(R.string.tangempay_payment_account),
description = TextReference.Res(R.string.tangempay_issuing_your_card),
buttonText = TextReference.EMPTY,
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
onButtonClick = {},
showProgress = true,
),
isBalanceHidden = false,
)
TangemPayMainScreenBlock(
TangemPayState.Card(
lastFourDigits = TextReference.Str("*1234"),
balanceText = TextReference.Str("$ 0.00"),
balanceSymbol = TextReference.Str("USDC"),
onClick = {},
),
isBalanceHidden = false,
)
}
}
}

View file

@ -1,120 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
import android.content.res.Configuration
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
private const val GRADIENT_START_COLOR = 0xFF252934
private const val GRADIENT_END_COLOR = 0xFF12141E
private const val GRADIENT_OFFSET_X = 0f
private const val GRADIENT_OFFSET_Y = 80F
private const val GRADIENT_RADIUS = 200F
@Composable
internal fun TangemPayOnboardingBanner(state: TangemPayState.OnboardingBanner, modifier: Modifier = Modifier) {
Box(
modifier = modifier
.fillMaxWidth()
.clip(TangemTheme.shapes.roundedCornersXMedium)
.background(
brush = Brush.radialGradient(
colors = listOf(Color(GRADIENT_START_COLOR), Color(GRADIENT_END_COLOR)),
center = Offset(GRADIENT_OFFSET_X, GRADIENT_OFFSET_Y),
radius = GRADIENT_RADIUS,
),
)
.clickable(onClick = state.onClick),
) {
ConstraintLayout(
modifier = Modifier.fillMaxWidth(),
) {
val (image, text, close) = createRefs()
Image(
painter = painterResource(R.drawable.ic_close_24),
contentDescription = null,
modifier = Modifier
.size(16.dp)
.clickable(onClick = state.closeOnClick)
.constrainAs(close) {
top.linkTo(parent.top, margin = 16.dp)
end.linkTo(parent.end, margin = 16.dp)
},
colorFilter = ColorFilter.tint(TangemTheme.colors.icon.inactive),
)
Column(
modifier = Modifier
.constrainAs(text) {
top.linkTo(parent.top)
start.linkTo(image.end, margin = 12.dp)
end.linkTo(close.start, margin = 12.dp)
width = Dimension.fillToConstraints
}
.padding(top = 16.dp, bottom = 16.dp),
) {
Text(
text = stringResourceSafe(R.string.tangempay_onboarding_banner_title),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.constantWhite,
)
SpacerH(6.dp)
Text(
text = stringResourceSafe(R.string.tangempay_onboarding_banner_description),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
}
Image(
painter = painterResource(R.drawable.img_tangem_pay_onboarding_banner),
contentDescription = null,
modifier = Modifier
.padding(top = 8.dp, start = 24.dp)
.constrainAs(image) {
start.linkTo(parent.start)
top.linkTo(text.top)
bottom.linkTo(text.bottom)
height = Dimension.fillToConstraints
},
)
}
}
}
@Preview(showBackground = true)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun PreviewTangemOnboardingBanner() {
TangemThemePreview {
TangemPayOnboardingBanner(
TangemPayState.OnboardingBanner(
onClick = {},
closeOnClick = {},
),
)
}
}

View file

@ -1,35 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import com.tangem.core.ui.R
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.inputrow.InputRowImageBase
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
@Composable
internal fun TangemPayProgressState(state: TangemPayState.Progress, modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
onClick = state.onButtonClick,
) {
InputRowImageBase(
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = state.title,
caption = state.description,
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}

View file

@ -1,79 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SpacerH12
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.inputrow.InputRowImageBase
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.extensions.resourceReference
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.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification.Warning.TangemPayRefreshNeeded
@Composable
internal fun TangemPayRefreshBlock(state: TangemPayState.RefreshNeeded, modifier: Modifier = Modifier) {
Column(modifier) {
Notification(
config = state.notification.config,
iconTint = when (state.notification) {
is WalletNotification.Critical -> TangemTheme.colors.icon.warning
is WalletNotification.Informational -> TangemTheme.colors.icon.accent
is WalletNotification.RateApp -> TangemTheme.colors.icon.attention
is WalletNotification.UnlockWallets -> TangemTheme.colors.icon.primary1
is WalletNotification.UsedOutdatedData -> TangemTheme.colors.text.attention
else -> null
},
)
SpacerH12()
BlockCard(
modifier = Modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
enabled = false,
) {
InputRowImageBase(
modifier = Modifier.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = resourceReference(R.string.tangempay_payment_account_sync_needed),
subtitleColor = TangemTheme.colors.text.tertiary,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}
}
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun TangemPayRefreshBlockPreview() {
TangemThemePreview {
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
TangemPayRefreshBlock(
state = TangemPayState.RefreshNeeded(
TangemPayRefreshNeeded(
buttonText = resourceReference(id = R.string.tangempay_sync_needed_restore_access),
onRefreshClick = {},
shouldShowProgress = true,
),
),
modifier = Modifier,
)
}
}
}

View file

@ -1,76 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SpacerH12
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.inputrow.InputRowImageBase
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
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.WalletNotification
import com.tangem.utils.StringsSigns.DASH_SIGN
@Composable
internal fun TangemPayUnavailableBlock(state: TangemPayState.TemporaryUnavailable, modifier: Modifier = Modifier) {
Column(modifier) {
Notification(
config = state.notification.config,
iconTint = when (state.notification) {
is WalletNotification.Critical -> TangemTheme.colors.icon.warning
is WalletNotification.Informational -> TangemTheme.colors.icon.accent
is WalletNotification.RateApp -> TangemTheme.colors.icon.attention
is WalletNotification.UnlockWallets -> TangemTheme.colors.icon.primary1
is WalletNotification.UsedOutdatedData -> TangemTheme.colors.text.attention
else -> null
},
)
SpacerH12()
BlockCard(
modifier = Modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
enabled = false,
) {
InputRowImageBase(
modifier = Modifier.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = TextReference.Str(DASH_SIGN),
subtitleColor = TangemTheme.colors.text.tertiary,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}
}
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun TangemPayUnavailableBlockPreview() {
TangemThemePreview {
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
TangemPayUnavailableBlock(
state = TangemPayState.TemporaryUnavailable(
WalletNotification.Warning.TangemPayUnreachable,
),
modifier = Modifier,
)
}
}
}