Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-17 20:36:48 +05:00
parent 2166bc48df
commit 72135d480f
7 changed files with 77 additions and 27 deletions

View file

@ -25,6 +25,7 @@ import com.tangem.features.managetokens.component.ChooseManagedTokensComponent.S
import com.tangem.features.managetokens.component.ManageTokensSource
import com.tangem.features.managetokens.component.analytics.CommonManageTokensAnalyticEvents
import com.tangem.features.managetokens.entity.item.CurrencyItemUM
import com.tangem.features.managetokens.entity.item.CurrencyItemUM.Basic
import com.tangem.features.managetokens.entity.managetokens.ManageTokensTopBarUM
import com.tangem.features.managetokens.entity.managetokens.ManageTokensUM
import com.tangem.features.managetokens.impl.R
@ -40,7 +41,6 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
import kotlin.collections.isNotEmpty
@Suppress("LongParameterList")
@ModelScoped
@ -86,7 +86,11 @@ internal class ChooseManagedTokensModel @Inject constructor(
observeSearchQueryChanges()
modelScope.launch {
manageTokensListManager.launchPagination(source = ManageTokensSource.SEND_VIA_SWAP, userWalletId = null)
manageTokensListManager.launchPagination(
source = ManageTokensSource.SEND_VIA_SWAP,
userWalletId = null,
isCollapsed = false,
)
}
}
@ -167,7 +171,20 @@ internal class ChooseManagedTokensModel @Inject constructor(
uiState.update { state ->
state.copy(
readContent = state.readContent.copy(
items = items.toPersistentList(),
items = items.filterNot { currency ->
val availableNetworks = (currency as? Basic)?.networks as? Basic.NetworksUM.Expanded
// Check whether currency is initial token
val isToken = currency.id.value == params.initialCurrency.id.rawCurrencyId?.value
// Ensure that initial token network is filtered out and network list is empty
val isEmptyNetworks = availableNetworks?.networks?.filterNot { network ->
network.id == params.initialCurrency.network.id.rawId.value
}.isNullOrEmpty()
// Filter out currency from display
isToken && isEmptyNetworks
}.toPersistentList(),
),
)
}

View file

@ -79,7 +79,11 @@ internal class ManageTokensModel @Inject constructor(
observeSearchQueryChanges()
modelScope.launch {
manageTokensListManager.launchPagination(source = params.source, userWalletId = params.userWalletId)
manageTokensListManager.launchPagination(
source = params.source,
userWalletId = params.userWalletId,
isCollapsed = true,
)
}
}

View file

@ -76,6 +76,7 @@ internal class OnboardingManageTokensModel @Inject constructor(
manageTokensListManager.launchPagination(
source = ManageTokensSource.ONBOARDING,
userWalletId = params.userWalletId,
isCollapsed = true,
)
}
}

View file

@ -84,28 +84,36 @@ internal class ManageTokensListManager @AssistedInject constructor(
.distinctUntilChanged()
val uiItems: Flow<ImmutableList<CurrencyItemUM>> = uiManager.items
suspend fun launchPagination(source: ManageTokensSource, userWalletId: UserWalletId?) = coroutineScope {
scope = this
this@ManageTokensListManager.source = source
/**
* Launch pagination flow to get currencies
*
* @param source screen where manage tokens is used
* @param userWalletId selected user wallet to manage
* @param isCollapsed set initial display state of networks. !!! WARNING !!! Use `false` flag with cation
*/
suspend fun launchPagination(source: ManageTokensSource, userWalletId: UserWalletId?, isCollapsed: Boolean) =
coroutineScope {
scope = this
this@ManageTokensListManager.source = source
val batchFlow = getManagedTokensUseCase(
context = ManageTokensListBatchingContext(
actionsFlow = actionsFlow,
coroutineScope = this,
),
// only for onboarding case, change carefully and check repository implementation
loadUserTokensFromRemote = userWalletId != null && source == ManageTokensSource.ONBOARDING,
)
val batchFlow = getManagedTokensUseCase(
context = ManageTokensListBatchingContext(
actionsFlow = actionsFlow,
coroutineScope = this,
),
// only for onboarding case, change carefully and check repository implementation
loadUserTokensFromRemote = userWalletId != null && source == ManageTokensSource.ONBOARDING,
)
batchFlow.state
.onEach { state -> updateState(state, userWalletId) }
.flowOn(dispatchers.default)
.launchIn(scope = this)
.saveIn(jobHolder)
batchFlow.state
.onEach { state -> updateState(state, userWalletId, isCollapsed) }
.flowOn(dispatchers.default)
.launchIn(scope = this)
.saveIn(jobHolder)
// Initial load
reload(userWalletId)
}
// Initial load
reload(userWalletId)
}
suspend fun reload(userWalletId: UserWalletId?) {
state.value = ManageTokensListState()
@ -139,6 +147,7 @@ internal class ManageTokensListManager @AssistedInject constructor(
private fun updateState(
batchListState: BatchListState<Int, List<ManagedCryptoCurrency>>,
userWalletId: UserWalletId?,
isCollapsed: Boolean,
) {
state.update { state ->
state.copy(
@ -185,7 +194,7 @@ internal class ManageTokensListManager @AssistedInject constructor(
state.copy(
userWalletId = userWalletId,
currencyBatches = newBatches,
uiBatches = uiManager.createOrUpdateUiBatches(newBatches, canEditItems),
uiBatches = uiManager.createOrUpdateUiBatches(newBatches, canEditItems, isCollapsed),
canEditItems = canEditItems,
)
}

View file

@ -54,6 +54,7 @@ internal class ManageTokensUiManager(
fun createOrUpdateUiBatches(
newCurrencyBatches: List<Batch<Int, List<ManagedCryptoCurrency>>>,
canEditItems: Boolean,
isCollapsed: Boolean,
): List<Batch<Int, List<CurrencyItemUM>>> {
val currentUiBatches = state.value.uiBatches
val batches = currentUiBatches.toMutableList()
@ -70,6 +71,7 @@ internal class ManageTokensUiManager(
isEditable = canEditItems,
onRemoveCustomCurrencyClick = ::removeCustomCurrency,
onTokenClick = actions::onTokenClick,
isCollapsed = isCollapsed,
)
},
)
@ -94,6 +96,7 @@ internal class ManageTokensUiManager(
isEditable = canEditItems,
onRemoveCustomCurrencyClick = ::removeCustomCurrency,
onTokenClick = actions::onTokenClick,
isCollapsed = isCollapsed,
)
} else {
previousUiItem.update(item)

View file

@ -8,14 +8,16 @@ import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
import com.tangem.features.managetokens.entity.item.CurrencyItemUM
import com.tangem.features.managetokens.entity.item.CurrencyItemUM.Basic.NetworksUM
import com.tangem.features.managetokens.utils.ui.getIconRes
import kotlinx.collections.immutable.toImmutableList
internal fun ManagedCryptoCurrency.toUiModel(
isEditable: Boolean,
onTokenClick: (ManagedCryptoCurrency.Token) -> Unit,
onRemoveCustomCurrencyClick: (ManagedCryptoCurrency.Custom) -> Unit,
isCollapsed: Boolean,
): CurrencyItemUM = when (this) {
is ManagedCryptoCurrency.Custom -> toUiModel(onRemoveCustomCurrencyClick)
is ManagedCryptoCurrency.Token -> toUiModel(isEditable, onTokenClick)
is ManagedCryptoCurrency.Token -> toUiModel(isEditable, onTokenClick, isCollapsed)
}
private fun ManagedCryptoCurrency.Custom.toUiModel(
@ -54,6 +56,7 @@ private fun ManagedCryptoCurrency.Custom.toUiModel(
private fun ManagedCryptoCurrency.Token.toUiModel(
isEditable: Boolean,
onTokenClick: (ManagedCryptoCurrency.Token) -> Unit,
isCollapsed: Boolean,
): CurrencyItemUM {
val background = TangemColorPalette.Black
@ -69,7 +72,20 @@ private fun ManagedCryptoCurrency.Token.toUiModel(
fallbackTint = getTintForTokenIcon(background),
fallbackBackground = background,
),
networks = NetworksUM.Collapsed,
networks = if (isCollapsed) {
NetworksUM.Collapsed
} else {
NetworksUM.Expanded(
availableNetworks.map {
it.toCurrencyNetworkModel(
isSelected = it.network in addedIn,
isEditable = false,
onSelectedStateChange = { _, _ -> },
onLongTap = { _ -> },
)
}.toImmutableList(),
)
},
onExpandClick = {
onTokenClick(this)
},

View file

@ -46,7 +46,7 @@ internal fun Network.toCurrencyNetworkModel(
)
}
private fun SourceNetwork.toCurrencyNetworkModel(
internal fun SourceNetwork.toCurrencyNetworkModel(
isSelected: Boolean,
isEditable: Boolean,
onSelectedStateChange: (SourceNetwork, Boolean) -> Unit,