Updated on 2026-08-14

This commit is contained in:
Tangem 2024-11-10 16:41:05 +04:00
parent 81b2f9e4a3
commit 71a9252de8
28 changed files with 193 additions and 70 deletions

View file

@ -5,6 +5,7 @@ import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIco
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.components.marketprice.utils.PriceChangeConverter
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.format.bigdecimal.percent
@ -126,7 +127,7 @@ class TokenItemStateConverter(
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
-> {
TokenItemState.TitleState.Content(text = currencyStatus.currency.name)
TokenItemState.TitleState.Content(text = stringReference(currencyStatus.currency.name))
}
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Custom,
@ -134,7 +135,7 @@ class TokenItemStateConverter(
is CryptoCurrencyStatus.NoAccount,
-> {
TokenItemState.TitleState.Content(
text = currencyStatus.currency.name,
text = stringReference(currencyStatus.currency.name),
hasPending = value.hasCurrentNetworkTransactions,
)
}

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="action_buttons_swap_choose_token">Wähle den Token</string>
<string name="action_buttons_you_want_to_receive">Du möchtest erhalten</string>
<string name="action_buttons_you_want_to_swap">Du möchtest tauschen</string>
<string name="add_custom_token_choose_network">Netzwerk wählen</string>
<string name="add_custom_token_title">Token anlegen</string>
<string name="add_tokens_title">Token verwalten</string>
@ -852,6 +855,9 @@
<string name="token_swap_changelly_promotion_message">Tausche diesen Token gegen einen anderen zu %1$s Servicegebühren von Februar %2$s-%3$s.</string>
<string name="token_swap_changelly_promotion_title">Tausche mit Changelly, %s Gebühren</string>
<string name="token_swap_promotion_button">Jetzt tauschen</string>
<string name="tokens_list_unavailable_to_purchase_header">Nicht verfügbar zum Kauf</string>
<string name="tokens_list_unavailable_to_sell_header">Nicht zum Verkauf verfügbar</string>
<string name="tokens_list_unavailable_to_swap_header">Nicht verfügbar für Tausch von %s</string>
<string name="transaction_history_contract_address">Vertrag: %s</string>
<string name="transaction_history_empty_transactions">Du hast noch keine Transaktionen</string>
<string name="transaction_history_error_failed_to_load">Der Transaktionsverlauf konnte nicht geladen werden.\nKlicke auf die Schaltfläche Neu laden, um die Informationen zu aktualisieren.</string>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="action_buttons_swap_choose_token">Elige el token</string>
<string name="action_buttons_you_want_to_receive">Desea recibir</string>
<string name="action_buttons_you_want_to_swap">Quiere intercambiar</string>
<string name="add_custom_token_choose_network">Elige red</string>
<string name="add_custom_token_title">Agregue un token personalizado</string>
<string name="add_tokens_title">Gestionar tokens</string>
@ -847,6 +850,9 @@
<string name="token_swap_changelly_promotion_message">Cambie este token por otro por una tarifa de servicio de %1$s del %2$s al %3$s de febrero.</string>
<string name="token_swap_changelly_promotion_title">Intercambio con Changelly, %s tarifa</string>
<string name="token_swap_promotion_button">Intercambie ahora</string>
<string name="tokens_list_unavailable_to_purchase_header">No disponible para compra</string>
<string name="tokens_list_unavailable_to_sell_header">No disponible para vender</string>
<string name="tokens_list_unavailable_to_swap_header">No disponible para cambio desde %s</string>
<string name="transaction_history_contract_address">contacto: %s</string>
<string name="transaction_history_empty_transactions">Aún no tiene ninguna transacción</string>
<string name="transaction_history_error_failed_to_load">Error al cargar el historial de transacciones.\nHaga clic en el botón de recarga para actualizar la información.</string>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="action_buttons_swap_choose_token">Choisissez le jeton</string>
<string name="action_buttons_you_want_to_receive">Vous souhaitez recevoir</string>
<string name="action_buttons_you_want_to_swap">Vous souhaitez échanger</string>
<string name="add_custom_token_choose_network">Choisissez le réseau</string>
<string name="add_custom_token_title">Ajouter un jeton personnalisé</string>
<string name="add_tokens_title">Gérer les jetons</string>
@ -847,6 +850,9 @@
<string name="token_swap_changelly_promotion_message">Échangez ce jeton contre un autre moyennant des frais de service de %1$s du %2$s au %3$s février.</string>
<string name="token_swap_changelly_promotion_title">Échangez avec Changelly, %s frais</string>
<string name="token_swap_promotion_button">Échangez maintenant</string>
<string name="tokens_list_unavailable_to_purchase_header">Non disponible à l\'achat</string>
<string name="tokens_list_unavailable_to_sell_header">Indisponible à la vente</string>
<string name="tokens_list_unavailable_to_swap_header">Non disponible pour l\'échange de %s</string>
<string name="transaction_history_contract_address">contrat : %s</string>
<string name="transaction_history_empty_transactions">Vous n\'avez pas encore de transactions</string>
<string name="transaction_history_error_failed_to_load">Échec du chargement de l\'historique des transactions.\nCliquez sur le bouton de rechargement pour mettre à jour les informations.</string>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="action_buttons_swap_choose_token">トークンを選択</string>
<string name="action_buttons_you_want_to_receive">受け取りたい</string>
<string name="action_buttons_you_want_to_swap">交換したい</string>
<string name="add_custom_token_choose_network">ネットワークを選択</string>
<string name="add_custom_token_title">カスタムトークンの追加</string>
<string name="add_tokens_title">トークンの管理</string>
@ -842,6 +845,9 @@
<string name="token_swap_changelly_promotion_message">このトークンは、2月%2$s-%3$s の間、%1$s のサービス手数料で別のトークンと交換できます。</string>
<string name="token_swap_changelly_promotion_title">Changellyでスワップ、手数料%s</string>
<string name="token_swap_promotion_button">今すぐスワップ</string>
<string name="tokens_list_unavailable_to_purchase_header">買付できません</string>
<string name="tokens_list_unavailable_to_sell_header">売却できません</string>
<string name="tokens_list_unavailable_to_swap_header">%sからのスワップは利用できません</string>
<string name="transaction_history_contract_address">コントラクト: %s</string>
<string name="transaction_history_empty_transactions">まだ取引はありません</string>
<string name="transaction_history_error_failed_to_load">取引履歴の読み込みに失敗しました。\n情報を更新するには、リロードボタンをクリックしてください。</string>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="action_buttons_swap_choose_token">Выберите токен</string>
<string name="action_buttons_you_want_to_receive">Вы хотите получить</string>
<string name="action_buttons_you_want_to_swap">Вы хотите обменять</string>
<string name="add_custom_token_choose_network">Выберите сеть</string>
<string name="add_custom_token_title">Добавить токен</string>
<string name="add_tokens_title">Валюты</string>
@ -867,6 +870,8 @@
<string name="token_swap_changelly_promotion_message">Обменивайте этот токен на другие с %1$s комиссии за обслуживание с %2$s по %3$s февраля.</string>
<string name="token_swap_changelly_promotion_title">Обмен с Changelly, %s комиссии</string>
<string name="token_swap_promotion_button">Обменять</string>
<string name="tokens_list_unavailable_to_purchase_header">Недоступно для покупки</string>
<string name="tokens_list_unavailable_to_sell_header">Недоступно для продажи</string>
<string name="transaction_history_contract_address">контракт: %s</string>
<string name="transaction_history_empty_transactions">У вас еще нет транзакций</string>
<string name="transaction_history_error_failed_to_load">Не удалось загрузить историю транзакций.\nНажмите на кнопку перезагрузки, чтобы обновить информацию.</string>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="action_buttons_swap_choose_token">Оберіть токен</string>
<string name="action_buttons_you_want_to_receive">Ви хочете отримати</string>
<string name="action_buttons_you_want_to_swap">Ви хочете обміняти</string>
<string name="add_custom_token_choose_network">Оберіть мережу</string>
<string name="add_custom_token_title">Додати токен</string>
<string name="add_tokens_title">Токени</string>
@ -866,6 +869,9 @@
<string name="token_swap_changelly_promotion_message">Обмінюйте цей токен на інші з %1$s комісією за обслуговування з %2$s по %3$s лютого.</string>
<string name="token_swap_changelly_promotion_title">Обмін із Changelly, %s комісії</string>
<string name="token_swap_promotion_button">Обміняти</string>
<string name="tokens_list_unavailable_to_purchase_header">Недоступно для покупки</string>
<string name="tokens_list_unavailable_to_sell_header">Недоступно для продажу</string>
<string name="tokens_list_unavailable_to_swap_header">Недоступно для обміну з %s</string>
<string name="transaction_history_contract_address">контракт: %s</string>
<string name="transaction_history_empty_transactions">У вас ще немає транзакцій</string>
<string name="transaction_history_error_failed_to_load">Не вдалося завантажити історію транзакцій.\nНатисніть кнопку нижче, щоб оновити інформацію</string>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="action_buttons_swap_choose_token">Choose the Token</string>
<string name="action_buttons_you_want_to_receive">You want to Receive</string>
<string name="action_buttons_you_want_to_swap">You want to Swap</string>
<string name="add_custom_token_choose_network">Choose network</string>
<string name="add_custom_token_title">Add custom token</string>
<string name="add_tokens_title">Manage tokens</string>
@ -860,6 +863,9 @@
<string name="token_swap_changelly_promotion_message">Exchange this token for another at %1$s service fees from February %2$s-%3$s.</string>
<string name="token_swap_changelly_promotion_title">Swap with Changelly, %s fees</string>
<string name="token_swap_promotion_button">Swap now</string>
<string name="tokens_list_unavailable_to_purchase_header">Unavailable to purchase</string>
<string name="tokens_list_unavailable_to_sell_header">Unavailable to sell</string>
<string name="tokens_list_unavailable_to_swap_header">Unavailable for swap from %s</string>
<string name="transaction_history_contract_address">contract: %s</string>
<string name="transaction_history_empty_transactions">You don\'t have any transactions yet</string>
<string name="transaction_history_error_failed_to_load">Failed to load transaction history.\nClick on reload button to update the information.</string>

View file

@ -25,6 +25,7 @@ import com.tangem.core.ui.components.token.internal.*
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.rememberHapticFeedback
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -458,7 +459,7 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
tokenItemVisibleState.copy(
iconState = coinIconState.copy(showCustomBadge = true),
titleState = TokenItemState.TitleState.Content(
text = "PolygonPolygonPolygonPolygonPolygonPolygon",
text = stringReference(value = "PolygonPolygonPolygonPolygonPolygonPolygon"),
hasPending = true,
),
fiatAmountState = TokenItemState.FiatAmountState.Content(
@ -475,41 +476,41 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
TokenItemState.Unreachable(
id = UUID.randomUUID().toString(),
iconState = tokenIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
onItemClick = {},
onItemLongClick = {},
),
TokenItemState.Unreachable(
id = UUID.randomUUID().toString(),
iconState = tokenIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
subtitleState = TokenItemState.SubtitleState.TextContent("Token"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
subtitleState = TokenItemState.SubtitleState.TextContent(stringReference(value = "Token")),
onItemClick = {},
onItemLongClick = {},
),
TokenItemState.NoAddress(
id = UUID.randomUUID().toString(),
iconState = tokenIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
onItemLongClick = {},
),
TokenItemState.NoAddress(
id = UUID.randomUUID().toString(),
iconState = tokenIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
subtitleState = TokenItemState.SubtitleState.TextContent("Token"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
subtitleState = TokenItemState.SubtitleState.TextContent(value = stringReference(value = "Token")),
onItemLongClick = {},
),
TokenItemState.Draggable(
id = UUID.randomUUID().toString(),
iconState = tokenIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "3 172,14 $"),
),
TokenItemState.Content(
id = UUID.randomUUID().toString(),
iconState = tokenIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = false),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "5,412 MATIC"),
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(
@ -523,7 +524,7 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
TokenItemState.Content(
id = UUID.randomUUID().toString(),
iconState = tokenIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = false),
subtitle2State = TokenItemState.Subtitle2State.LabelContent(
auditLabelUM = AuditLabelUM(
@ -542,21 +543,21 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
TokenItemState.Loading(
id = "Loading#1",
iconState = customTokenIconState.copy(isGrayscale = true),
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
),
tokenItemVisibleState.copy(
titleState = TokenItemState.TitleState.Content(text = "Polygon testnet"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon testnet")),
iconState = tokenIconState.copy(isGrayscale = true),
),
tokenItemVisibleState.copy(
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
iconState = customTokenIconState.copy(
tint = TangemColorPalette.White,
background = TangemColorPalette.Black,
),
),
tokenItemVisibleState.copy(
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
iconState = customTokenIconState.copy(isGrayscale = true),
),
),
@ -594,7 +595,10 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
TokenItemState.Content(
id = UUID.randomUUID().toString(),
iconState = coinIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon", hasPending = true),
titleState = TokenItemState.TitleState.Content(
text = stringReference(value = "Polygon"),
hasPending = true,
),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = true),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "5,412 MATIC"),
subtitleState = TokenItemState.SubtitleState.Unknown,

View file

@ -21,6 +21,8 @@ import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.SpacerW4
import com.tangem.core.ui.components.SpacerW6
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.utils.StringsSigns.DASH_SIGN
@ -38,7 +40,7 @@ internal fun TokenPrice(state: TokenPriceState?, modifier: Modifier = Modifier)
)
}
is TokenPriceState.TextContent -> {
PriceText(text = state.value, modifier = modifier, isAvailable = state.isAvailable)
PriceText(text = state.value.resolveReference(), modifier = modifier, isAvailable = state.isAvailable)
}
is TokenPriceState.Unknown -> {
PriceText(text = DASH_SIGN, modifier = modifier)
@ -158,7 +160,7 @@ private class TokenPriceChangeStateProvider : CollectionPreviewParameterProvider
priceChangePercent = "2.5%",
type = PriceChangeType.NEUTRAL,
),
TokenPriceState.TextContent(value = "Subtitle", isAvailable = true),
TokenPriceState.TextContent(value = stringReference(value = "Subtitle"), isAvailable = true),
TokenPriceState.Unknown,
TokenPriceState.Loading,
TokenPriceState.Locked,

View file

@ -15,6 +15,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import com.tangem.core.ui.R
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.components.token.state.TokenItemState.TitleState as TokenTitleState
@ -46,7 +47,7 @@ private fun ContentTitle(state: TokenTitleState.Content, modifier: Modifier = Mo
* So we need to use [weight] to avoid displacement.
*/
CurrencyNameText(
name = state.text,
name = state.text.resolveReference(),
isAvailable = state.isAvailable,
modifier = Modifier.weight(weight = 1f, fill = false),
)

View file

@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.audits.AuditLabelUM
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.extensions.TextReference
/** TokenItem component state */
@Immutable
@ -161,7 +162,7 @@ sealed class TokenItemState {
sealed class TitleState {
data class Content(
val text: String,
val text: TextReference,
val hasPending: Boolean = false,
val isAvailable: Boolean = true,
) : TitleState()
@ -180,7 +181,7 @@ sealed class TokenItemState {
val type: PriceChangeType,
) : SubtitleState()
data class TextContent(val value: String, val isAvailable: Boolean = true) : SubtitleState()
data class TextContent(val value: TextReference, val isAvailable: Boolean = true) : SubtitleState()
data object Unknown : SubtitleState()

View file

@ -4,6 +4,7 @@ import com.tangem.core.ui.components.audits.AuditLabelUM
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.markets.TokenMarketExchange
import com.tangem.domain.markets.TokenMarketExchange.TrustScore
@ -26,7 +27,7 @@ internal object ExchangeItemStateConverter : Converter<TokenMarketExchange, Toke
isGrayscale = false,
showCustomBadge = false,
),
titleState = TokenItemState.TitleState.Content(text = value.name),
titleState = TokenItemState.TitleState.Content(text = stringReference(value.name)),
fiatAmountState = TokenItemState.FiatAmountState.Content(
text = BigDecimalFormatter.formatFiatPriceUncapped(
fiatAmount = value.volumeInUsd,
@ -35,7 +36,7 @@ internal object ExchangeItemStateConverter : Converter<TokenMarketExchange, Toke
),
),
subtitleState = TokenItemState.SubtitleState.TextContent(
value = if (value.isCentralized) "CEX" else "DEX",
value = stringReference(value = if (value.isCentralized) "CEX" else "DEX"),
),
subtitle2State = TokenItemState.Subtitle2State.LabelContent(
auditLabelUM = value.trustScore.toAuditLabelUM(),

View file

@ -176,9 +176,9 @@ private class ExchangesBottomSheetContentProvider : CollectionPreviewParameterPr
isGrayscale = false,
showCustomBadge = false,
),
titleState = TokenItemState.TitleState.Content(text = "OKX"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "OKX")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "$67.52M"),
subtitleState = TokenItemState.SubtitleState.TextContent(value = "CEX"),
subtitleState = TokenItemState.SubtitleState.TextContent(value = stringReference(value = "CEX")),
subtitle2State = TokenItemState.Subtitle2State.LabelContent(
auditLabelUM = AuditLabelUM(
text = stringReference("Caution"),

View file

@ -2,6 +2,7 @@ package com.tangem.features.markets.portfolio.impl.model
import com.tangem.common.ui.tokens.TokenItemStateConverter
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason
@ -29,9 +30,9 @@ internal class PortfolioTokenUMConverter(
override fun convert(value: PortfolioData.CryptoCurrencyData): PortfolioTokenUM {
val tokenItemStateConverter = TokenItemStateConverter(
appCurrency = appCurrency,
titleStateProvider = { TokenItemState.TitleState.Content(text = value.userWallet.name) },
titleStateProvider = { TokenItemState.TitleState.Content(text = stringReference(value.userWallet.name)) },
subtitleStateProvider = {
TokenItemState.SubtitleState.TextContent(value = value.status.currency.name)
TokenItemState.SubtitleState.TextContent(value = stringReference(value.status.currency.name))
},
onItemClick = { _, status -> onTokenItemClick(status) },
)

View file

@ -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.core.ui.extensions.stringReference
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
@ -49,10 +50,12 @@ internal class PreviewMyPortfolioUMProvider : PreviewParameterProvider<MyPortfol
tokenItemState = TokenItemState.Content(
id = "",
iconState = CurrencyIconState.Locked,
titleState = TokenItemState.TitleState.Content(text = "My wallet"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "My wallet")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "486,65 \$"),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "733,71097 MATIC"),
subtitleState = TokenItemState.SubtitleState.TextContent(value = "XRP Ledger token"),
subtitleState = TokenItemState.SubtitleState.TextContent(
value = stringReference(value = "XRP Ledger token"),
),
onItemClick = {},
onItemLongClick = {},
),

View file

@ -3,7 +3,9 @@ package com.tangem.features.onramp.swap.availablepairs.model
import arrow.core.getOrElse
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.ui.extensions.capitalize
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
@ -27,7 +29,6 @@ import com.tangem.features.onramp.utils.UpdateSearchQueryTransformer
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@Suppress("LongParameterList")
@ -67,28 +68,32 @@ internal class AvailableSwapPairsModel @Inject constructor(
private fun subscribeOnUpdateState() {
combine(
flow = tokenListFlow,
flow2 = getSelectedAppCurrencyUseCase().map { it.getOrElse { AppCurrency.Default } }.distinctUntilChanged(),
flow3 = getBalanceHidingSettingsUseCase().map { it.isBalanceHidden }.distinctUntilChanged(),
flow2 = getAppCurrencyAndBalanceHidingFlow(),
flow3 = params.selectedStatus,
flow4 = searchManager.query,
flow5 = availablePairsByNetworkFlow
.map { it[params.selectedStatus.value?.toLeastTokenInfo()].orEmpty() }
.distinctUntilChanged(),
) { currencies, appCurrency, isBalanceHidden, query, availablePairs ->
) { currencies, appCurrencyAndBalanceHiding, selectedStatus, query, availablePairs ->
if (availablePairs.isEmpty()) {
SetLoadingTokenItemsTransformer(currencies)
} else {
val (appCurrency, isBalanceHidden) = appCurrencyAndBalanceHiding
val filterTokenList = currencies
.filterByQuery(query = query)
.filterByAvailability(availablePairs = availablePairs)
Timber.e("${filterTokenList[true].orEmpty().size}")
UpdateTokenItemsTransformer(
appCurrency = appCurrency,
onItemClick = params.onTokenClick,
statuses = filterTokenList,
isBalanceHidden = isBalanceHidden,
hasSearchBar = currencies.isNotEmpty(),
unavailableTokensHeaderReference = resourceReference(
id = R.string.tokens_list_unavailable_to_swap_header,
wrappedList(selectedStatus?.currency?.name?.capitalize() ?: ""),
),
onQueryChange = ::onSearchQueryChange,
onActiveChange = ::onSearchBarActiveChange,
)
@ -115,8 +120,6 @@ internal class AvailableSwapPairsModel @Inject constructor(
currencies = tokenList.map(CryptoCurrencyStatus::currency),
)
Timber.e("$initialCurrency = ${pairs.size}")
availablePairsByNetworkFlow.update {
it.toMutableMap().apply {
put(initialCurrency, pairs)
@ -126,6 +129,14 @@ internal class AvailableSwapPairsModel @Inject constructor(
}
}
private fun getAppCurrencyAndBalanceHidingFlow(): Flow<Pair<AppCurrency, Boolean>> {
return combine(
flow = getSelectedAppCurrencyUseCase().map { it.getOrElse { AppCurrency.Default } }.distinctUntilChanged(),
flow2 = getBalanceHidingSettingsUseCase().map { it.isBalanceHidden }.distinctUntilChanged(),
transform = ::Pair,
)
}
private fun onSearchQueryChange(newQuery: String) {
val searchBar = tokenListUMController.getSearchBar()
if (searchBar?.searchBarUM?.query == newQuery) return

View file

@ -3,6 +3,7 @@ package com.tangem.features.onramp.swap.entity
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.features.onramp.impl.R
/**
@ -24,18 +25,23 @@ internal sealed interface ExchangeCardUM {
/**
* Empty state
*
* @property titleReference title reference
* @property titleReference title reference
* @property subtitleReference empty token subtitle reference
*/
data class Empty(override val titleReference: TextReference) : ExchangeCardUM {
data class Empty(
override val titleReference: TextReference,
val subtitleReference: TextReference,
) : ExchangeCardUM {
override val removeButtonUM: RemoveButtonUM? = null
// TODO: [REDACTED_JIRA]
override val tokenItemState: TokenItemState = TokenItemState.Content(
id = "empty",
iconState = CurrencyIconState.Empty(R.drawable.ic_empty_64),
titleState = TokenItemState.TitleState.Content(text = "Choose the Token"),
subtitleState = TokenItemState.SubtitleState.TextContent(value = "You want to Swap"),
titleState = TokenItemState.TitleState.Content(
text = resourceReference(id = R.string.action_buttons_swap_choose_token),
),
subtitleState = TokenItemState.SubtitleState.TextContent(value = subtitleReference),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = ""),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = ""),
onItemClick = null,

View file

@ -1,8 +1,8 @@
package com.tangem.features.onramp.swap.entity
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.swap.entity.utils.createEmptyExchangeFrom
import com.tangem.features.onramp.swap.entity.utils.createEmptyExchangeTo
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
@ -25,8 +25,8 @@ internal class SwapSelectTokensController @Inject constructor(
private val _state: MutableStateFlow<SwapSelectTokensUM> = MutableStateFlow(
value = SwapSelectTokensUM(
onBackClick = router::pop,
exchangeFrom = ExchangeCardUM.Empty(titleReference = resourceReference(id = R.string.swapping_from_title)),
exchangeTo = ExchangeCardUM.Empty(titleReference = resourceReference(id = R.string.swapping_to_title)),
exchangeFrom = createEmptyExchangeFrom(),
exchangeTo = createEmptyExchangeTo(),
),
)

View file

@ -1,8 +1,9 @@
package com.tangem.features.onramp.swap.entity.transformer
import com.tangem.features.onramp.swap.entity.ExchangeCardUM
import com.tangem.features.onramp.swap.entity.SwapSelectTokensUM
import com.tangem.features.onramp.swap.entity.SwapSelectTokensUMTransformer
import com.tangem.features.onramp.swap.entity.utils.createEmptyExchangeFrom
import com.tangem.features.onramp.swap.entity.utils.createEmptyExchangeTo
/**
* Transformer for removing selected "from" token
@ -13,8 +14,8 @@ internal object RemoveSelectedFromTokenTransformer : SwapSelectTokensUMTransform
override fun transform(prevState: SwapSelectTokensUM): SwapSelectTokensUM {
return prevState.copy(
exchangeFrom = ExchangeCardUM.Empty(titleReference = prevState.exchangeFrom.titleReference),
exchangeTo = ExchangeCardUM.Empty(titleReference = prevState.exchangeTo.titleReference),
exchangeFrom = createEmptyExchangeFrom(),
exchangeTo = createEmptyExchangeTo(),
)
}
}

View file

@ -1,8 +1,26 @@
package com.tangem.features.onramp.swap.entity.utils
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.swap.entity.ExchangeCardUM
/** Create empty exchange "from" card */
internal fun createEmptyExchangeFrom(): ExchangeCardUM.Empty {
return ExchangeCardUM.Empty(
titleReference = resourceReference(id = R.string.swapping_from_title),
subtitleReference = resourceReference(id = R.string.action_buttons_you_want_to_swap),
)
}
/** Create empty exchange "to" card */
internal fun createEmptyExchangeTo(): ExchangeCardUM.Empty {
return ExchangeCardUM.Empty(
titleReference = resourceReference(id = R.string.swapping_to_title),
subtitleReference = resourceReference(id = R.string.action_buttons_you_want_to_receive),
)
}
/**
* Convert from [ExchangeCardUM] to [ExchangeCardUM.Filled]
*

View file

@ -26,6 +26,7 @@ import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.onramp.impl.R
@ -112,7 +113,10 @@ private fun Preview_ExchangeCard(@PreviewParameter(ExchangeCardUMProvider::class
private class ExchangeCardUMProvider : PreviewParameterProvider<ExchangeCardUM> {
override val values: Sequence<ExchangeCardUM> = sequenceOf(
ExchangeCardUM.Empty(titleReference = resourceReference(id = R.string.swapping_from_title)),
ExchangeCardUM.Empty(
titleReference = resourceReference(id = R.string.swapping_from_title),
subtitleReference = resourceReference(id = R.string.action_buttons_you_want_to_swap),
),
createFilled(removeButtonUM = null),
createFilled(removeButtonUM = ExchangeCardUM.RemoveButtonUM { }),
)
@ -124,7 +128,7 @@ private class ExchangeCardUMProvider : PreviewParameterProvider<ExchangeCardUM>
tokenItemState = TokenItemState.Content(
id = "1",
iconState = CurrencyIconState.Locked,
titleState = TokenItemState.TitleState.Content(text = "Bitcoin"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Bitcoin")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "12 368,14 \$"),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "0,35853044 BTC"),
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(

View file

@ -23,6 +23,7 @@ internal class UpdateTokenItemsTransformer(
private val statuses: Map<Boolean, List<CryptoCurrencyStatus>>,
private val isBalanceHidden: Boolean,
private val hasSearchBar: Boolean,
private val unavailableTokensHeaderReference: TextReference,
private val onQueryChange: (String) -> Unit,
private val onActiveChange: (Boolean) -> Unit,
) : TokenListUMTransformer {
@ -62,11 +63,7 @@ internal class UpdateTokenItemsTransformer(
.toImmutableList(),
unavailableItems = buildList {
if (unavailableItems.isNotEmpty()) {
// TODO: [REDACTED_JIRA]
createGroupTitle(
textReference = stringReference(value = "Unavailable tokens"),
)
.let(::add)
createGroupTitle(textReference = unavailableTokensHeaderReference).let(::add)
}
addAll(unavailableItems)
@ -91,11 +88,21 @@ internal class UpdateTokenItemsTransformer(
return TokenItemStateConverter(
appCurrency = appCurrency,
iconStateProvider = { CryptoCurrencyToIconStateConverter(isAvailable = false).convert(it) },
titleStateProvider = { TokenItemState.TitleState.Content(text = it.currency.name, isAvailable = false) },
titleStateProvider = {
TokenItemState.TitleState.Content(
text = stringReference(value = it.currency.name),
isAvailable = false,
)
},
subtitleStateProvider = {
when (it.value) {
CryptoCurrencyStatus.Loading -> TokenItemState.SubtitleState.Loading
else -> TokenItemState.SubtitleState.TextContent(value = it.currency.symbol, isAvailable = false)
else -> {
TokenItemState.SubtitleState.TextContent(
value = stringReference(value = it.currency.symbol),
isAvailable = false,
)
}
}
},
fiatAmountStateProvider = {

View file

@ -4,6 +4,7 @@ import arrow.core.getOrElse
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
@ -12,9 +13,9 @@ import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.tokens.GetTokenListUseCase
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.TokenList
import com.tangem.features.onramp.impl.R
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.features.onramp.entity.OnrampOperation
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.tokenlist.OnrampTokenListComponent
import com.tangem.features.onramp.tokenlist.entity.TokenListUM
import com.tangem.features.onramp.tokenlist.entity.TokenListUMController
@ -74,6 +75,17 @@ internal class OnrampTokenListModel @Inject constructor(
statuses = filterTokenList,
isBalanceHidden = isBalanceHidden,
hasSearchBar = params.hasSearchBar && currencies.isNotEmpty(),
unavailableTokensHeaderReference = when (params.filterOperation) {
OnrampOperation.BUY -> resourceReference(id = R.string.tokens_list_unavailable_to_purchase_header)
OnrampOperation.SELL -> resourceReference(id = R.string.tokens_list_unavailable_to_sell_header)
OnrampOperation.SWAP -> {
// TODO: [REDACTED_JIRA]
resourceReference(
id = R.string.tokens_list_unavailable_to_swap_header,
wrappedList(""),
)
}
},
onQueryChange = ::onSearchQueryChange,
onActiveChange = ::onSearchBarActiveChange,
)

View file

@ -7,6 +7,7 @@ import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.tokenlist.entity.TokenListUM
import kotlinx.collections.immutable.persistentListOf
@ -69,7 +70,7 @@ internal class PreviewTokenListUMProvider : PreviewParameterProvider<TokenListUM
state = TokenItemState.Content(
id = "1",
iconState = CurrencyIconState.Locked,
titleState = TokenItemState.TitleState.Content(text = "Bitcoin"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Bitcoin")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "12 368,14 \$"),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "0,35853044 BTC"),
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(
@ -88,13 +89,19 @@ internal class PreviewTokenListUMProvider : PreviewParameterProvider<TokenListUM
state = TokenItemState.Content(
id = "2",
iconState = CurrencyIconState.Locked,
titleState = TokenItemState.TitleState.Content(text = "Bitcoin", isAvailable = false),
titleState = TokenItemState.TitleState.Content(
text = stringReference(value = "Bitcoin"),
isAvailable = false,
),
fiatAmountState = TokenItemState.FiatAmountState.TextContent(
text = "12 368,14 \$",
isAvailable = false,
),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "0,35853044 BTC"),
subtitleState = TokenItemState.SubtitleState.TextContent(value = "BTC", isAvailable = false),
subtitleState = TokenItemState.SubtitleState.TextContent(
value = stringReference(value = "BTC"),
isAvailable = false,
),
onItemClick = {},
onItemLongClick = {},
),

View file

@ -5,6 +5,7 @@ import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.event.consumedEvent
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.feature.wallet.impl.R
@ -76,7 +77,7 @@ internal object WalletPreviewData {
isGrayscale = false,
showCustomBadge = false,
),
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "3 172,14 $"),
)
}
@ -108,7 +109,7 @@ internal object WalletPreviewData {
tokenItemState = tokenItemDragState.copy(
id = "${group.id}_token_$tokenNumber",
titleState = TokenItemState.TitleState.Content(
text = "Token $tokenNumber from $networkNumber network",
text = stringReference(value = "Token $tokenNumber from $networkNumber network"),
),
),
groupId = group.id,

View file

@ -19,7 +19,7 @@ internal object WalletScreenPreviewData {
private val tokenItemState = TokenItemState.Content(
id = "1",
iconState = CurrencyIconState.Locked,
titleState = TokenItemState.TitleState.Content(text = "Bitcoin"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Bitcoin")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "12 368,14 \$"),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "0,35853044 BTC"),
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(
@ -45,7 +45,7 @@ internal object WalletScreenPreviewData {
TokensListItemUM.Token(
state = tokenItemState.copy(
id = "2",
titleState = TokenItemState.TitleState.Content(text = "Ethereum"),
titleState = TokenItemState.TitleState.Content(text = stringReference("Ethereum")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "3 340,79 \$"),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "1,856660295 ETH"),
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(
@ -59,7 +59,7 @@ internal object WalletScreenPreviewData {
state = TokenItemState.Unreachable(
id = "3",
iconState = CurrencyIconState.Locked,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
onItemClick = {},
onItemLongClick = {},
),
@ -67,7 +67,7 @@ internal object WalletScreenPreviewData {
TokensListItemUM.Token(
state = tokenItemState.copy(
id = "4",
titleState = TokenItemState.TitleState.Content(text = "Shiba Inu"),
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Shiba Inu")),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "48,64 \$"),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "6 200 220,00 SHIB"),
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(

View file

@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.it
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
@ -46,7 +47,7 @@ internal class CryptoCurrencyToDraggableItemConverter(
return TokenItemState.Draggable(
id = getTokenItemId(currency.id),
iconState = iconStateConverter.convert(currencyStatus),
titleState = TokenItemState.TitleState.Content(text = currency.name),
titleState = TokenItemState.TitleState.Content(text = stringReference(currency.name)),
subtitle2State = if (currencyStatus.value.isError) {
TokenItemState.Subtitle2State.Unreachable
} else {