From 0fff8339d4fe71ff592909e0649d8d3ac3fc5989 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 5 Sep 2024 14:15:18 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../model/AddToPortfolioBSContentUMFactory.kt | 3 +- .../impl/model/MarketsPortfolioModel.kt | 26 ++---- .../impl/model/MyPortfolioUMFactory.kt | 10 ++- .../impl/model/PortfolioTokenUMConverter.kt | 1 + .../impl/model/TokenActionsHandler.kt | 14 +++- .../impl/model/TokensPortfolioUMConverter.kt | 83 +++++++++++++++++-- .../preview/PreviewMyPortfolioUMProvider.kt | 2 + .../impl/ui/state/PortfolioTokenUM.kt | 2 + 8 files changed, 106 insertions(+), 35 deletions(-) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/AddToPortfolioBSContentUMFactory.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/AddToPortfolioBSContentUMFactory.kt index 9e95fe3af0..761d567f41 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/AddToPortfolioBSContentUMFactory.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/AddToPortfolioBSContentUMFactory.kt @@ -86,7 +86,8 @@ internal class AddToPortfolioBSContentUMFactory( portfolioData = portfolioData, selectedWalletId = selectedWallet.walletId, ), - isWalletBlockVisible = portfolioData.walletsWithBalance.size > 1, + isWalletBlockVisible = portfolioData.walletsWithCurrencies + .filterKeys(UserWallet::isMultiCurrency).size > 1, ), ) } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt index 6c6f15a0dd..03170e971d 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt @@ -10,7 +10,6 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.card.HasMissedDerivationsUseCase import com.tangem.domain.markets.SaveMarketTokensUseCase import com.tangem.domain.markets.TokenMarketInfo -import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase @@ -19,7 +18,6 @@ import com.tangem.features.markets.portfolio.impl.loader.PortfolioDataLoader import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber @@ -62,7 +60,6 @@ internal class MarketsPortfolioModel @Inject constructor( private val factory = MyPortfolioUMFactory( onAddClick = { onAddToPortfolioBSVisibilityChange(isShow = true) }, - onTokenItemClick = ::onTokenItemClick, addToPortfolioBSContentUMFactory = AddToPortfolioBSContentUMFactory( token = params.token, onAddToPortfolioVisibilityChange = ::onAddToPortfolioBSVisibilityChange, @@ -71,6 +68,7 @@ internal class MarketsPortfolioModel @Inject constructor( onWalletSelect = ::onWalletSelect, onContinueClick = ::onContinueClick, ), + currentState = Provider { _state.value }, tokenActionsHandler = tokenActionsIntentsFactory.create( currentAppCurrency = Provider { currentAppCurrency.value }, updateTokenActionsBSConfig = { updateBlock -> @@ -80,6 +78,11 @@ internal class MarketsPortfolioModel @Inject constructor( updateTokensState { it.copy(tokenReceiveBSConfig = updateBlock(it.tokenReceiveBSConfig)) } }, ), + updateTokens = { updateBlock -> + updateTokensState { state -> + state.copy(tokens = updateBlock(state.tokens)) + } + }, ) init { @@ -150,23 +153,6 @@ internal class MarketsPortfolioModel @Inject constructor( } } - private fun onTokenItemClick(index: Int, id: CryptoCurrency.ID) { - updateTokensState { state -> - state.copy( - tokens = state.tokens - .mapIndexed { i, tokenUM -> - // check by index and id because id can be the same - if (index == i && id.value == tokenUM.tokenItemState.id) { - tokenUM.copy(isQuickActionsShown = !tokenUM.isQuickActionsShown) - } else { - tokenUM.copy(isQuickActionsShown = false) - } - } - .toImmutableList(), - ) - } - } - private fun onNetworkSwitchClick(networkId: String, isChecked: Boolean) { val selectedWalletId = selectedMultiWalletIdFlow.value diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MyPortfolioUMFactory.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MyPortfolioUMFactory.kt index c7e25a4287..e9b8527b12 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MyPortfolioUMFactory.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MyPortfolioUMFactory.kt @@ -2,11 +2,13 @@ package com.tangem.features.markets.portfolio.impl.model import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.domain.markets.TokenMarketInfo -import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.markets.portfolio.impl.loader.PortfolioData import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM +import com.tangem.features.markets.portfolio.impl.ui.state.PortfolioTokenUM +import com.tangem.utils.Provider +import kotlinx.collections.immutable.ImmutableList /** * Factory for creating [MyPortfolioUM] @@ -18,9 +20,10 @@ import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM */ internal class MyPortfolioUMFactory( private val onAddClick: () -> Unit, - private val onTokenItemClick: (Int, CryptoCurrency.ID) -> Unit, private val addToPortfolioBSContentUMFactory: AddToPortfolioBSContentUMFactory, private val tokenActionsHandler: TokenActionsHandler, + private val currentState: Provider, + private val updateTokens: ((ImmutableList) -> ImmutableList) -> Unit, ) { fun create(portfolioData: PortfolioData, portfolioUIData: PortfolioUIData): MyPortfolioUM { @@ -58,8 +61,9 @@ internal class MyPortfolioUMFactory( ), bsConfig = createAddToPortfolioBSConfig(portfolioData = portfolioData, portfolioUIData = portfolioUIData), onAddClick = onAddClick, - onTokenItemClick = onTokenItemClick, quickActionsIntents = tokenActionsHandler, + currentState = currentState, + updateTokens = updateTokens, ) .convert(walletsWithCurrencies) } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/PortfolioTokenUMConverter.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/PortfolioTokenUMConverter.kt index cf437c80c1..218d63c9ae 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/PortfolioTokenUMConverter.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/PortfolioTokenUMConverter.kt @@ -41,6 +41,7 @@ internal class PortfolioTokenUMConverter( return PortfolioTokenUM( tokenItemState = tokenItemStateConverter.convert(value = value.status), + walletId = value.userWallet.walletId, isBalanceHidden = isBalanceHidden, isQuickActionsShown = false, quickActions = quickActions(cryptoData = value), diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt index 8dea5f71b6..b77101acb9 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt @@ -53,6 +53,15 @@ internal class TokenActionsHandler @AssistedInject constructor( } fun onTokenLongClick(cryptoCurrencyData: PortfolioData.CryptoCurrencyData) { + val actions = cryptoCurrencyData.actions + .mapNotNull { it.toAction(cryptoCurrencyData) } + .sortedBy { it.order } + .toImmutableList() + + if (actions.isEmpty()) { + return + } + updateTokenActionsBSConfig { TangemBottomSheetConfig( isShow = true, @@ -63,10 +72,7 @@ internal class TokenActionsHandler @AssistedInject constructor( }, content = TokenActionsBSContentUM( title = cryptoCurrencyData.userWallet.name, - actions = cryptoCurrencyData.actions - .mapNotNull { it.toAction(cryptoCurrencyData) } - .sortedBy { it.order } - .toImmutableList(), + actions = actions, onActionClick = { action -> handle(action, cryptoCurrencyData) updateTokenActionsBSConfig { diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokensPortfolioUMConverter.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokensPortfolioUMConverter.kt index 1614ad4ebb..4dc478786c 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokensPortfolioUMConverter.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokensPortfolioUMConverter.kt @@ -2,13 +2,16 @@ package com.tangem.features.markets.portfolio.impl.model import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.markets.portfolio.impl.loader.PortfolioData import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM.Tokens.AddButtonState +import com.tangem.features.markets.portfolio.impl.ui.state.PortfolioTokenUM +import com.tangem.utils.Provider import com.tangem.utils.converter.Converter +import com.tangem.utils.extensions.isZero +import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList /** @@ -23,28 +26,94 @@ internal class TokensPortfolioUMConverter( private val isAllAvailableNetworksAdded: Boolean, private val bsConfig: TangemBottomSheetConfig, private val onAddClick: () -> Unit, - private val onTokenItemClick: (index: Int, id: CryptoCurrency.ID) -> Unit, private val quickActionsIntents: TokenActionsHandler, + private val currentState: Provider, + private val updateTokens: ((ImmutableList) -> ImmutableList) -> Unit, ) : Converter>, MyPortfolioUM.Tokens> { override fun convert(value: Map>): MyPortfolioUM.Tokens { + val currentTokensState = currentState() as? MyPortfolioUM.Tokens + return MyPortfolioUM.Tokens( tokens = value .flatMap { entry -> entry.value } - .mapIndexed { index, cryptoData -> + .map { cryptoData -> PortfolioTokenUMConverter( appCurrency = appCurrency, isBalanceHidden = isBalanceHidden, - onTokenItemClick = { onTokenItemClick(index, it.currency.id) }, + onTokenItemClick = { toggleQuickActions(cryptoData) }, tokenActionsHandler = quickActionsIntents, - ).convert(cryptoData) + ).convert(value = cryptoData) to cryptoData } + .setQuickActionsVisibility(currentState = currentTokensState) .toImmutableList(), buttonState = if (isAllAvailableNetworksAdded) AddButtonState.Unavailable else AddButtonState.Available, addToPortfolioBSConfig = bsConfig, onAddClick = onAddClick, - tokenReceiveBSConfig = TangemBottomSheetConfig.Empty, - tokenActionsBSConfig = TangemBottomSheetConfig.Empty, + tokenReceiveBSConfig = (currentState() as? MyPortfolioUM.Tokens) + ?.tokenReceiveBSConfig + ?: TangemBottomSheetConfig.Empty, + tokenActionsBSConfig = (currentState() as? MyPortfolioUM.Tokens) + ?.tokenActionsBSConfig + ?: TangemBottomSheetConfig.Empty, ) } + + private fun List>.setQuickActionsVisibility( + currentState: MyPortfolioUM.Tokens?, + ): List { + return when { + // if there is only one token and it has empty balance, show quick actions for it + currentState == null && this.size == 1 && isEmptyBalance(this.first().second) -> { + this.map { (token, _) -> + token.copy(isQuickActionsShown = true) + } + } + // if there is no previous state, hide quick actions for all tokens + currentState == null -> { + this.map { (token, _) -> + token.copy(isQuickActionsShown = false) + } + } + else -> { + val previousList = currentState.tokens + + // otherwise, keep previous state + this.map { (token, _) -> + token.copy( + isQuickActionsShown = previousList + .firstOrNull { it.matchWith(token) } + ?.isQuickActionsShown ?: false, + ) + } + } + } + } + + private fun isEmptyBalance(cryptoData: PortfolioData.CryptoCurrencyData): Boolean { + return cryptoData.status.value.amount?.isZero() ?: false + } + + private fun toggleQuickActions(cryptoData: PortfolioData.CryptoCurrencyData) { + updateTokens { tokenList -> + tokenList.map { + it.copy( + isQuickActionsShown = if (it.matchWith(cryptoData)) { + !it.isQuickActionsShown + } else { + false + }, + ) + }.toImmutableList() + } + } + + private fun PortfolioTokenUM.matchWith(token: PortfolioTokenUM): Boolean { + return this.walletId == token.walletId && this.tokenItemState.id == token.tokenItemState.id + } + + private fun PortfolioTokenUM.matchWith(cryptoData: PortfolioData.CryptoCurrencyData): Boolean { + return this.walletId == cryptoData.userWallet.walletId && + this.tokenItemState.id == cryptoData.status.currency.id.value + } } \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/preview/PreviewMyPortfolioUMProvider.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/preview/PreviewMyPortfolioUMProvider.kt index 247b98ce7d..3d027349ed 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/preview/PreviewMyPortfolioUMProvider.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/preview/PreviewMyPortfolioUMProvider.kt @@ -4,6 +4,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.components.token.state.TokenItemState +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM import com.tangem.features.markets.portfolio.impl.ui.state.PortfolioTokenUM import com.tangem.features.markets.portfolio.impl.ui.state.QuickActionUM @@ -64,5 +65,6 @@ internal class PreviewMyPortfolioUMProvider : PreviewParameterProvider