Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-14 15:45:21 +04:00
parent 5f619a56fe
commit 9a0fbcbe1b
22 changed files with 324 additions and 254 deletions

View file

@ -54,9 +54,7 @@ internal class DefaultChooseTokenComponent @AssistedInject constructor(
return addToPortfolioComponentFactory.create(
context = childByContext(componentContext),
params = AddToPortfolioComponent.Params(
addToPortfolioManager = model.addToPortfolioManager!!,
callback = model.addToPortfolioCallback,
shouldSkipTokenActionsScreen = true,
addToPortfolioManager = model.addToPortfolioManager,
),
)
}

View file

@ -80,10 +80,13 @@ internal class ChooseTokenListItemConverter(
clickIntents.onAccountExpandClick(clickedAccount)
}
}
val fiatAmountStateProvider: ((TotalFiatBalance) -> FiatAmountState?) = if (isSearchingState) {
{ _ -> FiatAmountState.Empty }
} else {
{ _ -> FiatAmountState.Icon(R.drawable.ic_chewron_down_20, IconTint.Informative) }
val fiatAmountStateProvider: ((TotalFiatBalance) -> FiatAmountState?) = { totalBalance ->
when {
isSearchingState -> FiatAmountState.Empty
!isExpanded -> FiatAmountState.Icon(R.drawable.ic_chewron_down_20, IconTint.Informative)
else -> AccountCryptoPortfolioItemStateConverter
.createFiatAmountState(totalBalance, appCurrency)
}
}
val converter = AccountCryptoPortfolioItemStateConverter(

View file

@ -10,7 +10,6 @@ import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.account.AccountStatus
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
@ -23,7 +22,6 @@ import com.tangem.feature.swap.converters.TokensDataConverter
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
import com.tangem.feature.swap.models.market.state.SwapMarketState
import com.tangem.feature.swap.presentation.R
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioComponent
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
@ -73,17 +71,6 @@ internal class ChooseTokenModel @Inject constructor(
private val expandedAccountsFlow: MutableStateFlow<Map<AccountId, Boolean>> = MutableStateFlow(emptyMap())
private val onWalletSelected = Channel<UserWalletId>()
// todo swap call new api result
val addToPortfolioCallback = object : AddToPortfolioComponent.Callback {
override fun onDismiss() = marketBlockDelegate.addToPortfolioSlot.dismiss()
override fun onSuccess(addedToken: CryptoCurrency) {
val newToken = addedToken to ChooseTokenAnalyticsPayload.IsSearched(isSearchingState)
bridge.onNewTokenAdded(newToken)
marketBlockDelegate.addToPortfolioSlot.dismiss()
}
}
val stateOld: StateFlow<SwapSelectTokenStateHolder?> = combineUIOld()
private val contentState: StateFlow<ChooseTokenUM?> = combineUI()
@ -103,6 +90,27 @@ internal class ChooseTokenModel @Inject constructor(
initialValue = ChooseTokenFullUM(initialState.value, contentState.value),
)
init {
addToPortfolioManager.onDismiss.receiveAsFlow()
.onEach { marketBlockDelegate.addToPortfolioSlot.dismiss() }
.launchIn(modelScope)
addToPortfolioManager.onSuccessAdded.receiveAsFlow()
.onEach { addedResult ->
val isSearched = ChooseTokenAnalyticsPayload.IsSearched(isSearchingState)
val newToken = addedResult.addedCurrency.currency to isSearched
bridge.onNewTokenAdded(newToken)
val chooseTokenResult = ChooseTokenResult(
currency = addedResult.addedCurrency,
account = addedResult.account,
wallet = addedResult.wallet,
analyticsPayload = setOf(isSearched),
)
bridge.onCurrencyChosen(chooseTokenResult)
marketBlockDelegate.addToPortfolioSlot.dismiss()
}
.launchIn(modelScope)
}
@Suppress("UnusedPrivateMember")
private fun combineUIOld(): StateFlow<SwapSelectTokenStateHolder?> = combine(
flow = bridge.currenciesGroup,

View file

@ -20,14 +20,11 @@ import com.tangem.feature.swap.models.market.state.SwapMarketState
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
@Suppress("LongParameterList")
internal class MarketBlockDelegate @AssistedInject constructor(
@ -40,12 +37,15 @@ internal class MarketBlockDelegate @AssistedInject constructor(
@Assisted private val screensSourcesName: String,
) {
private val addToPortfolioJobHolder = JobHolder()
private val visibleMarketItemIds = MutableStateFlow<List<CryptoCurrency.RawID>>(emptyList())
private val visibleDefaultMarketItemIds = MutableStateFlow<List<CryptoCurrency.RawID>>(emptyList())
val addToPortfolioSlot: SlotNavigation<AddToPortfolioRoute> = SlotNavigation()
var addToPortfolioManager: AddToPortfolioManager? = null
val addToPortfolioManager: AddToPortfolioManager = addToPortfolioManagerFactory.create(
scope = modelScope,
settings = AddToPortfolioManager.Settings.ChooseToken,
analyticsParams = AddToPortfolioManager.AnalyticsParams(source = screensSourcesName),
)
val marketsStateFlow: Flow<SwapMarketState> = searchQueryState
// Switch between default and search market flows
@ -177,45 +177,34 @@ internal class MarketBlockDelegate @AssistedInject constructor(
}
private fun addToPortfolioItem(item: MarketsListItemUM) {
modelScope.launch {
val tokenMarket = defaultMarketsListManager.getTokenMarketById(item.id)
?: searchMarketsListManager.getTokenMarketById(item.id)
?: return@launch
val tokenMarket = defaultMarketsListManager.getTokenMarketById(item.id)
?: searchMarketsListManager.getTokenMarketById(item.id) ?: return
val param = tokenMarket.toSerializableParam()
val hasOnlyHotWallets = getUserWalletsUseCase.invokeSync().all { it is UserWallet.Hot }
val param = tokenMarket.toSerializableParam()
val hasOnlyHotWallets = getUserWalletsUseCase.invokeSync().all { it is UserWallet.Hot }
val networks = tokenMarket.networks?.filter { network ->
BlockchainUtils.isSupportedNetworkId(
networkId = network.networkId,
coinId = tokenMarket.id.value,
contractAddress = network.contractAddress,
excludedBlockchains = excludedBlockchains,
hotExcludedBlockchains = hotWalletExcludedBlockchains,
hasOnlyHotWallets = hasOnlyHotWallets,
)
}?.map { network ->
TokenMarketInfo.Network(
networkId = network.networkId,
isExchangeable = false,
contractAddress = network.contractAddress,
decimalCount = network.decimalCount,
)
}.orEmpty()
val networks = tokenMarket.networks?.filter { network ->
BlockchainUtils.isSupportedNetworkId(
networkId = network.networkId,
coinId = tokenMarket.id.value,
contractAddress = network.contractAddress,
excludedBlockchains = excludedBlockchains,
hotExcludedBlockchains = hotWalletExcludedBlockchains,
hasOnlyHotWallets = hasOnlyHotWallets,
)
}?.map { network ->
TokenMarketInfo.Network(
networkId = network.networkId,
isExchangeable = false,
contractAddress = network.contractAddress,
decimalCount = network.decimalCount,
)
}.orEmpty()
addToPortfolioManager = addToPortfolioManagerFactory
.create(
scope = modelScope,
token = param,
analyticsParams = AddToPortfolioManager.AnalyticsParams(source = screensSourcesName),
).apply {
setTokenNetworks(networks)
}
addToPortfolioManager.setTokenNetworks(networks)
addToPortfolioManager.setTokenParams(param)
addToPortfolioManager?.state
?.firstOrNull { it is AddToPortfolioManager.State.AvailableToAdd }
?.run { addToPortfolioSlot.activate(AddToPortfolioRoute) }
}.saveIn(addToPortfolioJobHolder)
addToPortfolioSlot.activate(AddToPortfolioRoute)
}
@AssistedFactory