From 2166bc48dff07c9e017f84e079fe06c43c7776f3 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 17 Sep 2025 19:52:20 +0500 Subject: [PATCH 1/4] Updated on 2026-08-14 --- .../choosetoken/model/ChooseManagedTokensModel.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt index 3c239162b1..cf0994d420 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt @@ -167,9 +167,7 @@ internal class ChooseManagedTokensModel @Inject constructor( uiState.update { state -> state.copy( readContent = state.readContent.copy( - items = items.filterNot { - it.id.value == params.initialCurrency.id.rawCurrencyId?.value - }.toPersistentList(), + items = items.toPersistentList(), ), ) } From 72135d480fe25ffa218568c020436ee1ed80bd14 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 17 Sep 2025 20:36:48 +0500 Subject: [PATCH 2/4] Updated on 2026-08-14 --- .../model/ChooseManagedTokensModel.kt | 23 +++++++-- .../managetokens/model/ManageTokensModel.kt | 6 ++- .../model/OnboardingManageTokensModel.kt | 1 + .../utils/list/ManageTokensListManager.kt | 49 +++++++++++-------- .../utils/list/ManageTokensUiManager.kt | 3 ++ .../utils/mapper/CurrencyItemMapper.kt | 20 +++++++- .../utils/mapper/CurrencyNetworksMapper.kt | 2 +- 7 files changed, 77 insertions(+), 27 deletions(-) diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt index cf0994d420..561ea9d992 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt @@ -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(), ), ) } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt index 91e1814599..26dac22d14 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt @@ -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, + ) } } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/OnboardingManageTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/OnboardingManageTokensModel.kt index 30f64dad46..6a517b7a29 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/OnboardingManageTokensModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/OnboardingManageTokensModel.kt @@ -76,6 +76,7 @@ internal class OnboardingManageTokensModel @Inject constructor( manageTokensListManager.launchPagination( source = ManageTokensSource.ONBOARDING, userWalletId = params.userWalletId, + isCollapsed = true, ) } } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensListManager.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensListManager.kt index 7664a6ce6e..3832809727 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensListManager.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensListManager.kt @@ -84,28 +84,36 @@ internal class ManageTokensListManager @AssistedInject constructor( .distinctUntilChanged() val uiItems: Flow> = 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>, 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, ) } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUiManager.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUiManager.kt index 8c038934c5..c83c810a11 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUiManager.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUiManager.kt @@ -54,6 +54,7 @@ internal class ManageTokensUiManager( fun createOrUpdateUiBatches( newCurrencyBatches: List>>, canEditItems: Boolean, + isCollapsed: Boolean, ): List>> { 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) diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/mapper/CurrencyItemMapper.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/mapper/CurrencyItemMapper.kt index c16e25cd84..47a6cfe610 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/mapper/CurrencyItemMapper.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/mapper/CurrencyItemMapper.kt @@ -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) }, diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/mapper/CurrencyNetworksMapper.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/mapper/CurrencyNetworksMapper.kt index 225fb0daae..58cea15030 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/mapper/CurrencyNetworksMapper.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/mapper/CurrencyNetworksMapper.kt @@ -46,7 +46,7 @@ internal fun Network.toCurrencyNetworkModel( ) } -private fun SourceNetwork.toCurrencyNetworkModel( +internal fun SourceNetwork.toCurrencyNetworkModel( isSelected: Boolean, isEditable: Boolean, onSelectedStateChange: (SourceNetwork, Boolean) -> Unit, From 5fcea67900ae21b25f67cbc5a76268fbaabed98c Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Sep 2025 14:33:25 +0500 Subject: [PATCH 3/4] Updated on 2026-08-14 --- .../choosetoken/model/ChooseManagedTokensModel.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt index 561ea9d992..3b425f1d64 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/choosetoken/model/ChooseManagedTokensModel.kt @@ -88,7 +88,7 @@ internal class ChooseManagedTokensModel @Inject constructor( modelScope.launch { manageTokensListManager.launchPagination( source = ManageTokensSource.SEND_VIA_SWAP, - userWalletId = null, + userWalletId = params.userWalletId, isCollapsed = false, ) } @@ -163,7 +163,7 @@ internal class ChooseManagedTokensModel @Inject constructor( } } .sample(periodMillis = 1_000) - .onEach { query -> manageTokensListManager.search(userWalletId = null, query = query) } + .onEach { query -> manageTokensListManager.search(userWalletId = params.userWalletId, query = query) } .launchIn(modelScope) } @@ -310,7 +310,7 @@ internal class ChooseManagedTokensModel @Inject constructor( if (state.readContent.isInitialBatchLoading || state.readContent.isNextBatchLoading) return false modelScope.launch { - manageTokensListManager.loadMore(userWalletId = null, query = state.readContent.search.query) + manageTokensListManager.loadMore(userWalletId = params.userWalletId, query = state.readContent.search.query) } return true From f2c749cc991a9c7e2e4b56097654f0c6e393e2f6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Sep 2025 11:03:32 +0000 Subject: [PATCH 4/4] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index a0d40cc249..958e54058c 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,13 +5,13 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.28-1226" +tangemBlockchainSdk = "develop-1230" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.28-563" +tangemCardSdk = "develop-564" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem12" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ -tangemHotSdk = "develop-461" +tangemHotSdk = "develop-528" #tangemHotSdk = "0.0.1" # Keep it! - used for local builds ^