From a67d482c3aa3e2292701957367fb457377bdc457 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 29 Aug 2024 14:51:47 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../converter/UserWalletItemUMConverter.kt | 2 + .../tokens/GetWalletTotalBalanceUseCase.kt | 4 +- .../portfolio/impl/loader/PortfolioData.kt | 26 +++++ .../impl/loader/PortfolioDataLoader.kt | 105 ++++++++++++++++++ .../impl/ui/WalletSelectorBottomSheet.kt | 2 - .../ui/state/WalletSelectorBSContentUM.kt | 1 - 6 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/loader/PortfolioData.kt create mode 100644 features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/loader/PortfolioDataLoader.kt diff --git a/common/ui/src/main/java/com/tangem/common/ui/userwallet/converter/UserWalletItemUMConverter.kt b/common/ui/src/main/java/com/tangem/common/ui/userwallet/converter/UserWalletItemUMConverter.kt index 704315fc82..163168be81 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/userwallet/converter/UserWalletItemUMConverter.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/userwallet/converter/UserWalletItemUMConverter.kt @@ -30,6 +30,7 @@ class UserWalletItemUMConverter( private val balance: TotalFiatBalance? = null, private val isLoading: Boolean = true, private val isBalanceHidden: Boolean = false, + private val endIcon: UserWalletItemUM.EndIcon = UserWalletItemUM.EndIcon.None, ) : Converter { override fun convert(value: UserWallet): UserWalletItemUM { @@ -45,6 +46,7 @@ class UserWalletItemUMConverter( ), imageUrl = artworkUrl, isEnabled = !isLocked, + endIcon = endIcon, onClick = { onClick(value.walletId) }, ) } diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetWalletTotalBalanceUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetWalletTotalBalanceUseCase.kt index 0f4d3477da..012dd2847a 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetWalletTotalBalanceUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetWalletTotalBalanceUseCase.kt @@ -29,7 +29,7 @@ class GetWalletTotalBalanceUseCase( private val stakingRepository: StakingRepository, ) { - suspend operator fun invoke( + operator fun invoke( userTallestIds: Collection, ): LceFlow> { val flows = userTallestIds.distinct() @@ -54,7 +54,7 @@ class GetWalletTotalBalanceUseCase( } @OptIn(ExperimentalCoroutinesApi::class) - suspend operator fun invoke(userWalletId: UserWalletId): LceFlow { + operator fun invoke(userWalletId: UserWalletId): LceFlow { val currenciesStatuses = getStatuses(userWalletId) return currenciesStatuses.transformLatest { maybeStatuses -> diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/loader/PortfolioData.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/loader/PortfolioData.kt new file mode 100644 index 0000000000..8ac05a4e90 --- /dev/null +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/loader/PortfolioData.kt @@ -0,0 +1,26 @@ +package com.tangem.features.markets.portfolio.impl.loader + +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.core.lce.Lce +import com.tangem.domain.tokens.error.TokenListError +import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.model.TotalFiatBalance +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId + +/** + * Portfolio data. Combined data from all flows that required to setup portfolio + * + * @property walletsWithCurrencyStatuses wallets with crypto currency statuses + * @property appCurrency app currency + * @property isBalanceHidden flag that indicates if balance should be hidden + * @property walletsWithBalance wallets with total balance + * +[REDACTED_AUTHOR] + */ +internal data class PortfolioData( + val walletsWithCurrencyStatuses: Map>, + val appCurrency: AppCurrency, + val isBalanceHidden: Boolean, + val walletsWithBalance: Map>, +) \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/loader/PortfolioDataLoader.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/loader/PortfolioDataLoader.kt new file mode 100644 index 0000000000..e2e08f4b70 --- /dev/null +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/loader/PortfolioDataLoader.kt @@ -0,0 +1,105 @@ +package com.tangem.features.markets.portfolio.impl.loader + +import arrow.core.getOrElse +import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase +import com.tangem.domain.core.lce.Lce +import com.tangem.domain.tokens.GetAllWalletsCryptoCurrencyStatusesUseCase +import com.tangem.domain.tokens.GetWalletTotalBalanceUseCase +import com.tangem.domain.tokens.error.TokenListError +import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.model.TotalFiatBalance +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.* +import timber.log.Timber +import javax.inject.Inject + +/** + * Loader of portfolio data + * + * @property getAllWalletsCryptoCurrencyStatusesUseCase use case for getting all wallets crypto currency statuses + * @property getSelectedAppCurrencyUseCase use case for getting selected app currency + * @property getBalanceHidingSettingsUseCase use case for getting balance hiding settings + * @property getWalletTotalBalanceUseCase use case for getting wallet total balance + * +[REDACTED_AUTHOR] + */ +internal class PortfolioDataLoader @Inject constructor( + private val getAllWalletsCryptoCurrencyStatusesUseCase: GetAllWalletsCryptoCurrencyStatusesUseCase, + private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, + private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, + private val getWalletTotalBalanceUseCase: GetWalletTotalBalanceUseCase, +) { + + /** Load data by [currencyRawId] */ + @OptIn(ExperimentalCoroutinesApi::class) + fun load(currencyRawId: String): Flow { + return combine( + flow = getAllWalletsCryptoCurrencyStatusesFlow(currencyRawId = currencyRawId), + flow2 = getSelectedAppCurrencyFlow(), + flow3 = getBalanceHidingSettingsFlow(), + ) { walletsWithCurrencyStatuses, appCurrency, isBalanceHidden -> + PortfolioData( + walletsWithCurrencyStatuses = walletsWithCurrencyStatuses, + appCurrency = appCurrency, + isBalanceHidden = isBalanceHidden, + walletsWithBalance = emptyMap(), + ) + } + // setup balances for wallets from walletsWithCurrencyStatuses + .flatMapLatest { portfolioData -> + getWalletsWithTotalBalanceFlow( + ids = portfolioData.walletsWithCurrencyStatuses.keys.map(UserWallet::walletId), + ) + .map { portfolioData.copy(walletsWithBalance = it) } + } + } + + private fun getAllWalletsCryptoCurrencyStatusesFlow( + currencyRawId: String, + ): Flow>> { + return getAllWalletsCryptoCurrencyStatusesUseCase(currencyRawId) + .distinctUntilChanged() + .map { walletsWithMaybeStatuses -> + walletsWithMaybeStatuses.mapValues { entry -> + entry.value.mapNotNull { it.getOrNull() } + } + } + } + + private fun getSelectedAppCurrencyFlow(): Flow { + return getSelectedAppCurrencyUseCase() + .map { + it.getOrElse { e -> + Timber.e("Failed to load app currency: $e") + AppCurrency.Default + } + } + .distinctUntilChanged() + } + + private fun getBalanceHidingSettingsFlow(): Flow { + return getBalanceHidingSettingsUseCase() + .map { it.isBalanceHidden } + .distinctUntilChanged() + } + + private fun getWalletsWithTotalBalanceFlow( + ids: List, + ): Flow>> { + return combine( + flows = ids + .map { userWalletId -> + getWalletTotalBalanceUseCase(userWalletId) + .map { userWalletId to it } + .distinctUntilChanged() + }, + transform = { it.toMap() }, + ) + .distinctUntilChanged() + .onEmpty { ids.associateWith { Lce.Loading(partialContent = null) } } + } +} \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/WalletSelectorBottomSheet.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/WalletSelectorBottomSheet.kt index a9e190928f..22ba89a8f7 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/WalletSelectorBottomSheet.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/WalletSelectorBottomSheet.kt @@ -109,7 +109,6 @@ private fun Preview() { ), ), onBack = {}, - onWalletSelected = {}, ), ), ) @@ -135,7 +134,6 @@ private fun PreviewContent() { ), ), onBack = {}, - onWalletSelected = {}, ), ) } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/state/WalletSelectorBSContentUM.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/state/WalletSelectorBSContentUM.kt index ee727b3608..fddc12c25e 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/state/WalletSelectorBSContentUM.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/state/WalletSelectorBSContentUM.kt @@ -6,6 +6,5 @@ import kotlinx.collections.immutable.ImmutableList internal data class WalletSelectorBSContentUM( val userWallets: ImmutableList, - val onWalletSelected: (UserWalletItemUM) -> Unit, val onBack: () -> Unit, ) : TangemBottomSheetConfigContent \ No newline at end of file