Updated on 2026-08-14
This commit is contained in:
commit
261715f3f9
8 changed files with 225 additions and 53 deletions
|
|
@ -180,8 +180,8 @@
|
|||
<item quantity="other">%d Geräte</item>
|
||||
</plurals>
|
||||
<plurals name="card_label_token_count">
|
||||
<item quantity="one">Token</item>
|
||||
<item quantity="other">Tokens</item>
|
||||
<item quantity="one">%d Token</item>
|
||||
<item quantity="other">%d Tokens</item>
|
||||
</plurals>
|
||||
<string name="card_reset_alert_continue_message">Bitte setze das nächste Gerät zurück, um fortzufahren.</string>
|
||||
<string name="card_reset_alert_continue_title">Wallet zurückgesetzt</string>
|
||||
|
|
|
|||
|
|
@ -176,12 +176,12 @@
|
|||
<string name="button_start_backup_process">Iniciar processo de backup</string>
|
||||
<string name="buy_token_description">Use um cartão bancário ou outros métodos de pagamento.</string>
|
||||
<plurals name="card_label_card_count">
|
||||
<item quantity="one">dispositivo</item>
|
||||
<item quantity="other">dispositivos</item>
|
||||
<item quantity="one">%d dispositivo</item>
|
||||
<item quantity="other">%d dispositivos</item>
|
||||
</plurals>
|
||||
<plurals name="card_label_token_count">
|
||||
<item quantity="one">token</item>
|
||||
<item quantity="other">tokens</item>
|
||||
<item quantity="one">%d token</item>
|
||||
<item quantity="other">%d tokens</item>
|
||||
</plurals>
|
||||
<string name="card_reset_alert_continue_message">Reinicie o próximo dispositivo para continuar.</string>
|
||||
<string name="card_reset_alert_continue_title">Reiniciar Carteira</string>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
|||
override suspend fun invoke(params: PaymentAccountStatusFetcher.Params): Either<Throwable, Unit> =
|
||||
Either.catchOn(dispatchers.default) {
|
||||
val account = Account.Payment(userWalletId = params.userWalletId)
|
||||
logger.i("fetch: ${params.userWalletId.stringValue}")
|
||||
logger.i("invoke() start: ${params.userWalletId.stringValue}")
|
||||
|
||||
if (deviceSecurity.isSecurityExposed()) {
|
||||
logger.i("fetch security info: rooted: ${deviceSecurity.isRooted}")
|
||||
|
|
@ -84,11 +84,14 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
|||
userWalletId = params.userWalletId,
|
||||
status = AccountStatus.Payment(account = account, value = status),
|
||||
)
|
||||
}.onLeft {
|
||||
}.onLeft { throwable ->
|
||||
logger.e("invoke() ${params.userWalletId} threw, falling back to ONLY_CACHE", throwable)
|
||||
paymentAccountStatusesStore.updateStatusSource(
|
||||
userWalletId = params.userWalletId,
|
||||
source = StatusSource.ONLY_CACHE,
|
||||
)
|
||||
}.also { result ->
|
||||
logger.i("invoke() end ${params.userWalletId}: isRight=${result.isRight()}")
|
||||
}
|
||||
|
||||
private suspend fun proceedHasTangemPayResult(
|
||||
|
|
@ -105,7 +108,12 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
|||
|
||||
private suspend fun fetchTangemPayAccountStatus(account: Account.Payment): PaymentAccountStatusValue {
|
||||
val prevResult = paymentAccountStatusesStore.getSyncOrNull(account.userWalletId)
|
||||
logger.i(
|
||||
"fetchTangemPayAccountStatus ${account.userWalletId}: " +
|
||||
"prevResultType=${prevResult?.value?.let { it::class.simpleName } ?: "null"}",
|
||||
)
|
||||
if (prevResult == null || prevResult.value is PaymentAccountStatusValue.Error.Unavailable) {
|
||||
logger.i("fetchTangemPayAccountStatus ${account.userWalletId}: writing Loading placeholder to store")
|
||||
paymentAccountStatusesStore.store(
|
||||
userWalletId = account.userWalletId,
|
||||
status = AccountStatus.Payment(account = account, value = PaymentAccountStatusValue.Loading),
|
||||
|
|
@ -116,10 +124,13 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun proceedWithOrderId(account: Account.Payment): PaymentAccountStatusValue {
|
||||
return if (!onboardingRepository.isTangemPayInitialDataProduced(account.userWalletId)) {
|
||||
val isInitial = onboardingRepository.isTangemPayInitialDataProduced(account.userWalletId)
|
||||
logger.i("proceedWithOrderId ${account.userWalletId}: isTangemPayInitialDataProduced=$isInitial")
|
||||
return if (!isInitial) {
|
||||
PaymentAccountStatusValue.Error.NotSynced
|
||||
} else {
|
||||
val orderId = onboardingRepository.getOrderId(account.userWalletId)
|
||||
logger.i("proceedWithOrderId ${account.userWalletId}: orderIdPresent=${orderId != null}")
|
||||
if (orderId != null) {
|
||||
proceedWithOrderId(account = account, orderId = orderId)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -9,12 +9,17 @@ import com.tangem.domain.models.account.AccountStatus
|
|||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusProducer
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onEmpty
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
|
||||
private const val TAG = "PaymentAccountStatusProducer"
|
||||
|
||||
internal class DefaultPaymentAccountStatusProducer @AssistedInject constructor(
|
||||
@Assisted private val params: PaymentAccountStatusProducer.Params,
|
||||
|
|
@ -24,13 +29,20 @@ internal class DefaultPaymentAccountStatusProducer @AssistedInject constructor(
|
|||
) : PaymentAccountStatusProducer {
|
||||
|
||||
private val account = Account.Payment(userWalletId = params.userWalletId)
|
||||
private val logger = TangemLogger.withTag(TAG)
|
||||
|
||||
override val fallback: Option<AccountStatus.Payment>
|
||||
get() = AccountStatus.Payment(account = account, value = PaymentAccountStatusValue.Error.Unavailable).some()
|
||||
|
||||
override fun produce(): Flow<AccountStatus.Payment> {
|
||||
logger.i("[${params.userWalletId}] produce() called")
|
||||
return paymentAccountStatusesStore.get(userWalletId = params.userWalletId)
|
||||
.onEmpty { emit(value = AccountStatus.Payment(account, PaymentAccountStatusValue.NotCreated)) }
|
||||
.onStart { logger.i("[${params.userWalletId}] flow subscribed to store") }
|
||||
.onEach { logger.i("[${params.userWalletId}] flow emits statusType=${it.value::class.simpleName}") }
|
||||
.onEmpty {
|
||||
logger.i("[${params.userWalletId}] onEmpty triggered: emitting NotCreated fallback")
|
||||
emit(value = AccountStatus.Payment(account, PaymentAccountStatusValue.NotCreated))
|
||||
}
|
||||
.flowOn(dispatchers.default)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,15 @@ import kotlinx.coroutines.coroutineScope
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal typealias WalletIdWithPaymentStatus = Map<String, AccountStatus.Payment>
|
||||
internal typealias WalletIdWithPaymentStatusDM = Map<String, PaymentAccountStatusValueDM>
|
||||
|
||||
private const val TAG = "PaymentAccountStatusesStore"
|
||||
|
||||
/**
|
||||
* Store for payment account statuses with dual storage (runtime + persistence).
|
||||
*
|
||||
|
|
@ -34,10 +38,18 @@ internal class PaymentAccountStatusesStore(
|
|||
scope: AppCoroutineScope,
|
||||
) {
|
||||
|
||||
private val logger = TangemLogger.withTag(TAG)
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
logger.i("init: loading cached payment statuses from persistence")
|
||||
try {
|
||||
val cachedStatuses = persistenceDataStore.data.firstOrNull() ?: return@launch
|
||||
val cachedStatuses = persistenceDataStore.data.firstOrNull()
|
||||
if (cachedStatuses == null) {
|
||||
logger.i("init: persistence empty (firstOrNull == null), runtimeStore stays empty")
|
||||
return@launch
|
||||
}
|
||||
logger.i("init: loaded ${cachedStatuses.size} cached entries; populating runtimeStore")
|
||||
runtimeStore.store(
|
||||
value = cachedStatuses.mapValues { (rawUserWalletId, statusDM) ->
|
||||
val account = Account.Payment(userWalletId = UserWalletId(rawUserWalletId))
|
||||
|
|
@ -45,19 +57,33 @@ internal class PaymentAccountStatusesStore(
|
|||
AccountStatus.Payment(account = account, value = statusValue)
|
||||
},
|
||||
)
|
||||
logger.i("init: runtimeStore populated with ${cachedStatuses.size} entries")
|
||||
} catch (e: Exception) {
|
||||
runSuspendCatching { persistenceDataStore.updateData { emptyMap() } }
|
||||
TangemLogger.e("Error while loading cached payment account statuses", e)
|
||||
logger.e("Error while loading cached payment account statuses", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun get(userWalletId: UserWalletId): Flow<AccountStatus.Payment> {
|
||||
return runtimeStore.get().mapNotNull { it[userWalletId.stringValue] }
|
||||
return runtimeStore.get()
|
||||
.onStart { logger.i("get($userWalletId): subscribed to runtimeStore") }
|
||||
.onEach { map ->
|
||||
logger.i(
|
||||
"get($userWalletId): runtimeStore emitted map size=${map.size}, " +
|
||||
"hasEntry=${map.containsKey(userWalletId.stringValue)}",
|
||||
)
|
||||
}
|
||||
.mapNotNull { it[userWalletId.stringValue] }
|
||||
.onEach { status ->
|
||||
logger.i("get($userWalletId): emitting statusType=${status.value::class.simpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId): AccountStatus.Payment? {
|
||||
return runtimeStore.getSyncOrNull()?.get(userWalletId.stringValue)
|
||||
val result = runtimeStore.getSyncOrNull()?.get(userWalletId.stringValue)
|
||||
logger.i("getSyncOrNull($userWalletId) valueType=${result?.value?.let { it::class.simpleName } ?: "null"}")
|
||||
return result
|
||||
}
|
||||
|
||||
suspend fun updateStatusSource(userWalletId: UserWalletId, source: StatusSource) {
|
||||
|
|
@ -71,6 +97,7 @@ internal class PaymentAccountStatusesStore(
|
|||
}
|
||||
|
||||
suspend fun store(userWalletId: UserWalletId, status: AccountStatus.Payment) {
|
||||
logger.i("store($userWalletId): valueType=${status.value::class.simpleName}")
|
||||
coroutineScope {
|
||||
launch { storeInRuntime(userWalletId = userWalletId, status = status) }
|
||||
launch { storeInPersistence(userWalletId = userWalletId, status = status.value) }
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import com.tangem.domain.tokens.operations.TokenListFactory
|
|||
import com.tangem.domain.tokens.operations.TotalFiatBalanceCalculator
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -73,7 +74,7 @@ import java.math.BigDecimal
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
// TODO: Move to :data:account:status [REDACTED_JIRA]
|
||||
@Suppress("LongParameterList")
|
||||
@Suppress("LongParameterList", "LargeClass")
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
internal class DefaultSingleAccountStatusListProducer @AssistedInject constructor(
|
||||
@Assisted private val params: SingleAccountStatusListProducer.Params,
|
||||
|
|
@ -90,17 +91,29 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
private val analyticsExceptionHandler: AnalyticsExceptionHandler,
|
||||
) : SingleAccountStatusListProducer {
|
||||
|
||||
private val logger = TangemLogger.withTag(TAG)
|
||||
|
||||
override val fallback: Option<AccountStatusList> = none()
|
||||
|
||||
override fun produce(): Flow<AccountStatusList> {
|
||||
logger.i("produce() called for ${params.userWalletId}")
|
||||
return flattenFlow()
|
||||
.onEach { list ->
|
||||
logger.i(
|
||||
"produce()[${params.userWalletId}] emit: accounts=${list.accountStatuses.size}, " +
|
||||
"currencies=${list.flattenCurrencies().size}, " +
|
||||
"totalFiatType=${list.totalFiatBalance::class.simpleName}",
|
||||
)
|
||||
}
|
||||
.flowOn(dispatchers.default)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun flattenFlow(): Flow<AccountStatusList> = channelFlow {
|
||||
val walletId = params.userWalletId
|
||||
logger.i("flattenFlow[$walletId]: start")
|
||||
val userWallet = userWalletsListRepository.getSyncStrict(id = params.userWalletId)
|
||||
logger.i("flattenFlow[$walletId]: userWallet resolved (type=${userWallet::class.simpleName})")
|
||||
|
||||
val flattenCurrency: MutableSharedFlow<Map<AccountCurrencyId, CryptoCurrency>> = MutableSharedFlow(
|
||||
replay = 1,
|
||||
|
|
@ -108,11 +121,20 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
)
|
||||
|
||||
val accountListFlow: StateFlow<AccountList> = singleAccountListSupplier(walletId)
|
||||
.onEach { accountList -> flattenCurrency.tryEmit(accountList.flattenMapCurrencies()) }
|
||||
.onEach { accountList ->
|
||||
logger.i(
|
||||
"flattenFlow[$walletId]: accountList emitted accounts=${accountList.accounts.size}, " +
|
||||
"currencies=${accountList.flattenMapCurrencies().size}",
|
||||
)
|
||||
flattenCurrency.tryEmit(accountList.flattenMapCurrencies())
|
||||
}
|
||||
.stateIn(this)
|
||||
|
||||
val hasCachedNetworks = networksRepository.hasCachedStatuses(walletId)
|
||||
logger.i("flattenFlow[$walletId]: hasCachedNetworks=$hasCachedNetworks")
|
||||
if (!hasCachedNetworks) {
|
||||
val initialAccounts = accountListFlow.value.accounts.size
|
||||
logger.i("flattenFlow[$walletId]: sending Loading placeholder (accounts=$initialAccounts)")
|
||||
send(createLoadingAccountStatusList(accountListFlow.value))
|
||||
}
|
||||
|
||||
|
|
@ -121,11 +143,19 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
flattenCurrency = flattenCurrency,
|
||||
)
|
||||
|
||||
if (userWallet.isPaymentAccountSupported()) {
|
||||
val isPaymentSupported = userWallet.isPaymentAccountSupported()
|
||||
logger.i("flattenFlow[$walletId]: isPaymentAccountSupported=$isPaymentSupported")
|
||||
if (isPaymentSupported) {
|
||||
combineWithPaymentAccount(
|
||||
accountListFlow = accountListFlow,
|
||||
cryptoCurrencyStatusFlow = cryptoCurrencyStatusFlow,
|
||||
paymentAccountStatusFlow = paymentAccountStatusSupplier.invoke(userWalletId = params.userWalletId),
|
||||
paymentAccountStatusFlow = paymentAccountStatusSupplier.invoke(userWalletId = params.userWalletId)
|
||||
.onEach { paymentStatus ->
|
||||
logger.i(
|
||||
"flattenFlow[$walletId]: paymentAccountStatus emitted " +
|
||||
"valueType=${paymentStatus.value::class.simpleName}",
|
||||
)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
combineWithoutPaymentAccount(
|
||||
|
|
@ -146,6 +176,12 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
flow2 = cryptoCurrencyStatusFlow,
|
||||
flow3 = paymentAccountStatusFlow,
|
||||
transform = { accountList, currencyStatusMap, paymentAccountStatus ->
|
||||
logger.i(
|
||||
"combineWithPayment[${params.userWalletId}] transform: " +
|
||||
"accounts=${accountList.accounts.size}, " +
|
||||
"currencyStatusMap=${currencyStatusMap.size}, " +
|
||||
"paymentType=${paymentAccountStatus.value::class.simpleName}",
|
||||
)
|
||||
val accountStatuses = accountList.accounts.map { account ->
|
||||
when (account) {
|
||||
is Account.Payment -> paymentAccountStatus
|
||||
|
|
@ -192,6 +228,11 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
flow = accountListFlow,
|
||||
flow2 = cryptoCurrencyStatusFlow,
|
||||
transform = { accountList, currencyStatusMap ->
|
||||
logger.i(
|
||||
"combineWithoutPayment[${params.userWalletId}] transform: " +
|
||||
"accounts=${accountList.accounts.size}, " +
|
||||
"currencyStatusMap=${currencyStatusMap.size}",
|
||||
)
|
||||
val accountStatuses = accountList.accounts
|
||||
.filterIsInstance<Account.CryptoPortfolio>()
|
||||
.map { account ->
|
||||
|
|
@ -242,14 +283,18 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
): Flow<Map<AccountCurrencyId, CryptoCurrencyStatus>> {
|
||||
val walletId = userWallet.walletId
|
||||
val networkStatusFlow: SharedFlow<Map<Network.ID, NetworkStatus>> = networkStatusFlow(walletId)
|
||||
.onEach { logger.i("flattenCurrencyStatusFlow[$walletId]: networkStatuses emitted size=${it.size}") }
|
||||
.shareIn(this, started = SharingStarted.Eagerly, replay = 1)
|
||||
val stakingBalanceFlow: SharedFlow<Map<StakingID, Set<StakingBalance>>> = stakingFlow(userWallet)
|
||||
.onEach { logger.i("flattenCurrencyStatusFlow[$walletId]: stakingBalances emitted stakingIds=${it.size}") }
|
||||
.shareIn(this, started = SharingStarted.Eagerly, replay = 1)
|
||||
val quoteStatusFlow: SharedFlow<Map<CryptoCurrency.RawID, QuoteStatus>> = quoteStatusFlow()
|
||||
.onEach { logger.i("flattenCurrencyStatusFlow[$walletId]: quoteStatuses emitted size=${it.size}") }
|
||||
.shareIn(this, started = SharingStarted.Eagerly, replay = 1)
|
||||
|
||||
return flattenCurrency
|
||||
.distinctUntilChanged()
|
||||
.onEach { logger.i("flattenCurrencyStatusFlow[$walletId]: flattenCurrency emitted size=${it.size}") }
|
||||
.flatMapLatest { a ->
|
||||
combine(
|
||||
flow = networkStatusFlow,
|
||||
|
|
@ -264,6 +309,15 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.onEach { box ->
|
||||
logger.i(
|
||||
"flattenCurrencyStatusFlow[$walletId]: box emitted " +
|
||||
"currencies=${box.flattenCurrencyMap.size}, " +
|
||||
"networks=${box.networkStatusMap.size}, " +
|
||||
"stakings=${box.stakingBalanceMap.size}, " +
|
||||
"quotes=${box.quoteStatusMap.size}",
|
||||
)
|
||||
}
|
||||
.map { box ->
|
||||
val flattenCurrencyMap: Map<AccountCurrencyId, CryptoCurrency> = box.flattenCurrencyMap
|
||||
val networkStatusMap: Map<Network.ID, NetworkStatus> = box.networkStatusMap
|
||||
|
|
@ -402,4 +456,8 @@ internal class DefaultSingleAccountStatusListProducer @AssistedInject constructo
|
|||
interface Factory : SingleAccountStatusListProducer.Factory {
|
||||
override fun create(params: SingleAccountStatusListProducer.Params): DefaultSingleAccountStatusListProducer
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TAG = "SingleAccountStatusListProducer"
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import com.tangem.domain.models.account.Account
|
|||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusProducer
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
|
|
@ -27,27 +28,51 @@ class IsAccountsModeEnabledUseCase(
|
|||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
operator fun invoke(): Flow<Boolean> {
|
||||
TangemLogger.i("$TAG: invoke() started")
|
||||
|
||||
val cryptoMode = multiAccountListSupplier.invoke()
|
||||
.map { lists -> lists.any { it.hasMultipleCryptoPortfolios() } }
|
||||
.onEach { lists ->
|
||||
TangemLogger.i("$TAG: multiAccountListSupplier emitted ${lists.size} lists (cryptoMode branch)")
|
||||
}
|
||||
.map { lists ->
|
||||
val isCryptoMode = lists.any { it.hasMultipleCryptoPortfolios() }
|
||||
TangemLogger.i("$TAG: cryptoMode=$isCryptoMode")
|
||||
isCryptoMode
|
||||
}
|
||||
|
||||
val paymentMode = multiAccountListSupplier.invoke().flatMapLatest { lists ->
|
||||
val walletIdsWithPayment = lists.mapNotNull { list ->
|
||||
if (list.accounts.any { it is Account.Payment }) list.userWalletId else null
|
||||
}
|
||||
TangemLogger.i("$TAG: walletIdsWithPayment=${walletIdsWithPayment.size}")
|
||||
|
||||
if (walletIdsWithPayment.isEmpty()) {
|
||||
flowOf(false)
|
||||
} else {
|
||||
val flows = walletIdsWithPayment.map { walletId ->
|
||||
paymentAccountStatusSupplier.invoke(walletId)
|
||||
.onEach { status ->
|
||||
TangemLogger.i("$TAG: paymentStatus for $walletId = ${status.value::class.simpleName}")
|
||||
}
|
||||
.map { it.value.isActivePayment() }
|
||||
.onStart { emit(false) }
|
||||
.onStart {
|
||||
TangemLogger.i("$TAG: paymentAccountStatusSupplier onStart for $walletId")
|
||||
emit(false)
|
||||
}
|
||||
}
|
||||
combine(flows) { results ->
|
||||
val isPaymentMode = results.any { it }
|
||||
TangemLogger.i("$TAG: paymentMode combine result=$isPaymentMode (${results.toList()})")
|
||||
isPaymentMode
|
||||
}
|
||||
combine(flows) { results -> results.any { it } }
|
||||
}
|
||||
}
|
||||
|
||||
return combine(cryptoMode, paymentMode) { crypto, payment -> crypto || payment }
|
||||
return combine(cryptoMode, paymentMode) { crypto, payment ->
|
||||
val isEnabled = crypto || payment
|
||||
TangemLogger.i("$TAG: final combine crypto=$crypto, payment=$payment, result=$isEnabled")
|
||||
isEnabled
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
|
|
@ -89,5 +114,6 @@ class IsAccountsModeEnabledUseCase(
|
|||
|
||||
private companion object {
|
||||
const val PAYMENT_STATUS_SYNC_TIMEOUT_MS = 1_000L
|
||||
const val TAG = "IsAccountsModeEnabledUseCase"
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.utils.coroutines.combine7
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -22,6 +23,8 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -46,38 +49,69 @@ internal class AccountListSubscriber @AssistedInject constructor(
|
|||
override val isAddAndManageTokensEnabled: Boolean
|
||||
get() = walletFeatureToggles.isAddAndManageTokensEnabled
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> = combine7(
|
||||
flow1 = getAccountStatusListFlow(),
|
||||
flow2 = getAppCurrencyFlow(),
|
||||
flow3 = accountDependencies.expandedAccountsHolder.expandedAccounts(userWallet),
|
||||
flow4 = accountDependencies.isAccountsModeEnabledUseCase(),
|
||||
flow5 = yieldSupplyApyFlow(),
|
||||
flow6 = yieldSupplyGetShouldShowMainPromoFlow(),
|
||||
flow7 = stakingAvailabilityFlow(),
|
||||
) {
|
||||
accountList, appCurrency, expandedAccounts, isAccountMode,
|
||||
yieldSupplyApyMap, shouldShowMainPromo, stakingAvailabilityMap,
|
||||
->
|
||||
if (designFeatureToggles.isRedesignEnabled) {
|
||||
updateState2(
|
||||
accountList = accountList,
|
||||
appCurrency = appCurrency,
|
||||
expandedAccounts = expandedAccounts,
|
||||
isAccountMode = isAccountMode,
|
||||
yieldSupplyApyMap = yieldSupplyApyMap,
|
||||
stakingAvailabilityMap = stakingAvailabilityMap,
|
||||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
)
|
||||
} else {
|
||||
updateState(
|
||||
accountList = accountList,
|
||||
appCurrency = appCurrency,
|
||||
expandedAccounts = expandedAccounts,
|
||||
isAccountMode = isAccountMode,
|
||||
yieldSupplyApyMap = yieldSupplyApyMap,
|
||||
stakingAvailabilityMap = stakingAvailabilityMap,
|
||||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
val walletId = userWallet.walletId.stringValue
|
||||
TangemLogger.i("$TAG[$walletId]: create() called, building combine7")
|
||||
return combine7(
|
||||
flow1 = getAccountStatusListFlow()
|
||||
.onStart { TangemLogger.i("$TAG[$walletId]: flow1 accountStatusList subscribed") }
|
||||
.onEach { list ->
|
||||
val count = list.flattenCurrencies().size
|
||||
TangemLogger.i("$TAG[$walletId]: flow1 accountStatusList emitted (currencies=$count)")
|
||||
},
|
||||
flow2 = getAppCurrencyFlow()
|
||||
.onStart { TangemLogger.i("$TAG[$walletId]: flow2 appCurrency subscribed") }
|
||||
.onEach { TangemLogger.i("$TAG[$walletId]: flow2 appCurrency emitted=${it.code}") },
|
||||
flow3 = accountDependencies.expandedAccountsHolder.expandedAccounts(userWallet)
|
||||
.onStart { TangemLogger.i("$TAG[$walletId]: flow3 expandedAccounts subscribed") }
|
||||
.onEach { TangemLogger.i("$TAG[$walletId]: flow3 expandedAccounts emitted (size=${it.size})") },
|
||||
flow4 = accountDependencies.isAccountsModeEnabledUseCase()
|
||||
.onStart { TangemLogger.i("$TAG[$walletId]: flow4 isAccountsModeEnabled subscribed") }
|
||||
.onEach { TangemLogger.i("$TAG[$walletId]: flow4 isAccountsModeEnabled emitted=$it") },
|
||||
flow5 = yieldSupplyApyFlow()
|
||||
.onStart { TangemLogger.i("$TAG[$walletId]: flow5 yieldSupplyApy subscribed") }
|
||||
.onEach { TangemLogger.i("$TAG[$walletId]: flow5 yieldSupplyApy emitted (size=${it.size})") },
|
||||
flow6 = yieldSupplyGetShouldShowMainPromoFlow()
|
||||
.onStart { TangemLogger.i("$TAG[$walletId]: flow6 shouldShowMainPromo subscribed") }
|
||||
.onEach { TangemLogger.i("$TAG[$walletId]: flow6 shouldShowMainPromo emitted=$it") },
|
||||
flow7 = stakingAvailabilityFlow()
|
||||
.onStart { TangemLogger.i("$TAG[$walletId]: flow7 stakingAvailability subscribed") }
|
||||
.onEach { TangemLogger.i("$TAG[$walletId]: flow7 stakingAvailability emitted (size=${it.size})") },
|
||||
) {
|
||||
accountList, appCurrency, expandedAccounts, isAccountMode,
|
||||
yieldSupplyApyMap, shouldShowMainPromo, stakingAvailabilityMap,
|
||||
->
|
||||
TangemLogger.i(
|
||||
"$TAG[$walletId]: combine7 transform fired — " +
|
||||
"currencies=${accountList.flattenCurrencies().size}, " +
|
||||
"appCurrency=${appCurrency.code}, " +
|
||||
"expanded=${expandedAccounts.size}, " +
|
||||
"isAccountMode=$isAccountMode, " +
|
||||
"apyMap=${yieldSupplyApyMap.size}, " +
|
||||
"promo=$shouldShowMainPromo, " +
|
||||
"stakingMap=${stakingAvailabilityMap.size}",
|
||||
)
|
||||
if (designFeatureToggles.isRedesignEnabled) {
|
||||
updateState2(
|
||||
accountList = accountList,
|
||||
appCurrency = appCurrency,
|
||||
expandedAccounts = expandedAccounts,
|
||||
isAccountMode = isAccountMode,
|
||||
yieldSupplyApyMap = yieldSupplyApyMap,
|
||||
stakingAvailabilityMap = stakingAvailabilityMap,
|
||||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
)
|
||||
} else {
|
||||
updateState(
|
||||
accountList = accountList,
|
||||
appCurrency = appCurrency,
|
||||
expandedAccounts = expandedAccounts,
|
||||
isAccountMode = isAccountMode,
|
||||
yieldSupplyApyMap = yieldSupplyApyMap,
|
||||
stakingAvailabilityMap = stakingAvailabilityMap,
|
||||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,4 +138,8 @@ internal class AccountListSubscriber @AssistedInject constructor(
|
|||
interface Factory {
|
||||
fun create(userWallet: UserWallet): AccountListSubscriber
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TAG = "AccountListSubscriber"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue