diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/WalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/WalletContentLoaderFactory.kt index 3e9dc79a01..14aa6b96e4 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/WalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/WalletContentLoaderFactory.kt @@ -13,6 +13,7 @@ import javax.inject.Inject @ModelScoped internal class WalletContentLoaderFactory @Inject constructor( private val multiWalletContentLoaderFactory: MultiWalletContentLoaderFactory, + private val multiWalletContentLoaderV2Factory: MultiWalletContentLoaderV2.Factory, private val singleWalletWithTokenContentLoaderFactory: SingleWalletWithTokenContentLoaderFactory, private val singleWalletWithTokenContentLoaderV2Factory: SingleWalletWithTokenContentLoaderV2.Factory, private val accountsFeatureToggles: AccountsFeatureToggles, @@ -28,7 +29,11 @@ internal class WalletContentLoaderFactory @Inject constructor( ): WalletContentLoader? { return when { userWallet.isMultiCurrency -> { - multiWalletContentLoaderFactory.create(userWallet, clickIntents) + if (accountsFeatureToggles.isFeatureEnabled) { + multiWalletContentLoaderV2Factory.create(userWallet) + } else { + multiWalletContentLoaderFactory.create(userWallet, clickIntents) + } } userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() -> { if (accountsFeatureToggles.isFeatureEnabled) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt index b08d9fb996..41098b86a2 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt @@ -12,7 +12,6 @@ import com.tangem.domain.wallets.repository.WalletsRepository 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 @@ -23,6 +22,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController import com.tangem.feature.wallet.presentation.wallet.subscribers.* @Suppress("LongParameterList") +@Deprecated("Use MultiWalletContentLoaderV2 instead") @ModelScoped internal class MultiWalletContentLoader( private val userWallet: UserWallet, @@ -41,7 +41,6 @@ internal class MultiWalletContentLoader( private val getStoryContentUseCase: GetStoryContentUseCase, private val walletsRepository: WalletsRepository, private val currenciesRepository: CurrenciesRepository, - private val accountDependencies: AccountDependencies, private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, private val stakingApyFlowUseCase: StakingApyFlowUseCase, ) : WalletContentLoader(id = userWallet.walletId) { @@ -57,7 +56,6 @@ internal class MultiWalletContentLoader( tokenListStore = tokenListStore, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, applyTokenListSortingUseCase = applyTokenListSortingUseCase, - accountDependencies = accountDependencies, yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase, stakingApyFlowUseCase = stakingApyFlowUseCase, ).let(::add) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt index e2dae7da64..af3187ba3c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt @@ -2,12 +2,12 @@ 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.models.wallet.UserWallet import com.tangem.domain.nft.GetNFTCollectionsUseCase import com.tangem.domain.promo.GetStoryContentUseCase +import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.domain.tokens.ApplyTokenListSortingUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase @@ -19,10 +19,10 @@ 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 @Suppress("LongParameterList") +@Deprecated("Use MultiWalletContentLoaderV2.Factory instead") @ModelScoped internal class MultiWalletContentLoaderFactory @Inject constructor( private val stateHolder: WalletStateController, @@ -39,7 +39,6 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( private val walletsRepository: WalletsRepository, private val getNFTCollectionsUseCase: GetNFTCollectionsUseCase, private val currenciesRepository: CurrenciesRepository, - private val accountDependencies: AccountDependencies, private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, private val stakingApyFlowUseCase: StakingApyFlowUseCase, ) { @@ -62,7 +61,6 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( walletsRepository = walletsRepository, getNFTCollectionsUseCase = getNFTCollectionsUseCase, currenciesRepository = currenciesRepository, - accountDependencies = accountDependencies, yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase, stakingApyFlowUseCase = stakingApyFlowUseCase, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderV2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderV2.kt new file mode 100644 index 0000000000..78b48bf1b3 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderV2.kt @@ -0,0 +1,59 @@ +package com.tangem.feature.wallet.presentation.wallet.loaders.implementors + +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.promo.GetStoryContentUseCase +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 MultiWalletContentLoaderV2 @AssistedInject constructor( + @Assisted private val userWallet: UserWallet, + private val accountListSubscriberFactory: AccountListSubscriber.Factory, + private val walletNFTListSubscriberV2Factory: WalletNFTListSubscriberV2.Factory, + private val stateController: WalletStateController, + private val clickIntents: WalletClickIntents, + private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, + private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, + private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory, + private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, + private val getStoryContentUseCase: GetStoryContentUseCase, + private val checkWalletWithFundsSubscriberFactory: CheckWalletWithFundsSubscriber.Factory, +) : WalletContentLoader(id = userWallet.walletId) { + + override fun create(): List = listOf( + accountListSubscriberFactory.create(userWallet = userWallet), + walletNFTListSubscriberV2Factory.create(userWallet = userWallet), + checkWalletWithFundsSubscriberFactory.create(userWallet = userWallet), + MultiWalletWarningsSubscriber( + userWallet = userWallet, + stateHolder = stateController, + clickIntents = clickIntents, + getMultiWalletWarningsFactory = getMultiWalletWarningsFactory, + walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, + walletWarningsSingleEventSender = walletWarningsSingleEventSender, + ), + MultiWalletActionButtonsSubscriber( + userWallet = userWallet, + stateHolder = stateController, + getStoryContentUseCase = getStoryContentUseCase, + ), + WalletDropDownItemsSubscriber( + stateHolder = stateController, + shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, + clickIntents = clickIntents, + ), + ) + + @AssistedFactory + interface Factory { + fun create(userWallet: UserWallet): MultiWalletContentLoaderV2 + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt index c2fbf4fa35..e18239073a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt @@ -7,7 +7,6 @@ import com.tangem.domain.staking.usecase.StakingApyFlowUseCase 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 @@ -32,7 +31,6 @@ internal class SingleWalletWithTokenContentLoader( private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, - private val accountDependencies: AccountDependencies, private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, private val stakingApyFlowUseCase: StakingApyFlowUseCase, ) : WalletContentLoader(id = userWallet.walletId) { @@ -47,7 +45,6 @@ internal class SingleWalletWithTokenContentLoader( walletWithFundsChecker = walletWithFundsChecker, tokenListStore = tokenListStore, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, - accountDependencies = accountDependencies, yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase, stakingApyFlowUseCase = stakingApyFlowUseCase, ).let(::add) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt index 7fe9f9188e..d8ff65a997 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt @@ -8,7 +8,6 @@ import com.tangem.domain.staking.usecase.StakingApyFlowUseCase 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 @@ -33,7 +32,6 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, - private val accountDependencies: AccountDependencies, private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, private val stakingApyFlowUseCase: StakingApyFlowUseCase, ) { @@ -52,7 +50,6 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( walletWarningsSingleEventSender = walletWarningsSingleEventSender, getStoryContentUseCase = getStoryContentUseCase, shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, - accountDependencies = accountDependencies, yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase, stakingApyFlowUseCase = stakingApyFlowUseCase, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/AccountListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/AccountListSubscriber.kt new file mode 100644 index 0000000000..1a01d99ec3 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/AccountListSubscriber.kt @@ -0,0 +1,57 @@ +package com.tangem.feature.wallet.presentation.wallet.subscribers + +import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.staking.model.stakekit.Yield +import com.tangem.domain.staking.usecase.StakingApyFlowUseCase +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.state.WalletStateController +import com.tangem.utils.coroutines.combine6 +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.distinctUntilChanged + +/** + * Subscriber that monitors account list related data and updates the wallet state accordingly. + * +[REDACTED_AUTHOR] + */ +@Suppress("LongParameterList") +internal class AccountListSubscriber @AssistedInject constructor( + @Assisted override val userWallet: UserWallet, + override val accountDependencies: AccountDependencies, + override val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, + override val stateController: WalletStateController, + override val clickIntents: WalletClickIntents, + private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, + private val stakingApyFlowUseCase: StakingApyFlowUseCase, +) : BasicAccountListSubscriber() { + + override fun create(coroutineScope: CoroutineScope): Flow<*> = combine6( + flow1 = getAccountStatusListFlow(), + flow2 = getAppCurrencyFlow(), + flow3 = accountDependencies.expandedAccountsHolder.expandedAccounts(userWallet), + flow4 = accountDependencies.isAccountsModeEnabledUseCase(), + flow5 = yieldSupplyApyFlow(), + flow6 = stakingApyFlow(), + transform = ::updateState, + ) + + private fun yieldSupplyApyFlow(): Flow> { + return yieldSupplyApyFlowUseCase().distinctUntilChanged() + } + + private fun stakingApyFlow(): Flow>> { + return stakingApyFlowUseCase().distinctUntilChanged() + } + + @AssistedFactory + interface Factory { + fun create(userWallet: UserWallet): AccountListSubscriber + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt index 514d33f97c..e827068c9b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt @@ -1,7 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers import arrow.core.getOrElse -import com.tangem.domain.account.models.AccountStatusList import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.core.lce.Lce @@ -9,7 +8,6 @@ import com.tangem.domain.core.lce.LceFlow import com.tangem.domain.core.utils.getOrElse import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.TotalFiatBalance -import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.tokenlist.TokenList import com.tangem.domain.models.wallet.UserWallet @@ -18,7 +16,6 @@ import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.domain.tokens.error.TokenListError 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.domain.WalletWithFundsChecker import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController @@ -26,43 +23,33 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetToken import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListTransformer import com.tangem.feature.wallet.presentation.wallet.state.transformers.TokenConverterParams import com.tangem.utils.coroutines.JobHolder -import com.tangem.utils.coroutines.combine6 import com.tangem.utils.coroutines.saveIn import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* -import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import timber.log.Timber +@Deprecated("Use AccountListSubscriber instead") @Suppress("LongParameterList") -internal abstract class BasicTokenListSubscriber : WalletSubscriber() { - protected abstract val userWallet: UserWallet - protected abstract val stateHolder: WalletStateController - protected abstract val clickIntents: WalletClickIntents - protected abstract val tokenListAnalyticsSender: TokenListAnalyticsSender - protected abstract val walletWithFundsChecker: WalletWithFundsChecker - protected abstract val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase - protected abstract val accountDependencies: AccountDependencies - protected abstract val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase - protected abstract val stakingApyFlowUseCase: StakingApyFlowUseCase +internal abstract class BasicTokenListSubscriber( + private val userWallet: UserWallet, + private val stateHolder: WalletStateController, + private val clickIntents: WalletClickIntents, + private val tokenListAnalyticsSender: TokenListAnalyticsSender, + private val walletWithFundsChecker: WalletWithFundsChecker, + private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, + private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, + private val stakingApyFlowUseCase: StakingApyFlowUseCase, +) : WalletSubscriber() { private val sendAnalyticsJobHolder = JobHolder() private val onTokenListReceivedJobHolder = JobHolder() - protected val isAccountsEnabled get() = accountDependencies.accountsFeatureToggles.isFeatureEnabled protected abstract fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow - protected abstract fun accountListFlow(coroutineScope: CoroutineScope): Flow - protected abstract suspend fun onTokenListReceived(maybeTokenList: Lce) - protected open suspend fun onAccountListReceived() = { - // todo account updateSortingIfNeeded? like [onTokenListReceived] - } - override fun create(coroutineScope: CoroutineScope): Flow<*> = - if (isAccountsEnabled) createAccountListFlow(coroutineScope) else createTokenListFlow(coroutineScope) - - private fun createTokenListFlow(coroutineScope: CoroutineScope): Flow<*> { + override fun create(coroutineScope: CoroutineScope): Flow<*> { return combine( flow = tokenListFlow(coroutineScope) .onEach { maybeTokenList -> @@ -83,121 +70,41 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { flow3 = yieldSupplyApyFlow(), flow4 = stakingApyFlow(), transform = { maybeTokenList, appCurrency, yieldSupplyApyMap, stakingApyMap -> - singleAccountTransform( - maybeTokenList = maybeTokenList, + val tokenList = maybeTokenList.getOrElse( + ifLoading = { maybeContent -> + val isRefreshing = stateHolder.getWalletState(userWallet.walletId) + ?.pullToRefreshConfig + ?.isRefreshing == true + + maybeContent + ?.takeIf { !isRefreshing } + ?: return@combine + }, + ifError = { e -> + Timber.e("Failed to load token list: $e") + stateHolder.update( + SetTokenListErrorTransformer( + selectedWallet = userWallet, + error = e, + appCurrency = appCurrency, + ), + ) + return@combine + }, + ) + + updateContent( + params = TokenConverterParams.Wallet(PortfolioId(userWallet.walletId), tokenList), appCurrency = appCurrency, - portfolioId = PortfolioId(userWallet.walletId), yieldSupplyApyMap = yieldSupplyApyMap, stakingApyMap = stakingApyMap, ) + + walletWithFundsChecker.check(tokenList) }, ) } - private suspend fun singleAccountTransform( - maybeTokenList: Lce, - appCurrency: AppCurrency, - portfolioId: PortfolioId, - yieldSupplyApyMap: Map, - stakingApyMap: Map>, - ) { - val tokenList = maybeTokenList.getOrElse( - ifLoading = { maybeContent -> - val isRefreshing = stateHolder.getWalletState(userWallet.walletId) - ?.pullToRefreshConfig - ?.isRefreshing == true - - maybeContent - ?.takeIf { !isRefreshing } - ?: return - }, - ifError = { e -> - Timber.e("Failed to load token list: $e") - stateHolder.update( - SetTokenListErrorTransformer( - selectedWallet = userWallet, - error = e, - appCurrency = appCurrency, - ), - ) - return - }, - ) - updateContent( - params = TokenConverterParams.Wallet(portfolioId, tokenList), - appCurrency = appCurrency, - yieldSupplyApyMap = yieldSupplyApyMap, - stakingApyMap = stakingApyMap, - ) - - walletWithFundsChecker.check(tokenList) - } - - private fun createAccountListFlow(coroutineScope: CoroutineScope): Flow<*> = combine6( - flow1 = accountListFlow(coroutineScope) - .onEach { accountStatusList -> - coroutineScope.launch { - sendTokenListAnalytics( - flattenCurrencies = accountStatusList.flattenCurrencies(), - totalFiatBalance = accountStatusList.totalFiatBalance, - ) - }.saveIn(sendAnalyticsJobHolder) - } - .distinctUntilChanged(), - flow2 = appCurrencyFlow(), - flow3 = accountDependencies.expandedAccountsHolder.expandedAccounts(userWallet), - flow4 = accountDependencies.isAccountsModeEnabledUseCase(), - flow5 = yieldSupplyApyFlow(), - flow6 = stakingApyFlow(), - transform = { accountList, appCurrency, expandedAccounts, isAccountMode, yieldSupplyApyMap, stakingApyMap -> - val accountFlattenTokensList = accountList.flattenTokens() - val accountFlattenCurrencies = accountFlattenTokensList - .map { it.flattenCurrencies() } - .flatten() - - val mainAccount = accountList.mainAccount - - suspend fun singleAccountTransform(maybeTokenList: Lce) = - this.singleAccountTransform( - maybeTokenList, - appCurrency, - PortfolioId(mainAccount.account.accountId), - yieldSupplyApyMap, - stakingApyMap, - ) - - when { - !isAccountMode -> when (mainAccount.tokenList.flattenCurrencies().isEmpty()) { - true -> singleAccountTransform(Lce.Error(TokenListError.EmptyTokens)) - false -> singleAccountTransform(Lce.Content(mainAccount.tokenList)) - } - - isAccountMode -> when (accountFlattenCurrencies.isEmpty()) { - true -> stateHolder.update( - SetTokenListErrorTransformer( - selectedWallet = userWallet, - error = TokenListError.EmptyTokens, - appCurrency = appCurrency, - ), - ) - false -> { - val convertParams = TokenConverterParams.Account(accountList, expandedAccounts) - updateContent(convertParams, appCurrency, yieldSupplyApyMap, stakingApyMap) - accountFlattenTokensList - .map { tokenList -> coroutineScope.launch { walletWithFundsChecker.check(tokenList) } } - .joinAll() - } - } - } - }, - ) - - private fun AccountStatusList.flattenTokens(): List = this.accountStatuses.map { - when (it) { - is AccountStatus.CryptoPortfolio -> it.tokenList - } - } - private suspend fun sendTokenListAnalytics( flattenCurrencies: List?, totalFiatBalance: TotalFiatBalance?, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicWalletSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicWalletSubscriber.kt index 9254f90e44..585a48c0b0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicWalletSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicWalletSubscriber.kt @@ -4,6 +4,7 @@ import com.tangem.domain.account.models.AccountStatusList import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.models.account.AccountStatus +import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.conflate @@ -41,16 +42,23 @@ internal abstract class BasicWalletSubscriber : WalletSubscriber() { * * @return A [Flow] emitting the [AccountStatus] of the wallet, distinct and conflated. */ - protected fun getMainAccountStatusFlow(): Flow { + protected fun getMainAccountStatusFlow(): Flow { return getAccountStatusListFlow() .mapNotNull { accountStatusList -> accountStatusList.accountStatuses.find { accountStatus -> when (accountStatus) { is AccountStatus.CryptoPortfolio -> accountStatus.account.isMainAccount } - } + } as? AccountStatus.CryptoPortfolio } .distinctUntilChanged() .conflate() } + + protected fun getCryptoCurrencyStatusesFlow(): Flow> { + return getAccountStatusListFlow() + .mapNotNull(AccountStatusList::flattenCurrencies) + .distinctUntilChanged() + .conflate() + } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt index 8cea37e832..36220cd6e1 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt @@ -1,7 +1,5 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers -import com.tangem.domain.account.models.AccountStatusList -import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.core.lce.Lce import com.tangem.domain.core.lce.LceFlow @@ -15,28 +13,35 @@ import com.tangem.domain.tokens.ApplyTokenListSortingUseCase import com.tangem.domain.tokens.error.TokenListError 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.domain.MultiWalletTokenListStore import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow +@Deprecated("Use AccountListSubscriber instead") @Suppress("LongParameterList") internal class MultiWalletTokenListSubscriber( - override val userWallet: UserWallet, + private val userWallet: UserWallet, private val tokenListStore: MultiWalletTokenListStore, private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase, - override val stateHolder: WalletStateController, - override val clickIntents: WalletClickIntents, - override val tokenListAnalyticsSender: TokenListAnalyticsSender, - override val walletWithFundsChecker: WalletWithFundsChecker, - override val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, - override val accountDependencies: AccountDependencies, - override val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, - override val stakingApyFlowUseCase: StakingApyFlowUseCase, -) : BasicTokenListSubscriber() { + stateHolder: WalletStateController, + clickIntents: WalletClickIntents, + tokenListAnalyticsSender: TokenListAnalyticsSender, + walletWithFundsChecker: WalletWithFundsChecker, + getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, + yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, + stakingApyFlowUseCase: StakingApyFlowUseCase, +) : BasicTokenListSubscriber( + userWallet = userWallet, + stateHolder = stateHolder, + clickIntents = clickIntents, + tokenListAnalyticsSender = tokenListAnalyticsSender, + walletWithFundsChecker = walletWithFundsChecker, + getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, + yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase, + stakingApyFlowUseCase = stakingApyFlowUseCase, +) { override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow { tokenListStore.addIfNot(userWallet.walletId, coroutineScope) @@ -44,11 +49,6 @@ internal class MultiWalletTokenListSubscriber( return tokenListStore.getOrThrow(userWallet.walletId) } - override fun accountListFlow(coroutineScope: CoroutineScope): Flow { - val params = SingleAccountStatusListProducer.Params(userWallet.walletId) - return accountDependencies.singleAccountStatusListSupplier(params) - } - override suspend fun onTokenListReceived(maybeTokenList: Lce) { updateSortingIfNeeded(maybeTokenList) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt index cb4085687e..e686dd4e20 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt @@ -1,7 +1,5 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers -import com.tangem.domain.account.models.AccountStatusList -import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.core.lce.Lce import com.tangem.domain.core.lce.LceFlow @@ -11,28 +9,34 @@ import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.domain.tokens.error.TokenListError 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.domain.MultiWalletTokenListStore import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker 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, + private val userWallet: UserWallet.Cold, private val tokenListStore: MultiWalletTokenListStore, - override val stateHolder: WalletStateController, - override val clickIntents: WalletClickIntents, - override val tokenListAnalyticsSender: TokenListAnalyticsSender, - override val walletWithFundsChecker: WalletWithFundsChecker, - override val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, - override val accountDependencies: AccountDependencies, - override val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, - override val stakingApyFlowUseCase: StakingApyFlowUseCase, -) : BasicTokenListSubscriber() { + stateHolder: WalletStateController, + clickIntents: WalletClickIntents, + tokenListAnalyticsSender: TokenListAnalyticsSender, + walletWithFundsChecker: WalletWithFundsChecker, + getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, + yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, + stakingApyFlowUseCase: StakingApyFlowUseCase, +) : BasicTokenListSubscriber( + userWallet = userWallet, + stateHolder = stateHolder, + clickIntents = clickIntents, + tokenListAnalyticsSender = tokenListAnalyticsSender, + walletWithFundsChecker = walletWithFundsChecker, + getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, + yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase, + stakingApyFlowUseCase = stakingApyFlowUseCase, +) { override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow { tokenListStore.addIfNot(userWallet.walletId, coroutineScope) @@ -40,10 +44,5 @@ internal class SingleWalletWithTokenListSubscriber( return tokenListStore.getOrThrow(userWallet.walletId) } - override fun accountListFlow(coroutineScope: CoroutineScope): Flow { - val params = SingleAccountStatusListProducer.Params(userWallet.walletId) - return accountDependencies.singleAccountStatusListSupplier(params) - } - override suspend fun onTokenListReceived(maybeTokenList: Lce) = Unit } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/WalletNFTListSubscriberV2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/WalletNFTListSubscriberV2.kt new file mode 100644 index 0000000000..aac248d2ba --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/WalletNFTListSubscriberV2.kt @@ -0,0 +1,66 @@ +package com.tangem.feature.wallet.presentation.wallet.subscribers + +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.nft.GetNFTCollectionsUseCase +import com.tangem.domain.wallets.repository.WalletsRepository +import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents +import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController +import com.tangem.feature.wallet.presentation.wallet.state.transformers.RemoveNFTCollectionsTransformer +import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetNFTCollectionsTransformer +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.* + +internal class WalletNFTListSubscriberV2 @AssistedInject constructor( + @Assisted override val userWallet: UserWallet, + override val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, + private val walletsRepository: WalletsRepository, + private val getNFTCollectionsUseCase: GetNFTCollectionsUseCase, + private val stateController: WalletStateController, + private val clickIntents: WalletClickIntents, +) : BasicWalletSubscriber() { + + @OptIn(ExperimentalCoroutinesApi::class) + override fun create(coroutineScope: CoroutineScope): Flow<*> = combine( + flow = walletsRepository.nftEnabledStatus(userWallet.walletId), + flow2 = getCryptoCurrencyStatusesFlow(), + transform = ::Pair, + ) + .distinctUntilChanged() + .flatMapLatest { (nftEnabled, currencies) -> + // if NFT is enabled for this wallet and there are currencies, + // then start observing changes from store and apply transformer if need + if (nftEnabled && currencies.isNotEmpty()) { + getNFTCollectionsUseCase(userWallet.walletId) + .shareIn( + scope = coroutineScope, + started = SharingStarted.WhileSubscribed(), + replay = 1, + ) + .onEach { + stateController.update( + SetNFTCollectionsTransformer( + userWalletId = userWallet.walletId, + nftCollections = it, + onItemClick = { clickIntents.onNFTClick(userWallet) }, + ), + ) + } + } else { + // otherwise, hide NFT from wallet + stateController.update( + RemoveNFTCollectionsTransformer(userWallet.walletId), + ) + emptyFlow() + } + } + + @AssistedFactory + interface Factory { + fun create(userWallet: UserWallet): WalletNFTListSubscriberV2 + } +} \ No newline at end of file