Updated on 2026-08-14
This commit is contained in:
parent
f086d6bb74
commit
40fe8bb5cb
56 changed files with 82 additions and 1491 deletions
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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> =
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
@ -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,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
package com.tangem.features.tangempay
|
package com.tangem.features.tangempay
|
||||||
|
|
||||||
interface TangemPayFeatureToggles {
|
interface TangemPayFeatureToggles
|
||||||
val isTangemPayAccountsRefactorEnabled: Boolean
|
|
||||||
}
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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))) }
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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 = {},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue