Updated on 2026-08-14
This commit is contained in:
parent
3aef6bf69c
commit
b340fc7e33
18 changed files with 357 additions and 107 deletions
|
|
@ -9,10 +9,12 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
|||
import com.tangem.feature.wallet.presentation.wallet.loaders.implementors.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class WalletContentLoaderFactory @Inject constructor(
|
||||
private val multiWalletContentLoaderFactory: MultiWalletContentLoaderFactory,
|
||||
private val singleWalletWithTokenContentLoaderFactory: SingleWalletWithTokenContentLoaderFactory,
|
||||
private val singleWalletWithTokenContentLoaderV2Factory: SingleWalletWithTokenContentLoaderV2.Factory,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val singleWalletContentLoaderFactory: SingleWalletContentLoaderFactory,
|
||||
private val singleWalletContentLoaderV2Factory: SingleWalletContentLoaderV2.Factory,
|
||||
|
|
@ -29,7 +31,11 @@ internal class WalletContentLoaderFactory @Inject constructor(
|
|||
multiWalletContentLoaderFactory.create(userWallet, clickIntents)
|
||||
}
|
||||
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() -> {
|
||||
singleWalletWithTokenContentLoaderFactory.create(userWallet, clickIntents)
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
singleWalletWithTokenContentLoaderV2Factory.create(userWallet)
|
||||
} else {
|
||||
singleWalletWithTokenContentLoaderFactory.create(userWallet, clickIntents)
|
||||
}
|
||||
}
|
||||
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isVisaWallet() -> {
|
||||
visaWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
|
|
@ -16,8 +17,8 @@ import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenList
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
|
||||
@Deprecated("Use SingleWalletWithTokenContentLoaderV2 instead")
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenContentLoader(
|
||||
private val userWallet: UserWallet.Cold,
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
|||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
|
|
@ -16,11 +17,11 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO: Refactor
|
||||
@Suppress("LongParameterList")
|
||||
@Deprecated("Use SingleWalletWithTokenContentLoaderV2.Factory instead")
|
||||
@ModelScoped
|
||||
internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenContentLoaderV2 @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet.Cold,
|
||||
private val singleWalletWithTokenSubscriberFactory: SingleWalletWithTokenSubscriber.Factory,
|
||||
private val checkWalletWithFundsSubscriberFactory: CheckWalletWithFundsSubscriber.Factory,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val stateController: WalletStateController,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> = listOf(
|
||||
singleWalletWithTokenSubscriberFactory.create(userWallet),
|
||||
MultiWalletWarningsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateController,
|
||||
clickIntents = clickIntents,
|
||||
getMultiWalletWarningsFactory = getMultiWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
|
||||
),
|
||||
WalletDropDownItemsSubscriber(
|
||||
stateHolder = stateController,
|
||||
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
|
||||
clickIntents = clickIntents,
|
||||
),
|
||||
checkWalletWithFundsSubscriberFactory.create(userWallet),
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet.Cold): SingleWalletWithTokenContentLoaderV2
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.core.utils.getOrElse
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListErrorTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TokenConverterParams
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Basic implementation of [WalletSubscriber] for wallet with accounts.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
|
||||
|
||||
abstract val accountDependencies: AccountDependencies
|
||||
abstract val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase
|
||||
abstract val stateController: WalletStateController
|
||||
abstract val clickIntents: WalletClickIntents
|
||||
|
||||
override val singleAccountStatusListSupplier: SingleAccountStatusListSupplier
|
||||
get() = accountDependencies.singleAccountStatusListSupplier
|
||||
|
||||
protected fun getAppCurrencyFlow(): Flow<AppCurrency> {
|
||||
return getSelectedAppCurrencyUseCase.invokeOrDefault()
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
protected fun updateState(
|
||||
accountList: AccountStatusList,
|
||||
appCurrency: AppCurrency,
|
||||
expandedAccounts: Set<AccountId>,
|
||||
isAccountMode: Boolean,
|
||||
yieldSupplyApyMap: Map<String, String> = emptyMap(),
|
||||
stakingApyMap: Map<String, List<Yield.Validator>> = emptyMap(),
|
||||
) {
|
||||
val accountFlattenCurrencies = accountList.flattenCurrencies()
|
||||
val mainAccount = accountList.mainAccount
|
||||
|
||||
when {
|
||||
!isAccountMode -> {
|
||||
val isMainAccountEmpty = mainAccount.tokenList.flattenCurrencies().isEmpty()
|
||||
val maybeTokenList = if (isMainAccountEmpty) {
|
||||
Lce.Error(TokenListError.EmptyTokens)
|
||||
} else {
|
||||
Lce.Content(mainAccount.tokenList)
|
||||
}
|
||||
|
||||
singleAccountTransform(
|
||||
maybeTokenList = maybeTokenList,
|
||||
appCurrency = appCurrency,
|
||||
portfolioId = PortfolioId(mainAccount.accountId),
|
||||
yieldSupplyApyMap = yieldSupplyApyMap,
|
||||
stakingApyMap = stakingApyMap,
|
||||
)
|
||||
}
|
||||
isAccountMode -> {
|
||||
val isAllAccountsEmpty = accountFlattenCurrencies.isEmpty()
|
||||
if (isAllAccountsEmpty) {
|
||||
stateController.update(
|
||||
SetTokenListErrorTransformer(
|
||||
selectedWallet = userWallet,
|
||||
error = TokenListError.EmptyTokens,
|
||||
appCurrency = appCurrency,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
val convertParams = TokenConverterParams.Account(accountList, expandedAccounts)
|
||||
|
||||
updateContent(convertParams, appCurrency, yieldSupplyApyMap, stakingApyMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun singleAccountTransform(
|
||||
maybeTokenList: Lce<TokenListError, TokenList>,
|
||||
appCurrency: AppCurrency,
|
||||
portfolioId: PortfolioId,
|
||||
yieldSupplyApyMap: Map<String, String> = emptyMap(),
|
||||
stakingApyMap: Map<String, List<Yield.Validator>> = emptyMap(),
|
||||
) {
|
||||
val tokenList = maybeTokenList.getOrElse(
|
||||
ifLoading = { maybeContent ->
|
||||
val isRefreshing = stateController.getWalletState(userWallet.walletId)
|
||||
?.pullToRefreshConfig
|
||||
?.isRefreshing == true
|
||||
|
||||
maybeContent
|
||||
?.takeIf { !isRefreshing }
|
||||
?: return
|
||||
},
|
||||
ifError = { e ->
|
||||
Timber.e("Failed to load token list: $e")
|
||||
stateController.update(
|
||||
SetTokenListErrorTransformer(
|
||||
selectedWallet = userWallet,
|
||||
error = e,
|
||||
appCurrency = appCurrency,
|
||||
),
|
||||
)
|
||||
return
|
||||
},
|
||||
)
|
||||
|
||||
updateContent(
|
||||
params = TokenConverterParams.Wallet(portfolioId, tokenList),
|
||||
appCurrency = appCurrency,
|
||||
yieldSupplyApyMap = yieldSupplyApyMap,
|
||||
stakingApyMap = stakingApyMap,
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateContent(
|
||||
params: TokenConverterParams,
|
||||
appCurrency: AppCurrency,
|
||||
yieldSupplyApyMap: Map<String, String> = emptyMap(),
|
||||
stakingApyMap: Map<String, List<Yield.Validator>> = emptyMap(),
|
||||
) {
|
||||
stateController.update(
|
||||
SetTokenListTransformer(
|
||||
params = params,
|
||||
userWallet = userWallet,
|
||||
appCurrency = appCurrency,
|
||||
clickIntents = clickIntents,
|
||||
yieldSupplyApyMap = yieldSupplyApyMap,
|
||||
stakingApyMap = stakingApyMap,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,9 @@ import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
|
|
@ -13,11 +16,12 @@ import kotlinx.coroutines.flow.*
|
|||
* @property userWallet The user wallet.
|
||||
* @property singleAccountStatusListSupplier Supplier for account status list.
|
||||
* @property walletWithFundsChecker The checker to notify when funds are detected.
|
||||
* @property dispatchers Coroutine dispatcher provider.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class CheckWalletWithFundsSubscriber(
|
||||
override val userWallet: UserWallet,
|
||||
internal class CheckWalletWithFundsSubscriber @AssistedInject constructor(
|
||||
@Assisted override val userWallet: UserWallet,
|
||||
override val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
|
|
@ -30,4 +34,9 @@ internal class CheckWalletWithFundsSubscriber(
|
|||
.onEach { walletWithFundsChecker.check(userWalletId = userWallet.walletId, currencies = it) }
|
||||
.flowOn(dispatchers.default)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet): CheckWalletWithFundsSubscriber
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
|||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Deprecated("Use SingleWalletWithTokenSubscriber instead")
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenListSubscriber(
|
||||
override val userWallet: UserWallet.Cold,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
internal class SingleWalletWithTokenSubscriber @AssistedInject constructor(
|
||||
@Assisted override val userWallet: UserWallet.Cold,
|
||||
override val accountDependencies: AccountDependencies,
|
||||
override val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
override val stateController: WalletStateController,
|
||||
override val clickIntents: WalletClickIntents,
|
||||
) : BasicAccountListSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<Unit> = combine(
|
||||
flow = getAccountStatusListFlow(),
|
||||
flow2 = getAppCurrencyFlow(),
|
||||
flow3 = accountDependencies.expandedAccountsHolder.expandedAccounts(userWallet),
|
||||
flow4 = accountDependencies.isAccountsModeEnabledUseCase(),
|
||||
transform = ::updateState,
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet.Cold): SingleWalletWithTokenSubscriber
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue