Updated on 2026-08-14
This commit is contained in:
parent
6ad742d678
commit
9101098d72
6 changed files with 116 additions and 34 deletions
|
|
@ -101,8 +101,9 @@ internal class ChooseTokenListItemConverter(
|
||||||
private fun AccountStatus.CryptoPortfolio.toPortfolioItem(
|
private fun AccountStatus.CryptoPortfolio.toPortfolioItem(
|
||||||
params: TokenConverterParams.Account,
|
params: TokenConverterParams.Account,
|
||||||
): TokensListItemUM.Portfolio {
|
): TokensListItemUM.Portfolio {
|
||||||
val tokenList: TokenList = this.tokenList
|
val displayedStatus = filterForDisplay()
|
||||||
val account: Account.CryptoPortfolio = this.account
|
val account: Account.CryptoPortfolio = displayedStatus.account
|
||||||
|
val displayedTokenList: TokenList = displayedStatus.tokenList
|
||||||
val isExpanded = isSearchingState || params.expandedAccounts.contains(account.accountId)
|
val isExpanded = isSearchingState || params.expandedAccounts.contains(account.accountId)
|
||||||
val onItemClick: (Account.CryptoPortfolio) -> Unit = { clickedAccount ->
|
val onItemClick: (Account.CryptoPortfolio) -> Unit = { clickedAccount ->
|
||||||
onAccountItemClick(clickedAccount, isExpanded)
|
onAccountItemClick(clickedAccount, isExpanded)
|
||||||
|
|
@ -116,10 +117,9 @@ internal class ChooseTokenListItemConverter(
|
||||||
fiatAmountStateProvider = { fiatBalance -> fiatAmountStateProvider(fiatBalance, isExpanded) },
|
fiatAmountStateProvider = { fiatBalance -> fiatAmountStateProvider(fiatBalance, isExpanded) },
|
||||||
subtitle2StateProvider = { _ -> null },
|
subtitle2StateProvider = { _ -> null },
|
||||||
)
|
)
|
||||||
val accountItem = converter.convert(tokenList.totalFiatBalance)
|
val accountItem = converter.convert(displayedTokenList.totalFiatBalance)
|
||||||
val tokenConverter = tokenStatusConverter(this)
|
val items = displayedTokenList.toUmData(tokenStatusConverter(this)).tokensList
|
||||||
val tokensListState = convertTokenList(tokenConverter, tokenList, this)
|
|
||||||
val items = tokensListState.tokensList
|
|
||||||
return TokensListPortfolioItemConverter(
|
return TokensListPortfolioItemConverter(
|
||||||
tokenItemUM = accountItem,
|
tokenItemUM = accountItem,
|
||||||
isExpanded = isExpanded,
|
isExpanded = isExpanded,
|
||||||
|
|
@ -128,22 +128,30 @@ internal class ChooseTokenListItemConverter(
|
||||||
).convert(Unit)
|
).convert(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun AccountStatus.CryptoPortfolio.filterForDisplay(): AccountStatus.CryptoPortfolio {
|
||||||
|
val filteredTokenList = filterTokenList(tokenList, this)
|
||||||
|
return copy(
|
||||||
|
account = account.copy(cryptoCurrencies = filteredTokenList.flattenCurrencies().map { it.currency }),
|
||||||
|
tokenList = filteredTokenList,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun convertTokenList(
|
private fun convertTokenList(
|
||||||
tokenConverter: TokenItemStateConverter,
|
tokenConverter: TokenItemStateConverter,
|
||||||
tokenListParam: TokenList,
|
tokenListParam: TokenList,
|
||||||
account: AccountStatus.CryptoPortfolio,
|
account: AccountStatus.CryptoPortfolio,
|
||||||
): TokenListUMData {
|
): TokenListUMData = filterTokenList(tokenListParam, account).toUmData(tokenConverter)
|
||||||
return when (val tokenList = filterTokenList(tokenListParam, account)) {
|
|
||||||
is TokenList.Empty -> TokenListUMData.EmptyList
|
private fun TokenList.toUmData(tokenConverter: TokenItemStateConverter): TokenListUMData = when (this) {
|
||||||
is TokenList.GroupedByNetwork -> TokenListUMData.TokenList(
|
TokenList.Empty -> TokenListUMData.EmptyList
|
||||||
tokensList = tokenList.toGroupedItems(tokenConverter).toPersistentList(),
|
is TokenList.GroupedByNetwork -> TokenListUMData.TokenList(
|
||||||
totalTokensCount = tokenList.flattenCurrencies().size,
|
tokensList = toGroupedItems(tokenConverter).toPersistentList(),
|
||||||
)
|
totalTokensCount = flattenCurrencies().size,
|
||||||
is TokenList.Ungrouped -> TokenListUMData.TokenList(
|
)
|
||||||
tokensList = tokenList.toUngroupedItems(tokenConverter).toPersistentList(),
|
is TokenList.Ungrouped -> TokenListUMData.TokenList(
|
||||||
totalTokensCount = tokenList.flattenCurrencies().size,
|
tokensList = toUngroupedItems(tokenConverter).toPersistentList(),
|
||||||
)
|
totalTokensCount = flattenCurrencies().size,
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<CryptoCurrencyStatus>.filterCurrencies(account: AccountStatus): List<CryptoCurrencyStatus> =
|
private fun List<CryptoCurrencyStatus>.filterCurrencies(account: AccountStatus): List<CryptoCurrencyStatus> =
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
|
import com.tangem.domain.account.models.AccountStatusList
|
||||||
|
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||||
import com.tangem.features.commonfeatures.api.R
|
import com.tangem.features.commonfeatures.api.R
|
||||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager
|
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager
|
||||||
import com.tangem.features.commonfeatures.api.choosetoken.*
|
import com.tangem.features.commonfeatures.api.choosetoken.*
|
||||||
|
|
@ -20,6 +22,7 @@ import com.tangem.features.commonfeatures.impl.choosetoken.ui.ChooseTokenFullUM
|
||||||
import com.tangem.features.commonfeatures.impl.choosetoken.ui.ChooseTokenInitialUM
|
import com.tangem.features.commonfeatures.impl.choosetoken.ui.ChooseTokenInitialUM
|
||||||
import com.tangem.features.commonfeatures.impl.choosetoken.ui.state.ChooserBlockUM
|
import com.tangem.features.commonfeatures.impl.choosetoken.ui.state.ChooserBlockUM
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -32,6 +35,7 @@ internal class ChooseTokenModel @Inject constructor(
|
||||||
marketBlockDelegateFactory: MarketBlockDelegate.Factory,
|
marketBlockDelegateFactory: MarketBlockDelegate.Factory,
|
||||||
predefinedTokensBlockDelegateFactory: PredefinedTokensBlockDelegate.Factory,
|
predefinedTokensBlockDelegateFactory: PredefinedTokensBlockDelegate.Factory,
|
||||||
addToPortfolioManagerFactory: AddToPortfolioManager.Factory,
|
addToPortfolioManagerFactory: AddToPortfolioManager.Factory,
|
||||||
|
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||||
paramsContainer: ParamsContainer,
|
paramsContainer: ParamsContainer,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
|
|
@ -62,6 +66,13 @@ internal class ChooseTokenModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Tokens the user already holds in the selected wallet — subtracted from the predefined "Other eligible" block. */
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
private val portfolioTokenKeysFlow: Flow<Set<Pair<String, String>>> = bridge.selectedWalletFlow
|
||||||
|
.flatMapLatest { wallet -> singleAccountStatusListSupplier(wallet.walletId) }
|
||||||
|
.map { accountStatusList -> accountStatusList.toTokenKeys() }
|
||||||
|
.onStart { emit(emptySet()) }
|
||||||
|
|
||||||
private val predefinedTokensBlockDelegate: PredefinedTokensBlockDelegate by lazy {
|
private val predefinedTokensBlockDelegate: PredefinedTokensBlockDelegate by lazy {
|
||||||
val block = bridge.settings.chooserBlock as ChooserBlock.Predefined
|
val block = bridge.settings.chooserBlock as ChooserBlock.Predefined
|
||||||
predefinedTokensBlockDelegateFactory.create(
|
predefinedTokensBlockDelegateFactory.create(
|
||||||
|
|
@ -71,6 +82,7 @@ internal class ChooseTokenModel @Inject constructor(
|
||||||
addToPortfolioSlot = bottomSheetNavigation,
|
addToPortfolioSlot = bottomSheetNavigation,
|
||||||
modelScope = modelScope,
|
modelScope = modelScope,
|
||||||
tokenFilter = bridge.tokenFilter,
|
tokenFilter = bridge.tokenFilter,
|
||||||
|
portfolioTokenKeys = portfolioTokenKeysFlow,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,6 +136,12 @@ internal class ChooseTokenModel @Inject constructor(
|
||||||
.launchIn(modelScope)
|
.launchIn(modelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun AccountStatusList.toTokenKeys(): Set<Pair<String, String>> =
|
||||||
|
flattenCurrencies().mapNotNullTo(hashSetOf()) { status ->
|
||||||
|
val rawId = status.currency.id.rawCurrencyId?.value ?: return@mapNotNullTo null
|
||||||
|
rawId to status.currency.network.rawId
|
||||||
|
}
|
||||||
|
|
||||||
fun onBackClicked() {
|
fun onBackClicked() {
|
||||||
bridge.onClose()
|
bridge.onClose()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ internal class PredefinedTokensBlockDelegate @AssistedInject constructor(
|
||||||
@Assisted private val addToPortfolioSlot: SlotNavigation<AddToPortfolioRoute>,
|
@Assisted private val addToPortfolioSlot: SlotNavigation<AddToPortfolioRoute>,
|
||||||
@Assisted private val modelScope: CoroutineScope,
|
@Assisted private val modelScope: CoroutineScope,
|
||||||
@Assisted private val tokenFilter: MutableStateFlow<(AccountStatus, CryptoCurrencyStatus) -> Boolean>,
|
@Assisted private val tokenFilter: MutableStateFlow<(AccountStatus, CryptoCurrencyStatus) -> Boolean>,
|
||||||
|
@Assisted private val portfolioTokenKeys: Flow<Set<Pair<String, String>>>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
@ -44,8 +45,13 @@ internal class PredefinedTokensBlockDelegate @AssistedInject constructor(
|
||||||
val stateFlow: Flow<PredefinedTokensUM?> = combine(
|
val stateFlow: Flow<PredefinedTokensUM?> = combine(
|
||||||
predefinedTokens,
|
predefinedTokens,
|
||||||
searchQueryState,
|
searchQueryState,
|
||||||
) { tokens, query ->
|
portfolioTokenKeys,
|
||||||
val filtered = tokens.filter { it.hasValidNetwork() && it.matchesQuery(query.value) }
|
) { tokens, query, portfolioKeys ->
|
||||||
|
val filtered = tokens.filter { token ->
|
||||||
|
token.hasValidNetwork() &&
|
||||||
|
token.matchesQuery(query.value) &&
|
||||||
|
!portfolioKeys.contains(token.toKey())
|
||||||
|
}
|
||||||
if (filtered.isEmpty()) {
|
if (filtered.isEmpty()) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -66,6 +72,9 @@ internal class PredefinedTokensBlockDelegate @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Identity of a predefined token as `(rawCurrencyId, networkId)` — matches the portfolio token keys. */
|
||||||
|
private fun PredefinedTokenToAdd.toKey(): Pair<String, String> = token.id.value to network.networkId
|
||||||
|
|
||||||
private fun PredefinedTokenToAdd.hasValidNetwork(): Boolean =
|
private fun PredefinedTokenToAdd.hasValidNetwork(): Boolean =
|
||||||
network.networkId.isNotBlank() && network.decimalCount != null
|
network.networkId.isNotBlank() && network.decimalCount != null
|
||||||
|
|
||||||
|
|
@ -104,6 +113,7 @@ internal class PredefinedTokensBlockDelegate @AssistedInject constructor(
|
||||||
addToPortfolioSlot: SlotNavigation<AddToPortfolioRoute>,
|
addToPortfolioSlot: SlotNavigation<AddToPortfolioRoute>,
|
||||||
modelScope: CoroutineScope,
|
modelScope: CoroutineScope,
|
||||||
tokenFilter: MutableStateFlow<(AccountStatus, CryptoCurrencyStatus) -> Boolean>,
|
tokenFilter: MutableStateFlow<(AccountStatus, CryptoCurrencyStatus) -> Boolean>,
|
||||||
|
portfolioTokenKeys: Flow<Set<Pair<String, String>>>,
|
||||||
): PredefinedTokensBlockDelegate
|
): PredefinedTokensBlockDelegate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,6 +125,41 @@ internal class PredefinedTokensBlockDelegateTest {
|
||||||
assertThat(actual).isNull()
|
assertThat(actual).isNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN predefined token already in portfolio WHEN state emitted THEN it is excluded`() = runTest {
|
||||||
|
// Arrange
|
||||||
|
val tokens = listOf(
|
||||||
|
createPredefinedToken(id = "usd-coin", symbol = "USDC", networkId = ETHEREUM_NETWORK_ID),
|
||||||
|
createPredefinedToken(id = "tether", symbol = "USDT", networkId = ETHEREUM_NETWORK_ID),
|
||||||
|
)
|
||||||
|
val delegate = createDelegate(
|
||||||
|
predefinedTokens = MutableStateFlow(tokens),
|
||||||
|
portfolioTokenKeys = MutableStateFlow(setOf("usd-coin" to ETHEREUM_NETWORK_ID)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val actual = lastState(delegate)
|
||||||
|
|
||||||
|
// Assert — usd-coin is already in the portfolio, so only tether stays in "Other eligible tokens"
|
||||||
|
assertThat(actual?.items?.map { it.id }).containsExactly("tether_$ETHEREUM_NETWORK_ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN all predefined tokens already in portfolio WHEN state emitted THEN emits null`() = runTest {
|
||||||
|
// Arrange
|
||||||
|
val token = createPredefinedToken(id = "usd-coin", symbol = "USDC", networkId = ETHEREUM_NETWORK_ID)
|
||||||
|
val delegate = createDelegate(
|
||||||
|
predefinedTokens = MutableStateFlow(listOf(token)),
|
||||||
|
portfolioTokenKeys = MutableStateFlow(setOf("usd-coin" to ETHEREUM_NETWORK_ID)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val actual = lastState(delegate)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertThat(actual).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ProvideTestModels
|
@ProvideTestModels
|
||||||
fun filter(model: FilterModel) = runTest {
|
fun filter(model: FilterModel) = runTest {
|
||||||
|
|
@ -234,6 +269,7 @@ internal class PredefinedTokensBlockDelegateTest {
|
||||||
searchQueryState: MutableStateFlow<SearchQuery> = MutableStateFlow(SearchQuery.Empty),
|
searchQueryState: MutableStateFlow<SearchQuery> = MutableStateFlow(SearchQuery.Empty),
|
||||||
tokenFilter: MutableStateFlow<(AccountStatus, CryptoCurrencyStatus) -> Boolean> =
|
tokenFilter: MutableStateFlow<(AccountStatus, CryptoCurrencyStatus) -> Boolean> =
|
||||||
MutableStateFlow({ _, _ -> true }),
|
MutableStateFlow({ _, _ -> true }),
|
||||||
|
portfolioTokenKeys: MutableStateFlow<Set<Pair<String, String>>> = MutableStateFlow(emptySet()),
|
||||||
): PredefinedTokensBlockDelegate = PredefinedTokensBlockDelegate(
|
): PredefinedTokensBlockDelegate = PredefinedTokensBlockDelegate(
|
||||||
predefinedTokens = predefinedTokens,
|
predefinedTokens = predefinedTokens,
|
||||||
searchQueryState = searchQueryState,
|
searchQueryState = searchQueryState,
|
||||||
|
|
@ -241,6 +277,7 @@ internal class PredefinedTokensBlockDelegateTest {
|
||||||
addToPortfolioSlot = addToPortfolioSlot,
|
addToPortfolioSlot = addToPortfolioSlot,
|
||||||
modelScope = CoroutineScope(backgroundScope.coroutineContext + UnconfinedTestDispatcher(testScheduler)),
|
modelScope = CoroutineScope(backgroundScope.coroutineContext + UnconfinedTestDispatcher(testScheduler)),
|
||||||
tokenFilter = tokenFilter,
|
tokenFilter = tokenFilter,
|
||||||
|
portfolioTokenKeys = portfolioTokenKeys,
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun currency(rawId: String, networkId: String): CryptoCurrencyStatus =
|
private fun currency(rawId: String, networkId: String): CryptoCurrencyStatus =
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,11 @@ import com.tangem.core.decompose.model.ParamsContainer
|
||||||
import com.tangem.core.decompose.ui.UiMessageSender
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
import com.tangem.core.navigation.url.UrlOpener
|
import com.tangem.core.navigation.url.UrlOpener
|
||||||
import com.tangem.core.ui.components.account.AccountIconSize
|
import com.tangem.core.ui.components.account.AccountIconSize
|
||||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
|
||||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.wrappedList
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
import com.tangem.core.ui.message.ToastMessage
|
import com.tangem.core.ui.message.ToastMessage
|
||||||
import com.tangem.domain.account.status.usecase.IsAccountsModeEnabledUseCase
|
import com.tangem.domain.account.supplier.MultiAccountListSupplier
|
||||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.models.account.Account
|
import com.tangem.domain.models.account.Account
|
||||||
|
|
@ -47,6 +46,7 @@ import com.tangem.utils.logging.TangemLogger
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
|
|
@ -61,7 +61,7 @@ internal class ActivateCampaignsModel @Inject constructor(
|
||||||
override val dispatchers: CoroutineDispatcherProvider,
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
chooseTokenBridgeFactory: ChooseTokenBridge.Factory,
|
chooseTokenBridgeFactory: ChooseTokenBridge.Factory,
|
||||||
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
private val multiAccountListSupplier: MultiAccountListSupplier,
|
||||||
private val enrollPromoCampaignUseCase: EnrollPromoCampaignUseCase,
|
private val enrollPromoCampaignUseCase: EnrollPromoCampaignUseCase,
|
||||||
private val urlOpener: UrlOpener,
|
private val urlOpener: UrlOpener,
|
||||||
@GlobalUiMessageSender private val messageSender: UiMessageSender,
|
@GlobalUiMessageSender private val messageSender: UiMessageSender,
|
||||||
|
|
@ -199,22 +199,30 @@ internal class ActivateCampaignsModel @Inject constructor(
|
||||||
urlOpener.openUrl(campaignContent.learnMoreUrl)
|
urlOpener.openUrl(campaignContent.learnMoreUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun hasMultipleCryptoPortfolioAccounts(): Boolean {
|
||||||
|
return multiAccountListSupplier.invoke()
|
||||||
|
.first()
|
||||||
|
.any { accountList ->
|
||||||
|
accountList.accounts.filterIsInstance<Account.CryptoPortfolio>().size > 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun onTokenChosen(result: ChooseTokenResult) {
|
private fun onTokenChosen(result: ChooseTokenResult) {
|
||||||
val selectedToken = result.currency.currency as? CryptoCurrency.Token ?: return
|
val selectedToken = result.currency.currency as? CryptoCurrency.Token ?: return
|
||||||
val networkAddress = result.currency.value.networkAddress ?: return
|
val networkAddress = result.currency.value.networkAddress ?: return
|
||||||
|
|
||||||
modelScope.launch {
|
modelScope.launch {
|
||||||
val selectedAccountUM = if (isAccountsModeEnabledUseCase.invokeSync()) {
|
val selectedAccountUM = if (hasMultipleCryptoPortfolioAccounts()) {
|
||||||
when (val account = result.account.account) {
|
when (val account = result.account.account) {
|
||||||
is Account.CryptoPortfolio -> SelectedAccountUM(
|
is Account.CryptoPortfolio -> SelectedAccountUM(
|
||||||
iconState = accountIconConverter.convert(account),
|
iconState = accountIconConverter.convert(account),
|
||||||
name = account.accountName.toUM().value,
|
name = account.accountName.toUM().value,
|
||||||
)
|
)
|
||||||
is Account.Payment -> SelectedAccountUM(
|
// Payment accounts are hidden in the chooser and don't count towards accounts mode,
|
||||||
iconState = CurrencyIconState.PaymentAccount(size = AccountIconSize.ExtraSmall),
|
// so there is no account label to show for them.
|
||||||
name = account.accountName.toUM().value,
|
is Account.Payment,
|
||||||
)
|
is Account.Virtual,
|
||||||
is Account.Virtual -> null
|
-> null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.core.decompose.model.MutableParamsContainer
|
import com.tangem.core.decompose.model.MutableParamsContainer
|
||||||
import com.tangem.core.decompose.ui.UiMessageSender
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
import com.tangem.core.navigation.url.UrlOpener
|
import com.tangem.core.navigation.url.UrlOpener
|
||||||
import com.tangem.domain.account.status.usecase.IsAccountsModeEnabledUseCase
|
import com.tangem.domain.account.models.AccountList
|
||||||
|
import com.tangem.domain.account.supplier.MultiAccountListSupplier
|
||||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.models.currency.CryptoCurrency
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
|
|
@ -53,7 +54,7 @@ internal class ActivateCampaignsModelTest {
|
||||||
|
|
||||||
private val chooseTokenBridgeFactory: ChooseTokenBridge.Factory = mockk(relaxed = true)
|
private val chooseTokenBridgeFactory: ChooseTokenBridge.Factory = mockk(relaxed = true)
|
||||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase = mockk()
|
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase = mockk()
|
||||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase = mockk()
|
private val multiAccountListSupplier: MultiAccountListSupplier = mockk()
|
||||||
private val enrollPromoCampaignUseCase: EnrollPromoCampaignUseCase = mockk()
|
private val enrollPromoCampaignUseCase: EnrollPromoCampaignUseCase = mockk()
|
||||||
private val urlOpener: UrlOpener = mockk(relaxed = true)
|
private val urlOpener: UrlOpener = mockk(relaxed = true)
|
||||||
private val messageSender: UiMessageSender = mockk(relaxed = true)
|
private val messageSender: UiMessageSender = mockk(relaxed = true)
|
||||||
|
|
@ -72,7 +73,7 @@ internal class ActivateCampaignsModelTest {
|
||||||
fun setup() {
|
fun setup() {
|
||||||
clearMocks(
|
clearMocks(
|
||||||
getSelectedAppCurrencyUseCase,
|
getSelectedAppCurrencyUseCase,
|
||||||
isAccountsModeEnabledUseCase,
|
multiAccountListSupplier,
|
||||||
enrollPromoCampaignUseCase,
|
enrollPromoCampaignUseCase,
|
||||||
getWalletsUseCase,
|
getWalletsUseCase,
|
||||||
messageSender,
|
messageSender,
|
||||||
|
|
@ -258,7 +259,7 @@ internal class ActivateCampaignsModelTest {
|
||||||
}
|
}
|
||||||
every { chooseTokenBridgeFactory.create(any(), any(), any()) } returns bridge
|
every { chooseTokenBridgeFactory.create(any(), any(), any()) } returns bridge
|
||||||
every { getSelectedAppCurrencyUseCase.invokeOrDefault() } returns flowOf(AppCurrency.Default)
|
every { getSelectedAppCurrencyUseCase.invokeOrDefault() } returns flowOf(AppCurrency.Default)
|
||||||
coEvery { isAccountsModeEnabledUseCase.invokeSync() } returns false
|
every { multiAccountListSupplier.invoke() } returns flowOf(emptyList<AccountList>())
|
||||||
coEvery { getPromoCampaignStateUseCase(any(), any(), any()) } returns Either.Left(Throwable())
|
coEvery { getPromoCampaignStateUseCase(any(), any(), any()) } returns Either.Left(Throwable())
|
||||||
every { getWalletsUseCase.invokeSync() } returns allWalletIds.map { walletId ->
|
every { getWalletsUseCase.invokeSync() } returns allWalletIds.map { walletId ->
|
||||||
mockk<UserWallet> { every { this@mockk.walletId } returns walletId }
|
mockk<UserWallet> { every { this@mockk.walletId } returns walletId }
|
||||||
|
|
@ -274,7 +275,7 @@ internal class ActivateCampaignsModelTest {
|
||||||
dispatchers = createTestingCoroutineDispatcherProvider(),
|
dispatchers = createTestingCoroutineDispatcherProvider(),
|
||||||
chooseTokenBridgeFactory = chooseTokenBridgeFactory,
|
chooseTokenBridgeFactory = chooseTokenBridgeFactory,
|
||||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||||
isAccountsModeEnabledUseCase = isAccountsModeEnabledUseCase,
|
multiAccountListSupplier = multiAccountListSupplier,
|
||||||
enrollPromoCampaignUseCase = enrollPromoCampaignUseCase,
|
enrollPromoCampaignUseCase = enrollPromoCampaignUseCase,
|
||||||
urlOpener = urlOpener,
|
urlOpener = urlOpener,
|
||||||
messageSender = messageSender,
|
messageSender = messageSender,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue