Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-09 12:50:16 +05:00
parent f9ae0d5188
commit 269a6d1d57
21 changed files with 240 additions and 40 deletions

View file

@ -0,0 +1,53 @@
package com.tangem.common.ui.account
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.account.AccountIconSize
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* Displays account name with icon
*
* @param name account name
* @param icon portfolio account icon model
* @param iconSize portfolio account icon size
* @param nameStyle account name style
* @param nameColor account name color
* @see AccountIcon
*/
@Composable
fun AccountLabel(
name: TextReference,
icon: CryptoPortfolioIconUM,
iconSize: AccountIconSize,
modifier: Modifier = Modifier,
nameStyle: TextStyle = TangemTheme.typography.subtitle2,
nameColor: Color = TangemTheme.colors.text.tertiary,
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
AccountIcon(
name = name,
icon = icon,
size = iconSize,
)
Text(
text = name.resolveReference(),
style = nameStyle,
color = nameColor,
maxLines = 1,
)
}
}

View file

@ -320,6 +320,7 @@
<string name="common_tangem_wallet">Tangem Wallet</string>
<string name="common_terms_and_conditions">Allgemeine Geschäftsbedingungen</string>
<string name="common_terms_of_use">Nutzungsbedingungen</string>
<string name="common_to">An</string>
<string name="common_today">Heute</string>
<plurals name="common_tokens_count">
<item quantity="one">%d Token</item>
@ -1304,8 +1305,12 @@
<string name="unlock_wallet_description_full">Verwende %s oder scanne eine Karte oder Ring, um Zugriff auf deine Wallet zu erhalten.</string>
<string name="unsupported_wc_version">Verbindung fehlgeschlagen: Diese dApp verwendet Wallet Connect Version 1.0, die nicht unterstützt wird. Bitte stelle sicher, dass die dApp Wallet Connect Version 2.0 unterstützt, um eine erfolgreiche Verbindung herzustellen.</string>
<string name="user_push_notification_agreement_argument_one">Bleib auf dem Laufenden mit den neuesten Funktionen und Neuigkeiten</string>
<string name="user_push_notification_agreement_argument_one_subtitle">Echtzeit-Warnungen für Transaktionen, Umtausch und wichtige Aktualisierungen.</string>
<string name="user_push_notification_agreement_argument_one_title">Transaktionswarnungen</string>
<string name="user_push_notification_agreement_argument_three">Genehmigung für Transaktionen anfordern</string>
<string name="user_push_notification_agreement_argument_two">Sei der Erste, der von neuen Aktionen erfährt</string>
<string name="user_push_notification_agreement_argument_two_subtitle">Frühzeitiger Zugriff auf neue Funktionen und exklusive Angebote.</string>
<string name="user_push_notification_agreement_argument_two_title">Updates zu Funktionen und Neuigkeiten</string>
<string name="user_push_notification_agreement_header">Möchtest du Push-Benachrichtigungen verwenden?</string>
<string name="user_wallet_list_add_button">Neues Wallet hinzufügen</string>
<string name="user_wallet_list_delete_prompt">Möchtest Du diese Wallet wirklich entfernen?</string>

View file

@ -258,6 +258,7 @@
<string name="common_swap">Intercambiar</string>
<string name="common_terms_and_conditions">términos y condiciones</string>
<string name="common_terms_of_use">Condiciones de uso</string>
<string name="common_to">A</string>
<string name="common_today">Hoy</string>
<plurals name="common_tokens_count">
<item quantity="one">%d token</item>
@ -1204,8 +1205,12 @@
<string name="unlock_wallet_description_full">Use %s o escanee una tarjeta/anillo para tener acceso a su billetera</string>
<string name="unsupported_wc_version">Error de conexión: Esta dApp utiliza la versión 1.0 de Wallet Connect, que no es compatible. Asegúrese de que la dApp sea compatible con la versión 2.0 de Wallet Connect para conectarse correctamente.</string>
<string name="user_push_notification_agreement_argument_one">Manténgase actualizado con las últimas funciones y noticias</string>
<string name="user_push_notification_agreement_argument_one_subtitle">Alertas en tiempo real de transacciones, intercambios y actualizaciones críticas.</string>
<string name="user_push_notification_agreement_argument_one_title">Alertas de transacciones</string>
<string name="user_push_notification_agreement_argument_three">Recibir notificaciones de las transacciones entrantes</string>
<string name="user_push_notification_agreement_argument_two">Sea el primero en enterarte de nuevas promociones</string>
<string name="user_push_notification_agreement_argument_two_subtitle">Acceso anticipado a nuevas funciones y ofertas exclusivas.</string>
<string name="user_push_notification_agreement_argument_two_title">Actualizaciones de características y noticias</string>
<string name="user_push_notification_agreement_header">¿Quiere utilizar\nnotificaciones push?</string>
<string name="user_wallet_list_add_button">Agregar una nueva billetera</string>
<string name="user_wallet_list_delete_prompt">¿Estás seguro de que deseas olvidar esta billetera?</string>

View file

@ -235,6 +235,7 @@
<string name="common_swap">Échanger</string>
<string name="common_terms_and_conditions">termes et conditions</string>
<string name="common_terms_of_use">Conditions d\'utilisation</string>
<string name="common_to">À</string>
<string name="common_today">Aujourd\'hui</string>
<plurals name="common_tokens_count">
<item quantity="one">%d jeton</item>
@ -1106,7 +1107,7 @@
<string name="swapping_high_price_impact_description">Échanger ce montant de jetons sélectionnés aura un impact significatif sur les prix et réduira votre résultat.</string>
<string name="swapping_insufficient_funds">Fonds insuffisants</string>
<string name="swapping_permission_header">Donner l\'autorisation</string>
<string name="swapping_swap_action">Échangez</string>
<string name="swapping_swap_action">Échanger</string>
<string name="swapping_to_title">Vous recevez</string>
<string name="swapping_token_list_title">Choisir le jeton</string>
<string name="swapping_token_not_available">non disponible</string>
@ -1177,8 +1178,12 @@
<string name="unlock_wallet_description_full">Utilisez %s ou scannez une carte/bague pour avoir accès à votre portefeuille</string>
<string name="unsupported_wc_version">Échec de la connexion : Cette dApp utilise Wallet Connect version1.0, qui n\'est pas prise en charge. Veuillez vous assurer que la dApp prend en charge Wallet Connect version2.0 pour réussir la connexion.</string>
<string name="user_push_notification_agreement_argument_one">Restez à jour avec les dernières fonctionnalités et actualités</string>
<string name="user_push_notification_agreement_argument_one_subtitle">Alertes en temps réel pour les transactions, les échanges et les mises à jour importantes.</string>
<string name="user_push_notification_agreement_argument_one_title">Alertes de transaction</string>
<string name="user_push_notification_agreement_argument_three">Recevez des notifications des transactions entrantes</string>
<string name="user_push_notification_agreement_argument_two">Soyez le premier informé des nouvelles promotions</string>
<string name="user_push_notification_agreement_argument_two_subtitle">Accès anticipé à de nouvelles fonctionnalités et à des offres exclusives.</string>
<string name="user_push_notification_agreement_argument_two_title">Actualités et mises à jour</string>
<string name="user_push_notification_agreement_header">Souhaitez-vous utiliser les\nnotifications push?</string>
<string name="user_wallet_list_add_button">Ajouter un nouveau portefeuille</string>
<string name="user_wallet_list_delete_prompt">Êtes-vous sûr de vouloir supprimer ce portefeuille ?</string>

View file

@ -33,6 +33,7 @@
<string name="account_form_create_button">アカウントを追加</string>
<string name="account_form_edit_button">保存</string>
<string name="account_form_name">アカウント名</string>
<string name="account_form_name_already_exist_error_description">アカウント名はすでに存在しています</string>
<string name="account_form_placeholder_edit_account">アカウント</string>
<string name="account_form_placeholder_new_account">新しいアカウント</string>
<string name="account_form_title_create">アカウントを追加</string>
@ -323,6 +324,7 @@
<string name="common_tangem">Tangem</string>
<string name="common_terms_and_conditions">利用規約</string>
<string name="common_terms_of_use">利用規約</string>
<string name="common_to">宛先</string>
<string name="common_today">今日</string>
<plurals name="common_tokens_count">
<item quantity="other">%d トークン</item>
@ -885,6 +887,7 @@
</plurals>
<string name="onramp_timing_minutes">%s分</string>
<string name="onramp_title_you_get">以下が手に入ります。</string>
<string name="onramp_tos_external_providers">サービスは外部プロバイダーによって提供されます。 \nTangemは責任を負いません。</string>
<string name="onramp_transaction_status_footer_text">この画面を閉じて、トークンの詳細画面で取引状況を確認できます。</string>
<string name="onramp_up_to_rate">最大</string>
<string name="onramp_via">経由</string>
@ -1094,6 +1097,7 @@
<string name="staking_details_account_fee_info">ステーキングアカウントとは、ステーキングされたSOLが保管される特別なアカウントです。トークンをバリデーターに委任し、取引の検証に参加して報酬を受け取る際に作成されます。ステーキングアカウントの作成には少額の手数料がかかりますが、ステーキング完了後に返金されます。</string>
<string name="staking_details_annual_percentage_rate">年率</string>
<string name="staking_details_annual_percentage_rate_info">ステーキングに参加することで得られる年間収益率。</string>
<string name="staking_details_annual_percentage_yield_info">APYは、バリデータのパフォーマンスに基づいた年間利回りを示します。</string>
<string name="staking_details_apr">APR</string>
<string name="staking_details_apy">APY</string>
<string name="staking_details_auto_claiming_rewards_daily_text">報酬は毎日自動的にステーキング残高に蓄積されます。</string>
@ -1254,6 +1258,10 @@
<string name="swapping_to_title">受け取る</string>
<string name="swapping_token_list_title">トークンを選択</string>
<string name="swapping_token_not_available">利用不可</string>
<string name="tangempay_card_details_error_text">データの読み込みに失敗しました。しばらくしてからもう一度お試しください。</string>
<string name="tangempay_card_details_hide_text">非表示</string>
<string name="tangempay_card_details_reveal_text">表示</string>
<string name="tangempay_card_details_title">カードの詳細</string>
<string name="tangempay_issue_card_notification_title">アカウントを作成してカードを発行</string>
<string name="tangempay_kyc_card_ready_notification_title">Tangem Pay</string>
<string name="tangempay_kyc_in_progress_notification_button">ステータスを表示</string>
@ -1266,6 +1274,7 @@
<string name="tangempay_onboarding_security_description">カードの詳細は保護されており、アプリ内で完全に制御できます。</string>
<string name="tangempay_onboarding_security_title">内蔵セキュリティ</string>
<string name="tangempay_onboarding_title">無料のCryptoカード\nを数分で入手しましょう</string>
<string name="tangempay_title">Tangem Pay</string>
<string name="this_is_my_wallet_title">これは私のウォレットです</string>
<string name="toast_balances_hidden">残高非表示</string>
<string name="toast_balances_shown">残高表示</string>
@ -1293,6 +1302,7 @@
<string name="token_details_token_type_subtitle_no_standard">%%image%% %1$sネットワーク上のトークン</string>
<string name="token_details_unable_hide_alert_message">%1$s ( %2$s ) トークンは%3$sネットワークの主要通貨であり、このネットワーク上の他のトークンがリストにある限り、非表示にすることはできません。</string>
<string name="token_details_unable_hide_alert_title">%sを非表示にできません</string>
<string name="token_receive_show_qr_code_title">QRコードを表示</string>
<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>
@ -1661,6 +1671,7 @@
<string name="yield_module_approve_sheet_title">承認を確定する</string>
<string name="yield_module_balance_info_sheet_subtitle">資産残高に関するテキスト [プレースホルダー]</string>
<string name="yield_module_balance_info_sheet_title">あなたの%sはAaveに預けられています</string>
<string name="yield_module_chart_loading_error">チャートを読み込めません・・</string>
<string name="yield_module_deposit_error_notification_title">受け取った金額%1$s %2$sはAaveに入金されませんでした。</string>
<string name="yield_module_earn_badge">%1$s%% を獲得</string>
<string name="yield_module_earn_sheet_available_title">利用可能</string>
@ -1678,6 +1689,7 @@
<string name="yield_module_fee_policy_sheet_max_fee_title">最大手数料</string>
<string name="yield_module_fee_policy_sheet_title">手数料ポリシー</string>
<string name="yield_module_high_fee_error">ネットワーク手数料が現在高すぎます。設定した上限を下回るまで待機しています。</string>
<string name="yield_module_historical_returns">過去のリターン</string>
<string name="yield_module_main_view_approve_notification_description">ここに説明を入力してください。1〜3行が理想的です。[プレースホルダー]</string>
<string name="yield_module_main_view_approve_notification_title">トークン承認が必要</string>
<string name="yield_module_network_fee_unreachable_notification_description">ネットワーク接続を確認してください</string>
@ -1708,6 +1720,7 @@
<string name="yield_module_stop_earning">収益を停止する</string>
<string name="yield_module_stop_earning_sheet_description">オフにすると、Aaveから資金が引き出され、ウォレットの%sに戻され、報酬の獲得が停止されます。</string>
<string name="yield_module_stop_earning_sheet_fee_note">出金金額からネットワーク手数料が差し引かれます。</string>
<string name="yield_module_supply_apr">供給APR</string>
<string name="yield_module_token_details_earn_notification_apy">APY</string>
<string name="yield_module_token_details_earn_notification_description">あなたの資産を眠らせない — 残高を運用して利息を得ましょう。</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">保有資産から報酬を得る</string>
@ -1716,4 +1729,7 @@
<string name="yield_module_transfer_mode_automatic">自動</string>
<string name="yield_module_unable_to_cover_fee_description">取引のネットワーク手数料をカバーするために、 %1$s %2$sを入金してください</string>
<string name="yield_module_unable_to_cover_fee_title">%s手数料を支払えません</string>
<string name="yield_module_unavailable_subtitle">利息サービスは現在利用できません。しばらくしてから再度お試しください。</string>
<string name="yield_module_unavailable_title">収益は利用できません</string>
<string name="yield_supply_chart_loading_error">チャートを読み込めません・・</string>
</resources>

View file

@ -250,6 +250,7 @@
<string name="common_swap">Обменять</string>
<string name="common_terms_and_conditions">условия участия</string>
<string name="common_terms_of_use">Условиями использования</string>
<string name="common_to">На</string>
<string name="common_today">Сегодня</string>
<plurals name="common_tokens_count">
<item quantity="one">%d токен</item>

View file

@ -233,6 +233,7 @@
<string name="common_swap">Обмін</string>
<string name="common_terms_and_conditions">умови участі</string>
<string name="common_terms_of_use">Умовами використання</string>
<string name="common_to">До</string>
<string name="common_today">Сьогодні</string>
<plurals name="common_tokens_count">
<item quantity="one">%d токен</item>

View file

@ -179,6 +179,7 @@
<string name="common_accept">Accept</string>
<string name="common_access_denied">Access denied</string>
<string name="common_accounts">Accounts</string>
<string name="common_activate">Activate</string>
<string name="common_add">Add</string>
<string name="common_add_to_portfolio">Add to portfolio</string>
<string name="common_add_token">Add token</string>
@ -253,6 +254,7 @@
<string name="common_fee_selector_title">Speed and fee</string>
<string name="common_finish">Finish</string>
<string name="common_free">Free</string>
<string name="common_from">From</string>
<string name="common_generate_addresses">Synchronize addresses</string>
<string name="common_get_started">Get started</string>
<string name="common_go_to_provider">Go to provider</string>
@ -331,6 +333,7 @@
<string name="common_tangem_wallet">Tangem Wallet</string>
<string name="common_terms_and_conditions">terms and conditions</string>
<string name="common_terms_of_use">Terms of Use</string>
<string name="common_to">To</string>
<string name="common_today">Today</string>
<plurals name="common_tokens_count">
<item quantity="one">%d token</item>
@ -1112,6 +1115,9 @@
<string name="settings_forget_wallet_footer">This will remove the wallet from the application. The wallet itself can be added again.</string>
<string name="settings_wallet_name_title">Name</string>
<string name="stake_token_description">Put your token to work</string>
<string name="staking_account_initialization_footer">A network fee is a small payment to process and confirm your transaction on the blockchain.</string>
<string name="staking_account_initialization_message">To start staking, your TON account must be activated with a self-transaction of 1 TON. The funds stay in your wallet — this step only enables your account for staking.</string>
<string name="staking_account_initialization_title">Account activation</string>
<string name="staking_amount_requirement_error">The amount to stake must be at least %s</string>
<string name="staking_amount_tron_integer_error">Staking amount will be rounded to %1$s TRX due to network rules.</string>
<string name="staking_amount_tron_integer_error_unstaking">Unstaking amount will be rounded to %1$s TRX due to network rules.</string>
@ -1178,6 +1184,8 @@
<string name="staking_notification_restake_rewards_text">Reinvests your earned rewards in your staked amount, increasing potential earnings.</string>
<string name="staking_notification_restake_text">Restake lets you move your funds from one validator to another without the need to unstake</string>
<string name="staking_notification_stake_entire_balance_text">Youre about to stake your entire balance. We recommend leaving a small amount to cover network fees for unstaking or claiming rewards.</string>
<string name="staking_notification_ton_account_initialization_message">To start staking, your TON account must be activated with a self-transaction of 1 TON. The funds stay in your wallet — this step only enables your account for staking.</string>
<string name="staking_notification_ton_account_initialization_title">Account activation</string>
<string name="staking_notification_ton_activate_account">To start staking in TON, first send a small transaction to your own address — this will activate your wallet.</string>
<string name="staking_notification_ton_extra_reserve_info">Up to 0.2 TON may be required in addition to the network fee to complete the transaction. Any unused amount will be refunded.</string>
<string name="staking_notification_ton_extra_reserve_is_required">0.2 TON is required to proceed with this operation, in addition to the network fee. Please top up your balance.</string>

View file

@ -60,10 +60,10 @@ fun TokenListItem(state: TokensListItemUM, isBalanceHidden: Boolean, modifier: M
@Composable
fun PortfolioListItem(state: TokensListItemUM.Portfolio, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
if (state.isExpanded) {
ExpandedPortfolioHeader(state = state.state, isCollapsable = state.isCollapsable, modifier = modifier)
ExpandedPortfolioHeader(state = state.tokenItemUM, isCollapsable = state.isCollapsable, modifier = modifier)
} else {
TokenItem(
state = state.state,
state = state.tokenItemUM,
isBalanceHidden = isBalanceHidden,
modifier = modifier,
)

View file

@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.fields.entity.SearchBarUM
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.TextReference
import kotlinx.collections.immutable.ImmutableList
/** Tokens list item state */
@Immutable
@ -41,12 +42,12 @@ sealed interface TokensListItemUM {
}
data class Portfolio(
val state: TokenItemState,
val tokenItemUM: TokenItemState,
val isExpanded: Boolean,
val isCollapsable: Boolean,
val tokens: List<PortfolioTokensListItemUM>,
val tokens: ImmutableList<PortfolioTokensListItemUM>,
) : TokensListItemUM {
override val id: String = state.id
override val id: String = tokenItemUM.id
}
data class Text(override val id: Any, val text: TextReference) : TokensListItemUM

View file

@ -16,7 +16,7 @@ internal class LoadingAccountTokenItemConverter(
val (account, currencies) = value
return TokensListItemUM.Portfolio(
state = AccountCryptoPortfolioItemStateConverter(
tokenItemUM = AccountCryptoPortfolioItemStateConverter(
appCurrency = appCurrency,
account = account,
onItemClick = null,

View file

@ -33,7 +33,7 @@ internal class SetNoAvailablePairsTransformerV2(
TokenListUMData.AccountList(
tokensList = accountList.map { (account, cryptoCurrencies) ->
TokensListItemUM.Portfolio(
state = AccountCryptoPortfolioItemStateConverter(
tokenItemUM = AccountCryptoPortfolioItemStateConverter(
appCurrency = appCurrency,
account = account,
onItemClick = null,

View file

@ -1,5 +1,7 @@
package com.tangem.features.onramp.swap.entity
import androidx.compose.runtime.Immutable
import com.tangem.common.ui.account.CryptoPortfolioIconUM
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.TextReference
@ -11,7 +13,7 @@ import com.tangem.core.ui.extensions.TextReference
internal sealed interface ExchangeCardUM {
/** Title reference */
val titleReference: TextReference
val titleUM: TitleUM
/** Remove button UI model */
val removeButtonUM: RemoveButtonUM?
@ -19,11 +21,11 @@ internal sealed interface ExchangeCardUM {
/**
* Empty state
*
* @property titleReference title reference
* @property titleUM title reference
* @property subtitleReference empty token subtitle reference
*/
data class Empty(
override val titleReference: TextReference,
override val titleUM: TitleUM,
val subtitleReference: TextReference,
) : ExchangeCardUM {
@ -33,15 +35,29 @@ internal sealed interface ExchangeCardUM {
/**
* Filled
*
* @property titleReference title reference
* @property titleUM title reference
* @property removeButtonUM remove button UI model
* @property tokenItemState token item state
*/
data class Filled(
override val titleReference: TextReference,
override val titleUM: TitleUM,
override val removeButtonUM: RemoveButtonUM?,
val tokenItemState: TokenItemState,
) : ExchangeCardUM
data class RemoveButtonUM(val onClick: () -> Unit)
@Immutable
sealed interface TitleUM {
data class Text(
val title: TextReference,
) : TitleUM
data class Account(
val prefixText: TextReference,
val name: TextReference,
val icon: CryptoPortfolioIconUM,
) : TitleUM
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.features.onramp.swap.entity.transformer
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.domain.models.account.Account
import com.tangem.features.onramp.swap.entity.ExchangeCardUM
import com.tangem.features.onramp.swap.entity.SwapSelectTokensUM
import com.tangem.features.onramp.swap.entity.SwapSelectTokensUMTransformer
@ -17,6 +18,8 @@ import com.tangem.features.onramp.swap.entity.utils.toFilled
internal class SelectFromTokenTransformer(
private val selectedTokenItemState: TokenItemState,
private val onRemoveClick: () -> Unit,
private val account: Account.CryptoPortfolio,
private val isAccountsMode: Boolean,
) : SwapSelectTokensUMTransformer {
override fun transform(prevState: SwapSelectTokensUM): SwapSelectTokensUM {
@ -24,6 +27,9 @@ internal class SelectFromTokenTransformer(
exchangeFrom = prevState.exchangeFrom.toFilled(
selectedTokenItemState = selectedTokenItemState,
removeButtonUM = ExchangeCardUM.RemoveButtonUM(onClick = onRemoveClick),
account = account,
isAccountsMode = isAccountsMode,
isFromCurrency = true,
),
)
}

View file

@ -1,6 +1,7 @@
package com.tangem.features.onramp.swap.entity.transformer
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.domain.models.account.Account
import com.tangem.features.onramp.swap.entity.ExchangeCardUM
import com.tangem.features.onramp.swap.entity.SwapSelectTokensUM
import com.tangem.features.onramp.swap.entity.SwapSelectTokensUMTransformer
@ -15,12 +16,19 @@ import com.tangem.features.onramp.swap.entity.utils.toFilled
*/
internal class SelectToTokenTransformer(
private val selectedTokenItemState: TokenItemState,
private val isAccountsMode: Boolean,
private val account: Account.CryptoPortfolio,
) : SwapSelectTokensUMTransformer {
override fun transform(prevState: SwapSelectTokensUM): SwapSelectTokensUM {
return prevState.copy(
exchangeFrom = prevState.exchangeFrom.hideRemoveButton(),
exchangeTo = prevState.exchangeTo.toFilled(selectedTokenItemState = selectedTokenItemState),
exchangeTo = prevState.exchangeTo.toFilled(
selectedTokenItemState = selectedTokenItemState,
isAccountsMode = isAccountsMode,
account = account,
isFromCurrency = false,
),
)
}

View file

@ -1,14 +1,16 @@
package com.tangem.features.onramp.swap.entity.utils
import com.tangem.common.ui.account.toUM
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.models.account.Account
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),
titleUM = ExchangeCardUM.TitleUM.Text(resourceReference(id = R.string.swapping_from_title)),
subtitleReference = resourceReference(id = R.string.action_buttons_you_want_to_swap),
)
}
@ -16,7 +18,7 @@ internal fun createEmptyExchangeFrom(): ExchangeCardUM.Empty {
/** Create empty exchange "to" card */
internal fun createEmptyExchangeTo(): ExchangeCardUM.Empty {
return ExchangeCardUM.Empty(
titleReference = resourceReference(id = R.string.swapping_to_title),
titleUM = ExchangeCardUM.TitleUM.Text(resourceReference(id = R.string.swapping_to_title)),
subtitleReference = resourceReference(id = R.string.action_buttons_you_want_to_receive),
)
}
@ -29,10 +31,25 @@ internal fun createEmptyExchangeTo(): ExchangeCardUM.Empty {
*/
internal fun ExchangeCardUM.toFilled(
selectedTokenItemState: TokenItemState,
account: Account.CryptoPortfolio,
isAccountsMode: Boolean,
isFromCurrency: Boolean,
removeButtonUM: ExchangeCardUM.RemoveButtonUM? = null,
): ExchangeCardUM.Filled {
return ExchangeCardUM.Filled(
titleReference = titleReference,
titleUM = if (isAccountsMode) {
ExchangeCardUM.TitleUM.Account(
prefixText = if (isFromCurrency) {
resourceReference(R.string.common_from)
} else {
resourceReference(R.string.common_to)
},
name = account.accountName.toUM().value,
icon = account.icon.toUM(),
)
} else {
titleUM
},
tokenItemState = selectedTokenItemState,
removeButtonUM = removeButtonUM,
)

View file

@ -8,7 +8,9 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.features.onramp.component.SwapSelectTokensComponent
import com.tangem.features.onramp.swap.entity.SwapSelectTokensController
@ -32,6 +34,7 @@ internal class SwapSelectTokensModel @Inject constructor(
private val router: Router,
private val analyticsEventHandler: AnalyticsEventHandler,
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
) : Model() {
val state: StateFlow<SwapSelectTokensUM> = controller.state
@ -43,9 +46,12 @@ internal class SwapSelectTokensModel @Inject constructor(
private val params = paramsContainer.require<SwapSelectTokensComponent.Params>()
private var isAccountsMode: Boolean = false
init {
controller.update { it.copy(onBackClick = ::onBackClick) }
subscribeOnAccountsMode()
subscribeOnBalanceHidingSettings()
}
@ -66,6 +72,11 @@ internal class SwapSelectTokensModel @Inject constructor(
transformer = SelectFromTokenTransformer(
selectedTokenItemState = selectedTokenItemState,
onRemoveClick = ::onRemoveFromTokenClick,
isAccountsMode = isAccountsMode,
account = Account.CryptoPortfolio.createMainAccount(
userWalletId = params.userWalletId,
cryptoCurrencies = setOf(status.currency),
), // todo account from from cryptocurrency
),
)
}
@ -84,7 +95,16 @@ internal class SwapSelectTokensModel @Inject constructor(
modelScope.launch {
_toCurrencyStatus.value = status
controller.update(transformer = SelectToTokenTransformer(selectedTokenItemState))
controller.update(
transformer = SelectToTokenTransformer(
selectedTokenItemState = selectedTokenItemState,
isAccountsMode = isAccountsMode,
account = Account.CryptoPortfolio.createMainAccount(
userWalletId = params.userWalletId,
cryptoCurrencies = setOf(status.currency),
), // todo account from from cryptocurrency
),
)
// require some delay to show state with selected "from" and "to" tokens
delay(timeMillis = 500)
@ -119,6 +139,16 @@ internal class SwapSelectTokensModel @Inject constructor(
.launchIn(modelScope)
}
private fun subscribeOnAccountsMode() {
isAccountsModeEnabledUseCase()
.distinctUntilChanged()
.onEach {
isAccountsMode = it
}
.flowOn(dispatchers.default)
.launchIn(modelScope)
}
private fun onBackClick() {
analyticsEventHandler.send(
event = MainScreenAnalyticsEvent.ButtonClose(source = AnalyticsParam.ScreensSources.Swap),

View file

@ -14,11 +14,14 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.account.AccountLabel
import com.tangem.core.ui.components.account.AccountIconSize
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.components.rows.NetworkTitle
@ -46,13 +49,14 @@ internal fun ExchangeCard(state: ExchangeCardUM, isBalanceHidden: Boolean, modif
modifier = modifier
.fillMaxWidth()
.heightIn(min = 116.dp)
.background(
color = TangemTheme.colors.background.primary,
shape = TangemTheme.shapes.roundedCornersXMedium,
),
.clip(TangemTheme.shapes.roundedCornersXMedium)
.background(TangemTheme.colors.background.primary),
verticalArrangement = Arrangement.SpaceBetween,
) {
Title(titleReference = state.titleReference, removeButtonUM = state.removeButtonUM)
Title(
titleUM = state.titleUM,
removeButtonUM = state.removeButtonUM,
)
AnimatedContent(
targetState = state,
@ -73,16 +77,39 @@ internal fun ExchangeCard(state: ExchangeCardUM, isBalanceHidden: Boolean, modif
}
@Composable
private fun Title(titleReference: TextReference, removeButtonUM: ExchangeCardUM.RemoveButtonUM?) {
private fun Title(titleUM: ExchangeCardUM.TitleUM, removeButtonUM: ExchangeCardUM.RemoveButtonUM?) {
NetworkTitle(
title = {
Text(
text = titleReference.resolveReference(),
color = TangemTheme.colors.text.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = TangemTheme.typography.subtitle2,
)
AnimatedContent(
titleUM,
) { currentState ->
when (currentState) {
is ExchangeCardUM.TitleUM.Account -> Row(
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = currentState.prefixText.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
AccountLabel(
name = currentState.name,
icon = currentState.icon,
iconSize = AccountIconSize.ExtraSmall,
nameStyle = TangemTheme.typography.subtitle2,
nameColor = TangemTheme.colors.text.tertiary,
)
}
is ExchangeCardUM.TitleUM.Text -> Text(
text = currentState.title.resolveReference(),
color = TangemTheme.colors.text.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = TangemTheme.typography.subtitle2,
)
}
}
},
action = { RemoveButton(state = removeButtonUM) },
)
@ -153,7 +180,7 @@ private class ExchangeCardUMProvider : PreviewParameterProvider<ExchangeCardUM>
override val values: Sequence<ExchangeCardUM> = sequenceOf(
ExchangeCardUM.Empty(
titleReference = resourceReference(id = R.string.swapping_from_title),
titleUM = ExchangeCardUM.TitleUM.Text(resourceReference(id = R.string.swapping_from_title)),
subtitleReference = resourceReference(id = R.string.action_buttons_you_want_to_swap),
),
createFilled(removeButtonUM = null),
@ -162,7 +189,7 @@ private class ExchangeCardUMProvider : PreviewParameterProvider<ExchangeCardUM>
private fun createFilled(removeButtonUM: ExchangeCardUM.RemoveButtonUM?): ExchangeCardUM.Filled {
return ExchangeCardUM.Filled(
titleReference = resourceReference(id = R.string.swapping_from_title),
titleUM = ExchangeCardUM.TitleUM.Text(resourceReference(id = R.string.swapping_from_title)),
removeButtonUM = removeButtonUM,
tokenItemState = TokenItemState.Content(
id = "1",

View file

@ -26,7 +26,7 @@ internal class UpdateAccountTokenItemConverter(
override fun convert(value: AccountAvailabilityUM): TokensListItemUM.Portfolio {
return TokensListItemUM.Portfolio(
state = AccountCryptoPortfolioItemStateConverter(
tokenItemUM = AccountCryptoPortfolioItemStateConverter(
appCurrency = appCurrency,
account = value.account,
onItemClick = null,

View file

@ -19,6 +19,7 @@ import com.tangem.feature.wallet.presentation.common.WalletPreviewData.topBarCon
import com.tangem.feature.wallet.presentation.wallet.state.model.*
import com.tangem.utils.StringsSigns.DASH_SIGN
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
internal object WalletScreenPreviewData {
private val tokenItemState = TokenItemState.Content(
@ -86,17 +87,17 @@ internal object WalletScreenPreviewData {
private val portfolioContentState = WalletTokensListState.ContentState.PortfolioContent(
items = persistentListOf(
TokensListItemUM.Portfolio(
tokens = textContentTokensState.items.filterIsInstance<PortfolioTokensListItemUM>(),
tokens = textContentTokensState.items.filterIsInstance<PortfolioTokensListItemUM>().toPersistentList(),
isExpanded = false,
isCollapsable = true,
state = AccountItemPreviewData.accountItem
tokenItemUM = AccountItemPreviewData.accountItem
.copy(iconState = AccountItemPreviewData.accountLetterIcon),
),
TokensListItemUM.Portfolio(
tokens = textContentTokensState.items.filterIsInstance<PortfolioTokensListItemUM>(),
tokens = textContentTokensState.items.filterIsInstance<PortfolioTokensListItemUM>().toPersistentList(),
isExpanded = true,
isCollapsable = true,
state = AccountItemPreviewData.accountItem,
tokenItemUM = AccountItemPreviewData.accountItem,
),
),
organizeTokensButtonConfig = WalletTokensListState.OrganizeTokensButtonConfig(

View file

@ -112,10 +112,10 @@ internal class TokenListStateConverter(
is WalletTokensListState.Empty -> listOf()
}
return TokensListItemUM.Portfolio(
state = accountItem,
tokenItemUM = accountItem,
isExpanded = isExtend,
isCollapsable = true,
tokens = items.filterIsInstance<PortfolioTokensListItemUM>(),
tokens = items.filterIsInstance<PortfolioTokensListItemUM>().toPersistentList(),
)
}