Updated on 2026-08-14
This commit is contained in:
commit
f08991988d
16 changed files with 722 additions and 8 deletions
|
|
@ -50,7 +50,6 @@
|
|||
<string name="app_settings_theme_selector_title">Thème</string>
|
||||
<string name="app_settings_title">Paramètres de l\'application</string>
|
||||
<string name="backup_complete_seed_description">Ces mots ne peuvent pas être récupérés en cas de perte. Assurez-vous de les conserver en lieu sûr.</string>
|
||||
<string name="backup_seed_caution">Ne partagez jamais ces mots. Quiconque les apprend peut voler toutes vos cryptomonnaies. Tangem ne vous les demandera jamais. Les %s mots ci-dessous constituent la phrase de récupération de votre portefeuille. Cette phrase vous permet de récupérer votre portefeuille en cas de perte de votre appareil.</string>
|
||||
<string name="balance_hidden_description">Pour masquer ou afficher vos soldes, il suffit de retourner l\'écran de votre appareil vers le bas ou de le désactiver dans les paramètres</string>
|
||||
<string name="balance_hidden_do_not_show_button">Ne plus afficher</string>
|
||||
<string name="balance_hidden_got_it_button">Compris</string>
|
||||
|
|
@ -118,6 +117,7 @@
|
|||
<string name="common_close">Fermer</string>
|
||||
<string name="common_confirm">Confirmez</string>
|
||||
<string name="common_continue">Continuer</string>
|
||||
<string name="common_convert">Convertir</string>
|
||||
<string name="common_copy">Copier</string>
|
||||
<string name="common_copy_address">Copier l\'adresse</string>
|
||||
<string name="common_create">Créer</string>
|
||||
|
|
@ -702,6 +702,11 @@
|
|||
<string name="organize_tokens_sort_by_balance">Par solde</string>
|
||||
<string name="organize_tokens_title">Organiser les jetons</string>
|
||||
<string name="organize_tokens_ungroup">Dégrouper</string>
|
||||
<string name="push_notifications_more_info">Plus d\'infos</string>
|
||||
<string name="push_notifications_permission_alert_description">Vous pouvez activer les notifications pour Tangem dans les paramètres.</string>
|
||||
<string name="push_notifications_permission_alert_negative_button">Activer plus tard</string>
|
||||
<string name="push_notifications_permission_alert_positive_button">Paramètres</string>
|
||||
<string name="push_notifications_permission_alert_title">Activer les notifications</string>
|
||||
<string name="push_transactions_notifications_description">Recevez des alertes pour les transactions entrantes sur les réseaux pris en charge.</string>
|
||||
<string name="qr_scanner_camera_denied_gallery_button">Sélectionnez dans la galerie</string>
|
||||
<string name="qr_scanner_camera_denied_settings_button">Paramètres</string>
|
||||
|
|
@ -775,7 +780,9 @@
|
|||
<string name="send_alert_fee_too_low_text">Vous avez spécifié une commission inférieure au montant recommandé, ce qui pourrait entraîner un retard dans votre transaction. Continuer?</string>
|
||||
<string name="send_alert_transaction_failed_text">Raison : %1$s\nCode : %2$s</string>
|
||||
<string name="send_alert_transaction_failed_title">La transaction est incomplète</string>
|
||||
<string name="send_amount_convert_to_another_token">Convertir en un autre jeton</string>
|
||||
<string name="send_amount_label">Montant</string>
|
||||
<string name="send_amount_receive_token_subtitle">Sera envoyé au destinataire</string>
|
||||
<string name="send_bitcoin_custom_fee_footer">Vous pouvez définir vos frais de transaction en ajustant la valeur dans le champ Satoshi par vByte.</string>
|
||||
<string name="send_custom_amount_fee_footer">Les frais qui seront facturés pour votre transaction. Vous pouvez définir votre propre valeur.</string>
|
||||
<string name="send_custom_evm_max_fee">Frais maximum</string>
|
||||
|
|
@ -799,6 +806,7 @@
|
|||
<string name="send_fee_unreachable_error_text">Vérifiez votre connexion réseau</string>
|
||||
<string name="send_fee_unreachable_error_title">Informations sur les frais de réseau inaccessibles</string>
|
||||
<string name="send_from_wallet_android">De</string>
|
||||
<string name="send_from_wallet_name">De %s</string>
|
||||
<string name="send_gas_limit">Limite de gaz</string>
|
||||
<string name="send_gas_limit_footer">Il s\'agit du montant maximal de gaz qui sera dépensé pour effectuer une transaction ou un contrat. Une limite de gaz empêche des frais imprévus ou illimités lors de l\'exécution d\'une transaction.</string>
|
||||
<string name="send_gas_price">Prix du gaz</string>
|
||||
|
|
@ -806,6 +814,7 @@
|
|||
<string name="send_max_amount">Max</string>
|
||||
<string name="send_max_amount_label">Somme maximale</string>
|
||||
<string name="send_max_fee">Frais jusqu\'à</string>
|
||||
<string name="send_memo">Mémo : %s</string>
|
||||
<string name="send_memo_destination_tag_error">Mémo invalide</string>
|
||||
<string name="send_network_fee_warning_title">Couverture des frais de réseau</string>
|
||||
<string name="send_notification_exceed_balance_text">Fonds insuffisants pour le transfert, car le total des frais et du montant du transfert dépasse le solde existant</string>
|
||||
|
|
@ -816,6 +825,7 @@
|
|||
<string name="send_notification_fee_too_high_title">Les frais de douane sont élevés</string>
|
||||
<string name="send_notification_high_fee_text">En raison des particularités du réseau %1$s, les frais de transfert de la totalité du solde sont plus élevés. Pour réduire la commission, vous pouvez en laisser %2$s.</string>
|
||||
<string name="send_notification_high_fee_title">Les frais sont plus élevés</string>
|
||||
<string name="send_notification_invalid_amount_rent_destination">Le compte du bénéficiaire n\'est pas activé. Le montant minimum du transfert doit être égal ou supérieur au solde exonéré de loyer : %1$s.</string>
|
||||
<string name="send_notification_invalid_amount_rent_fee">Le solde de votre compte ne peut pas être inférieur au montant du loyer. Veuillez conserver au moins %1$s sur votre compte ou retirer tous les fonds.</string>
|
||||
<string name="send_notification_invalid_amount_text">La commission incluse dépasse le montant du transfert, ce qui entraîne une valeur négative</string>
|
||||
<string name="send_notification_invalid_amount_title">Montant invalide</string>
|
||||
|
|
@ -835,6 +845,7 @@
|
|||
<string name="send_recipient">Destinataire</string>
|
||||
<string name="send_recipient_address_error">Adresse non valide</string>
|
||||
<string name="send_recipient_address_footer">Assurez-vous que l\'adresse du portefeuille de réception est sur le réseau %s pour éviter de perdre vos jetons</string>
|
||||
<string name="send_recipient_address_footer_highlighted_part">envoyer à %s</string>
|
||||
<string name="send_recipient_label">Envoyer à</string>
|
||||
<string name="send_recipient_memo_footer">Un Memo/Destination Tag est un identifiant unique permettant de différencier les transactions envoyées au même destinataire sur le même réseau. Attention : L\'omission d\'un mémo peut entraîner des fonds mal placés</string>
|
||||
<string name="send_recipient_memo_footer_v2">Le Memo / Destination Tag est un code qui distingue les transactions envoyées à un destinataire partagé sur un réseau crypto.</string>
|
||||
|
|
@ -851,6 +862,7 @@
|
|||
<string name="send_summary_transaction_description_suffix_fee_covered">les frais de réseau seront couverts en utilisant %1$s énergie</string>
|
||||
<string name="send_summary_transaction_description_suffix_fee_reduced">les frais de réseau seront réduits en utilisant %1$s énergie</string>
|
||||
<string name="send_summary_transaction_description_suffix_including">y compris des frais de réseau de %1$s</string>
|
||||
<string name="send_to_address">À l\'adresse</string>
|
||||
<string name="send_transaction_success">La transaction a été signée avec succès et envoyée au nœud de blockchain. Le solde du portefeuille sera mis à jour après un certain temps</string>
|
||||
<string name="send_tron_account_activation_error">%1$s est un actif du réseau Tron. Pour calculer les frais et effectuer une transaction, déposez du Tron (TRX) sur votre compte.</string>
|
||||
<string name="send_validation_amount_exceeds_balance">Le montant dépasse le solde</string>
|
||||
|
|
@ -860,6 +872,7 @@
|
|||
<string name="send_validation_invalid_fee">Les frais de commissions dépassent le solde</string>
|
||||
<string name="send_validation_invalid_total">Le total dépasse le solde</string>
|
||||
<string name="send_with_swap_confirm_title">Échanger et envoyer</string>
|
||||
<string name="send_with_swap_recipient_amount_title">Montant à recevoir</string>
|
||||
<string name="sent_transaction_sent_title">Transaction envoyée</string>
|
||||
<string name="settings_card_settings_footer">Scannez la carte/ bague que vous souhaitez configurer.</string>
|
||||
<string name="settings_forget_wallet">Oublier le portefeuille</string>
|
||||
|
|
@ -1013,6 +1026,7 @@
|
|||
<string name="swap_story_second_title">Meilleurs Tarifs</string>
|
||||
<string name="swap_story_third_subtitle">Simple et intuitif, vous permettant d\'échanger des jetons en quelques clics</string>
|
||||
<string name="swap_story_third_title">Plus Simple Que Jamais</string>
|
||||
<string name="swap_via_provider">Échange via le fournisseur</string>
|
||||
<string name="swapping_alert_cex_description">Le montant comprend :\n• les frais du fournisseur de services\n• les frais de réseau pour l\'envoi de %s depuis l\'échange vers l\'adresse de l\'utilisateur.</string>
|
||||
<string name="swapping_alert_cex_description_with_slippage">Le montant comprend :\n• les frais du fournisseur de services\n• les frais de réseau pour l\'envoi de %1$s depuis l\'échange vers l\'adresse de l\'utilisateur. \n\nLe slippage du fournisseur peut atteindre %2$s</string>
|
||||
<string name="swapping_alert_dex_description">Le montant comprend les frais du fournisseur de services.</string>
|
||||
|
|
@ -1164,6 +1178,7 @@
|
|||
<string name="wallet_promo_banner_description">Accédez à plus de 13 000 cryptomonnaies. Achetez, vendez, échangez et stakez en un seul clic.\nAssociez jusqu\'à trois cartes pour une sauvegarde.</string>
|
||||
<string name="wallet_promo_banner_title">Découvrez le Portefeuille Tangem</string>
|
||||
<string name="wallet_settings_push_notifications_description">Recevez des notifications sur les transactions entrantes du portefeuille et les mises à jour de Tangem.</string>
|
||||
<string name="wallet_settings_push_notifications_title">Notifications de transaction</string>
|
||||
<string name="wallet_settings_title">Paramètres du portefeuille</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
<string name="warning_access_denied_message">Utilisez %s ou scannez une carte/bague pour déverrouiller l\'accès à votre portefeuille</string>
|
||||
|
|
@ -1255,6 +1270,7 @@
|
|||
<string name="warning_testnet_card_title">À des fins de test uniquement</string>
|
||||
<string name="warning_token_balance_not_updated">Le solde peut être obsolète. Rafraîchissez la page.</string>
|
||||
<string name="wc_alert_audit_malicious_domain">Domaine malveillant</string>
|
||||
<string name="wc_alert_unknown_error_description_no_error_code">Si le problème persiste, n’hésitez pas à contacter notre support.</string>
|
||||
<string name="wc_alert_unsupported_dapps_description">Le portefeuille Tangem ne prend actuellement pas en charge %ss</string>
|
||||
<string name="wc_alert_unsupported_dapps_title">dApp non prise en charge</string>
|
||||
<string name="wc_connections">Connexions</string>
|
||||
|
|
|
|||
|
|
@ -1253,6 +1253,7 @@
|
|||
<string name="warning_rate_app_message">Ваш отзыв мотивирует нас сделать кошелек Tangem еще лучше</string>
|
||||
<string name="warning_rate_app_title">Нравится Tangem?</string>
|
||||
<string name="warning_receive_blocked_hedera_token_association_required_message">Вам необходимо провести ассоциацию токена для того, чтобы иметь возможность принимать его</string>
|
||||
<string name="warning_receive_blocked_token_trustline_required_message">Вы должны открыть трастлайн для своего токена, чтобы иметь возможность получить на него средства.</string>
|
||||
<string name="warning_rent_fee_title">Необходима плата за аренду сети</string>
|
||||
<string name="warning_seedphrase_action_required_title">Требуется действие</string>
|
||||
<string name="warning_seedphrase_contacted_support">Вы обращались в службу поддержки через приложение в течение 7 дней после создания кошелька? Если обращались или не уверены, нажмите «Да» и следуйте инструкциям.</string>
|
||||
|
|
@ -1268,26 +1269,71 @@
|
|||
<string name="warning_some_networks_unreachable_message">Свайпните вниз для обновления или попробуйте позже.</string>
|
||||
<string name="warning_some_networks_unreachable_title">Некоторые сети недоступны</string>
|
||||
<string name="warning_some_token_balances_not_updated">Некоторые балансы токенов не удалось обновить</string>
|
||||
<string name="warning_stellar_token_trustline_not_enough_xlm">Недостаточно %s. Пополните свой XLM аккаунт чтобы открыть трастлайн.</string>
|
||||
<string name="warning_testnet_card_message">Это Testnet карта. Он не может обрабатывать транзакции и используется только в целях тестирования и разработки.</string>
|
||||
<string name="warning_testnet_card_title">Только для целей тестирования</string>
|
||||
<string name="warning_token_balance_not_updated">Возможно, баланс устарел. Обновите страницу.</string>
|
||||
<string name="warning_token_trustline_button_title">Открыть Trustline</string>
|
||||
<string name="warning_token_trustline_subtitle">Согласно правилам сети, чтобы пополнить этот токен, необходимо сначала открыть Trustline — это позволит вашему кошельку принимать и хранить этот актив.</string>
|
||||
<string name="warning_token_trustline_title">Откройте Trustline</string>
|
||||
<string name="warning_token_trustline_title">Требуется трастлайн</string>
|
||||
<string name="wc_alert_audit_malicious_domain">Вредоносный домен</string>
|
||||
<string name="wc_alert_audit_unknown_domain">Неизвестный домен</string>
|
||||
<string name="wc_alert_connect_anyway">Подключиться всё равно</string>
|
||||
<string name="wc_alert_connection_timeout_description">Ошибка тайм-аута. Пожалуйста, попробуйте позже.</string>
|
||||
<string name="wc_alert_connection_timeout_title">Не удалось подключиться через Wallet Connect</string>
|
||||
<string name="wc_alert_domain_issues_description">Этот домен не может быть верифицирован. Внимательно проверьте запрос перед одобрением.</string>
|
||||
<string name="wc_alert_session_disconnected_description">Пожалуйста, вернитесь в браузер и выполните повторное подключение через WalletConnect.</string>
|
||||
<string name="wc_alert_session_disconnected_title">Сессия Wallet Connect была завершена</string>
|
||||
<string name="wc_alert_sign_anyway">Подписать всё равно</string>
|
||||
<string name="wc_alert_unknown_error_description">Код ошибки: %s. Если проблема сохраняется, обратитесь в нашу службу поддержки.</string>
|
||||
<string name="wc_alert_unknown_error_description_no_error_code">Если проблема сохраняется, обратитесь в нашу службу поддержки</string>
|
||||
<string name="wc_alert_unknown_error_title">Мы обнаружили неизвестную ошибку</string>
|
||||
<string name="wc_alert_unsupported_dapps_description">Кошелек Tangem.в настоящий момент не поддерживает %s</string>
|
||||
<string name="wc_alert_unsupported_dapps_title">Неподдерживаемый dApp</string>
|
||||
<string name="wc_alert_unsupported_method_title">Мы обнаружили неизвестную ошибку</string>
|
||||
<string name="wc_alert_unsupported_networks_description">Tangem в настоящее время не поддерживает необходимую сеть для %s</string>
|
||||
<string name="wc_alert_unsupported_networks_title">Неподдерживаемые сети</string>
|
||||
<string name="wc_alert_verified_domain_description">Tangem поддерживает сеть, необходимую для %s</string>
|
||||
<string name="wc_alert_verified_domain_title">Верифицированный домен</string>
|
||||
<string name="wc_alert_wrong_card_description">Выбрана не верная карта или кольцо</string>
|
||||
<string name="wc_alert_wrong_card_title">Похоже, возникла проблема</string>
|
||||
<string name="wc_allow_to_spend">Разрешение на использование</string>
|
||||
<string name="wc_common_address">Адрес</string>
|
||||
<string name="wc_common_connect">Подключение</string>
|
||||
<string name="wc_common_loading">Загрузка</string>
|
||||
<string name="wc_common_network">Сеть</string>
|
||||
<string name="wc_common_networks">Сети</string>
|
||||
<string name="wc_common_unlimited">Безлимитно</string>
|
||||
<string name="wc_common_wallet">Кошелек</string>
|
||||
<string name="wc_connected_networks">Подключенные сети</string>
|
||||
<string name="wc_connection_reqeust_can_view_balance">Посмотреть баланс кошелька и его активность</string>
|
||||
<string name="wc_connection_reqeust_cant_sign">Подписать транзакцию без вашего участия</string>
|
||||
<string name="wc_connection_reqeust_request_approval">Запрос разрешения на транзакцию</string>
|
||||
<string name="wc_connection_reqeust_will_not">Не имеет возможности</string>
|
||||
<string name="wc_connection_reqeust_would_like">Хотели бы</string>
|
||||
<string name="wc_connection_request">Запрос на подключение</string>
|
||||
<string name="wc_connections">Подключения</string>
|
||||
<string name="wc_contents">Вложение</string>
|
||||
<string name="wc_copy_data_button_text">Копировать данные</string>
|
||||
<string name="wc_custom_allowance_title">Настраиваемый лимит</string>
|
||||
<string name="wc_disconnect_all">Отключить все</string>
|
||||
<string name="wc_disconnect_all_alert_title">Отключить все dApp</string>
|
||||
<string name="wc_estimated_wallet_changes">Предварительные изменения</string>
|
||||
<string name="wc_estimated_wallet_changes_not_simulated">Не удалось выполнить симуляцию транзакции. Пожалуйста, действуйте с осторожностью.</string>
|
||||
<string name="wc_malicious_transaction">Вредоносная транзакция</string>
|
||||
<string name="wc_missing_required_network_description">Добавьте сеть %s в ваш портфель для выбранного кошелька</string>
|
||||
<string name="wc_missing_required_network_title">В кошельке не добавлены необходимые сети</string>
|
||||
<string name="wc_new_connection">Новое подключение</string>
|
||||
<string name="wc_no_sessions_desc">Подключите свой кошелек к различным dApp</string>
|
||||
<string name="wc_no_sessions_title">Нет подключений</string>
|
||||
<string name="wc_notification_security_risk_subtitle">Этот домен помечен как небезопасный несколькими поставщиками систем безопасности. Немедленно покиньте его, чтобы защитить свои активы.</string>
|
||||
<string name="wc_notification_security_risk_title">Известный риск безопасности</string>
|
||||
<string name="wc_request_from">Запрос от</string>
|
||||
<string name="wc_signature_type">Тип подписи</string>
|
||||
<string name="wc_transaction_info_to_title">На</string>
|
||||
<string name="wc_transaction_request">Запрос транзакции</string>
|
||||
<string name="wc_transaction_request_title">Запрос транзакции</string>
|
||||
<string name="wc_unlimited_amount">Безлимитное количество</string>
|
||||
<string name="wc_wallet_connect">Подключение кошелька</string>
|
||||
<string name="welcome_interrupted_backup_alert_discard">Отказаться</string>
|
||||
<string name="welcome_interrupted_backup_alert_message">Вы не закончили резервное копирование. Хотите продолжить?</string>
|
||||
|
|
|
|||
|
|
@ -722,6 +722,9 @@
|
|||
<string name="organize_tokens_title">Сортування токенів</string>
|
||||
<string name="organize_tokens_ungroup">Список</string>
|
||||
<string name="push_notifications_more_info">Більше</string>
|
||||
<string name="push_notifications_permission_alert_description">Ви можете ввімкнути сповіщення у налаштуваннях</string>
|
||||
<string name="push_notifications_permission_alert_negative_button">Увімкнути пізніше</string>
|
||||
<string name="push_notifications_permission_alert_positive_button">Налаштування</string>
|
||||
<string name="push_notifications_permission_alert_title">Увімкнути сповіщення</string>
|
||||
<string name="push_transactions_notifications_description">Отримуйте сповіщення про вхідні транзакції в підтримуваних мережах.</string>
|
||||
<string name="qr_scanner_camera_denied_gallery_button">Виберіть з галереї</string>
|
||||
|
|
|
|||
|
|
@ -948,6 +948,7 @@
|
|||
<string name="send_validation_invalid_total">Total amount exceeds balance</string>
|
||||
<string name="send_with_swap_confirm_title">Swap and send</string>
|
||||
<string name="send_with_swap_notification_text">Send any token, and we’ll convert it on the way. Your recipient gets exactly what they need—seamlessly.</string>
|
||||
<string name="send_with_swap_recipient_amount_success_title">Recipient will receive</string>
|
||||
<string name="send_with_swap_recipient_amount_text">Will be sent a recipient</string>
|
||||
<string name="send_with_swap_recipient_amount_title">Amount to receive</string>
|
||||
<string name="send_with_swap_title">Send with swap</string>
|
||||
|
|
@ -1427,7 +1428,7 @@
|
|||
<string name="warning_some_networks_unreachable_message">Swipe down to refresh or try again later.</string>
|
||||
<string name="warning_some_networks_unreachable_title">Some networks are unreachable</string>
|
||||
<string name="warning_some_token_balances_not_updated">Some token balances could not be updated</string>
|
||||
<string name="warning_stellar_token_trustline_not_enough_xlm">Not enough %s. Top up your XLM account to associate this token</string>
|
||||
<string name="warning_stellar_token_trustline_not_enough_xlm">Not enough %s. Top up your XLM account to open trustline.</string>
|
||||
<string name="warning_testnet_card_message">This is a Testnet card. It cannot process transactions and should only be used for testing and development purposes.</string>
|
||||
<string name="warning_testnet_card_title">For testing purposes only</string>
|
||||
<string name="warning_token_balance_not_updated">Balance may be outdated. Refresh the page.</string>
|
||||
|
|
@ -1482,7 +1483,7 @@
|
|||
<string name="wc_estimated_wallet_changes">Estimated wallet changes</string>
|
||||
<string name="wc_estimated_wallet_changes_not_simulated">The transaction couldn\'t be simulated. Please proceed with caution.</string>
|
||||
<string name="wc_malicious_transaction">Malicious transaction</string>
|
||||
<string name="wc_missing_required_network_description">Add the %s network to your profile for this wallet</string>
|
||||
<string name="wc_missing_required_network_description">Add the %s network to your portfolio for this wallet</string>
|
||||
<string name="wc_missing_required_network_title">The wallet has no required networks</string>
|
||||
<string name="wc_new_connection">New connection</string>
|
||||
<string name="wc_no_sessions_desc">Connect your wallet to a different dApps</string>
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ object StringsSigns {
|
|||
const val PERCENT = "%"
|
||||
const val THREE_STARS = "\u2217\u2217\u2217"
|
||||
const val PASSWORD_VISUAL_CHAR = '\u2022'
|
||||
const val APPROXIMATE = "≈"
|
||||
}
|
||||
|
|
@ -250,6 +250,7 @@ internal class SwapAmountModel @Inject constructor(
|
|||
.onEach { currency ->
|
||||
uiState.update { amountUM ->
|
||||
if (amountUM is SwapAmountUM.Content) {
|
||||
initPairs(currency)
|
||||
amountUM.copy(
|
||||
isPrimaryButtonEnabled = false,
|
||||
secondaryAmount = SwapAmountFieldUM.Loading(
|
||||
|
|
@ -260,7 +261,6 @@ internal class SwapAmountModel @Inject constructor(
|
|||
amountUM
|
||||
}
|
||||
}
|
||||
initPairs(currency)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
|
@ -400,6 +400,7 @@ internal class SwapAmountModel @Inject constructor(
|
|||
swapDirection = swapDirection,
|
||||
allowanceContract = quote.allowanceContract,
|
||||
isApprovalNeeded = checkAllowance(state, quote),
|
||||
fromAmount = fromAmountValue,
|
||||
).convert(
|
||||
SwapQuoteUMConverter.Data(
|
||||
quote = quote,
|
||||
|
|
|
|||
|
|
@ -12,9 +12,13 @@ import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
|||
import com.tangem.utils.extensions.isZero
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
import kotlin.math.min
|
||||
|
||||
internal object SwapAmountQuoteUtils {
|
||||
|
||||
private const val MAX_DECIMALS = 8
|
||||
private const val MIN_DECIMALS = 2
|
||||
|
||||
fun calculatePriceImpact(
|
||||
fromTokenAmount: BigDecimal,
|
||||
toTokenAmount: BigDecimal,
|
||||
|
|
@ -41,6 +45,11 @@ internal object SwapAmountQuoteUtils {
|
|||
}
|
||||
}
|
||||
|
||||
fun calculateRate(fromAmount: BigDecimal, toAmount: BigDecimal, toAmountDecimals: Int): BigDecimal {
|
||||
val rateDecimals = if (toAmountDecimals == 0) MIN_DECIMALS else toAmountDecimals
|
||||
return toAmount.divide(fromAmount, min(rateDecimals, MAX_DECIMALS), RoundingMode.HALF_UP)
|
||||
}
|
||||
|
||||
fun SwapAmountUM.updateAmount(
|
||||
onPrimaryAmount: SwapAmountFieldUM.Content.(CryptoCurrencyStatus) -> SwapAmountFieldUM,
|
||||
onSecondaryAmount: SwapAmountFieldUM.Content.(CryptoCurrencyStatus) -> SwapAmountFieldUM,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,20 @@
|
|||
package com.tangem.features.swap.v2.impl.amount.model.converter
|
||||
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import com.tangem.core.ui.extensions.annotatedReference
|
||||
import com.tangem.core.ui.extensions.appendSpace
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.anyDecimals
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapDirection
|
||||
import com.tangem.domain.swap.models.SwapQuoteModel
|
||||
import com.tangem.features.swap.v2.impl.amount.model.SwapAmountQuoteUtils.calculateRate
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM.Content.DifferencePercent
|
||||
import com.tangem.utils.StringsSigns
|
||||
import com.tangem.utils.converter.Converter
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -18,10 +24,24 @@ internal class SwapQuoteUMConverter(
|
|||
private val isApprovalNeeded: Boolean,
|
||||
private val primaryCurrency: CryptoCurrency,
|
||||
private val secondaryCurrency: CryptoCurrency,
|
||||
private val fromAmount: BigDecimal,
|
||||
) : Converter<SwapQuoteUMConverter.Data, SwapQuoteUM> {
|
||||
override fun convert(value: Data): SwapQuoteUM {
|
||||
val (quote, provider) = value
|
||||
|
||||
val rate = calculateRate(
|
||||
fromAmount = fromAmount,
|
||||
toAmount = quote.toTokenAmount,
|
||||
toAmountDecimals = secondaryCurrency.decimals,
|
||||
)
|
||||
val rateString = buildAnnotatedString {
|
||||
append(BigDecimal.ONE.format { crypto(symbol = primaryCurrency.symbol, decimals = 0).anyDecimals() })
|
||||
appendSpace()
|
||||
append(StringsSigns.APPROXIMATE)
|
||||
appendSpace()
|
||||
append(rate.format { crypto(secondaryCurrency) })
|
||||
}
|
||||
|
||||
return if (allowanceContract != null) {
|
||||
if (isApprovalNeeded) {
|
||||
SwapQuoteUM.Allowance(
|
||||
|
|
@ -36,6 +56,7 @@ internal class SwapQuoteUMConverter(
|
|||
quoteAmountValue = stringReference(
|
||||
quote.toTokenAmount.toQuoteValue(),
|
||||
),
|
||||
rate = annotatedReference(rateString),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -46,6 +67,7 @@ internal class SwapQuoteUMConverter(
|
|||
quoteAmountValue = stringReference(
|
||||
quote.toTokenAmount.toQuoteValue(),
|
||||
),
|
||||
rate = annotatedReference(rateString),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
|
@ -16,10 +18,11 @@ import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountType
|
|||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal data object SwapAmountContentPreview {
|
||||
|
||||
private val cryptoCurrencyStatus = CryptoCurrencyStatus(
|
||||
val cryptoCurrencyStatus = CryptoCurrencyStatus(
|
||||
currency = CryptoCurrency.Coin(
|
||||
id = CryptoCurrency.ID.fromValue("coin⟨BITCOIN⟩bitcoin"),
|
||||
network = Network(
|
||||
|
|
@ -41,12 +44,32 @@ internal data object SwapAmountContentPreview {
|
|||
name = "Bitcoin",
|
||||
symbol = "BTC",
|
||||
decimals = 8,
|
||||
iconUrl = "",
|
||||
iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/medium/bitcoin.png",
|
||||
isCustom = false,
|
||||
),
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
|
||||
private val provider = ExpressProvider(
|
||||
providerId = "changenow",
|
||||
rateTypes = listOf(ExpressRateType.Float),
|
||||
name = "ChangeNow",
|
||||
type = ExpressProviderType.CEX,
|
||||
imageLarge = "",
|
||||
termsOfUse = "",
|
||||
privacyPolicy = "",
|
||||
isRecommended = true,
|
||||
slippage = BigDecimal.ZERO,
|
||||
)
|
||||
|
||||
private val quote = SwapQuoteUM.Content(
|
||||
provider = provider,
|
||||
quoteAmount = "123".toBigDecimal(),
|
||||
quoteAmountValue = stringReference("123"),
|
||||
rate = stringReference("1 USD ≈ 123.123 POL"),
|
||||
diffPercent = SwapQuoteUM.Content.DifferencePercent.Best,
|
||||
)
|
||||
|
||||
val emptyState = SwapAmountUM.Content(
|
||||
isPrimaryButtonEnabled = false,
|
||||
primaryAmount = SwapAmountFieldUM.Empty(
|
||||
|
|
@ -95,7 +118,7 @@ internal data object SwapAmountContentPreview {
|
|||
selectedAmountType = SwapAmountType.From,
|
||||
swapCurrencies = SwapCurrencies.EMPTY,
|
||||
swapQuotes = persistentListOf(),
|
||||
selectedQuote = SwapQuoteUM.Empty,
|
||||
selectedQuote = quote,
|
||||
primaryCryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
secondaryCryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
swapRateType = ExpressRateType.Float,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ internal object SwapChooseProviderContentPreview {
|
|||
provider = provider1,
|
||||
quoteAmount = "123".toBigDecimal(),
|
||||
quoteAmountValue = stringReference("123"),
|
||||
rate = stringReference("1 USD ≈ 123.123 POL"),
|
||||
diffPercent = SwapQuoteUM.Content.DifferencePercent.Best,
|
||||
)
|
||||
|
||||
|
|
@ -43,6 +44,7 @@ internal object SwapChooseProviderContentPreview {
|
|||
provider = provider2,
|
||||
quoteAmount = "13.12".toBigDecimal(),
|
||||
quoteAmountValue = stringReference("13.12"),
|
||||
rate = stringReference("1 USD ≈ 12.123 POL"),
|
||||
diffPercent = SwapQuoteUM.Content.DifferencePercent.Empty,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package com.tangem.features.swap.v2.impl.common.entity
|
|||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.swap.models.SwapDataModel
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Immutable
|
||||
|
|
@ -18,6 +20,14 @@ internal sealed class ConfirmUM {
|
|||
val notifications: ImmutableList<NotificationUM>,
|
||||
) : ConfirmUM()
|
||||
|
||||
data class Success(
|
||||
override val isPrimaryButtonEnabled: Boolean = true,
|
||||
val transactionDate: Long,
|
||||
val txUrl: String,
|
||||
val swapDataModel: SwapDataModel,
|
||||
val provider: ExpressProvider,
|
||||
) : ConfirmUM()
|
||||
|
||||
data object Empty : ConfirmUM() {
|
||||
override val isPrimaryButtonEnabled: Boolean = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ internal sealed class SwapQuoteUM {
|
|||
val quoteAmount: BigDecimal,
|
||||
val quoteAmountValue: TextReference,
|
||||
val diffPercent: DifferencePercent,
|
||||
val rate: TextReference,
|
||||
) : SwapQuoteUM() {
|
||||
sealed class DifferencePercent {
|
||||
data object Empty : DifferencePercent()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
package com.tangem.features.swap.v2.impl.sendviaswap.success
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.common.ui.navigationButtons.NavigationModelCallback
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.SendWithSwapRoute
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.entity.SendWithSwapUM
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.success.model.SendWithSwapSuccessModel
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.success.ui.SendWithSwapSuccessContent
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
internal class SendWithSwapSuccessComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
params: Params,
|
||||
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: SendWithSwapSuccessModel = getOrCreateModel(params = params)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
SendWithSwapSuccessContent(sendWithSwapUM = state)
|
||||
}
|
||||
|
||||
data class Params(
|
||||
val sendWithSwapUMFlow: StateFlow<SendWithSwapUM>,
|
||||
val analyticsCategoryName: String,
|
||||
val currentRoute: Flow<SendWithSwapRoute.Success>,
|
||||
val callback: NavigationModelCallback,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.features.swap.v2.impl.sendviaswap.success.di
|
||||
|
||||
import com.tangem.core.decompose.di.ModelComponent
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.success.model.SendWithSwapSuccessModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
|
||||
@Module
|
||||
@InstallIn(ModelComponent::class)
|
||||
internal interface SendWithSwapSuccessModule {
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(SendWithSwapSuccessModel::class)
|
||||
fun bindSendWithSwapSuccessModel(impl: SendWithSwapSuccessModel): Model
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package com.tangem.features.swap.v2.impl.sendviaswap.success.model
|
||||
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButton
|
||||
import com.tangem.common.ui.navigationButtons.NavigationUM
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.common.entity.ConfirmUM
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.entity.SendWithSwapUM
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.success.SendWithSwapSuccessComponent
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
internal class SendWithSwapSuccessModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val shareManager: ShareManager,
|
||||
private val appRouter: AppRouter,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
private val params: SendWithSwapSuccessComponent.Params = paramsContainer.require()
|
||||
|
||||
val uiState: StateFlow<SendWithSwapUM> = params.sendWithSwapUMFlow
|
||||
|
||||
val confirmUM = uiState.value.confirmUM as? ConfirmUM.Success
|
||||
|
||||
init {
|
||||
configConfirmSuccessNavigation()
|
||||
}
|
||||
|
||||
private fun configConfirmSuccessNavigation() {
|
||||
params.callback.onNavigationResult(
|
||||
NavigationUM.Content(
|
||||
title = TextReference.EMPTY,
|
||||
subtitle = null,
|
||||
backIconRes = R.drawable.ic_close_24,
|
||||
backIconClick = appRouter::pop,
|
||||
primaryButton = NavigationButton(
|
||||
textReference = resourceReference(R.string.common_close),
|
||||
iconRes = null,
|
||||
isEnabled = true,
|
||||
isHapticClick = false,
|
||||
onClick = appRouter::pop,
|
||||
),
|
||||
prevButton = null,
|
||||
secondaryPairButtonsUM = NavigationButton(
|
||||
textReference = resourceReference(R.string.common_explore),
|
||||
iconRes = R.drawable.ic_web_24,
|
||||
onClick = ::onExploreClick,
|
||||
) to NavigationButton(
|
||||
textReference = resourceReference(R.string.common_share),
|
||||
iconRes = R.drawable.ic_share_24,
|
||||
onClick = ::onShareClick,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun onExploreClick() {
|
||||
if (confirmUM == null) return
|
||||
|
||||
// analyticsEventHandler.send(CommonSendAnalyticEvents.ExploreButtonClicked(params.analyticsCategoryName))
|
||||
urlOpener.openUrl(confirmUM.txUrl)
|
||||
}
|
||||
|
||||
private fun onShareClick() {
|
||||
if (confirmUM == null) return
|
||||
|
||||
// analyticsEventHandler.send(CommonSendAnalyticEvents.ShareButtonClicked(params.analyticsCategoryName))
|
||||
shareManager.shareText(confirmUM.txUrl)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,441 @@
|
|||
package com.tangem.features.swap.v2.impl.sendviaswap.success.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Text
|
||||
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.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButton
|
||||
import com.tangem.common.ui.navigationButtons.NavigationUM
|
||||
import com.tangem.core.ui.components.SecondaryButtonIconStart
|
||||
import com.tangem.core.ui.components.SpacerW12
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.icons.identicon.IdentIcon
|
||||
import com.tangem.core.ui.components.inputrow.InputRowBestRate
|
||||
import com.tangem.core.ui.components.rows.SelectorRowItem
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fee
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||
import com.tangem.core.ui.utils.singleEvent
|
||||
import com.tangem.core.ui.utils.toTimeFormat
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.swap.models.SwapDataModel
|
||||
import com.tangem.domain.swap.models.SwapDataTransactionModel
|
||||
import com.tangem.domain.utils.convertToSdkAmount
|
||||
import com.tangem.features.send.v2.api.entity.FeeExtraInfo
|
||||
import com.tangem.features.send.v2.api.entity.FeeItem
|
||||
import com.tangem.features.send.v2.api.entity.FeeNonce
|
||||
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationTextFieldUM
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationUM
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountFieldUM
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
||||
import com.tangem.features.swap.v2.impl.amount.ui.preview.SwapAmountContentPreview
|
||||
import com.tangem.features.swap.v2.impl.common.entity.ConfirmUM
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.entity.SendWithSwapUM
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
private const val GRADIENT_ALPHA = 0.3f
|
||||
|
||||
@Composable
|
||||
internal fun SendWithSwapSuccessContent(sendWithSwapUM: SendWithSwapUM) {
|
||||
if (sendWithSwapUM.navigationUM !is NavigationUM.Content) return
|
||||
|
||||
val confirmUM = sendWithSwapUM.confirmUM as? ConfirmUM.Success ?: return
|
||||
val amountUM = sendWithSwapUM.amountUM as? SwapAmountUM.Content ?: return
|
||||
val quoteUM = amountUM.selectedQuote as? SwapQuoteUM.Content ?: return
|
||||
val destinationUM = sendWithSwapUM.destinationUM as? DestinationUM.Content ?: return
|
||||
val feeSelectorUM = sendWithSwapUM.feeSelectorUM as? FeeSelectorUM.Content ?: return
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
TransactionDoneTitle(
|
||||
title = resourceReference(R.string.sent_transaction_sent_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.send_date_format,
|
||||
formatArgs = wrappedList(
|
||||
confirmUM.transactionDate.toTimeFormat(DateTimeFormatters.dateFormatter),
|
||||
confirmUM.transactionDate.toTimeFormat(),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.padding(vertical = 12.dp),
|
||||
)
|
||||
SwapAmountBlock(amountUM = amountUM)
|
||||
InputRowBestRate(
|
||||
imageUrl = confirmUM.provider.imageLarge,
|
||||
title = stringReference(confirmUM.provider.name),
|
||||
titleExtra = stringReference(confirmUM.provider.type.typeName),
|
||||
subtitle = quoteUM.rate,
|
||||
modifier = Modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action),
|
||||
)
|
||||
DestinationBlock(destinationUM.addressTextField)
|
||||
FeeBlock(feeSelectorUM = feeSelectorUM)
|
||||
Spacer(Modifier.height(60.dp))
|
||||
}
|
||||
DoneButtons(
|
||||
pairButtonsUM = sendWithSwapUM.navigationUM.secondaryPairButtonsUM,
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.background(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
Color.Transparent,
|
||||
TangemTheme.colors.background.tertiary.copy(GRADIENT_ALPHA),
|
||||
TangemTheme.colors.background.tertiary,
|
||||
),
|
||||
),
|
||||
)
|
||||
.padding(top = 24.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SwapAmountBlock(amountUM: SwapAmountUM.Content) {
|
||||
AmountBlock(
|
||||
title = resourceReference(
|
||||
id = R.string.send_from_wallet_name,
|
||||
formatArgs = wrappedList(
|
||||
(amountUM.primaryAmount.amountField as? AmountState.Data)?.title
|
||||
?: TextReference.EMPTY,
|
||||
),
|
||||
),
|
||||
amountFieldUM = amountUM.primaryAmount,
|
||||
)
|
||||
AmountBlock(
|
||||
title = resourceReference(R.string.send_with_swap_recipient_amount_success_title),
|
||||
amountFieldUM = amountUM.secondaryAmount,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AmountBlock(title: TextReference, amountFieldUM: SwapAmountFieldUM, modifier: Modifier = Modifier) {
|
||||
val amountFieldData = amountFieldUM.amountField as? AmountState.Data ?: return
|
||||
val cryptoAmount = amountFieldData.amountTextField.cryptoAmount
|
||||
val fiatAmount = amountFieldData.amountTextField.fiatAmount
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.padding(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = title.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp),
|
||||
) {
|
||||
CurrencyIcon(
|
||||
state = amountFieldData.tokenIconState,
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
Text(
|
||||
text = cryptoAmount.value?.format {
|
||||
crypto(
|
||||
symbol = cryptoAmount.currencySymbol,
|
||||
decimals = cryptoAmount.decimals,
|
||||
)
|
||||
}.orEmpty(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
Text(
|
||||
text = fiatAmount.value.format {
|
||||
fiat(
|
||||
fiatCurrencyCode = amountFieldData.appCurrency.code,
|
||||
fiatCurrencySymbol = amountFieldData.appCurrency.symbol,
|
||||
)
|
||||
},
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FeeBlock(feeSelectorUM: FeeSelectorUM.Content) {
|
||||
val feeExtraInfo = feeSelectorUM.feeExtraInfo
|
||||
val feeFiatRateUM = feeSelectorUM.feeFiatRateUM
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(com.tangem.common.ui.R.string.common_network_fee_title),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
|
||||
Box(modifier = Modifier.padding(top = TangemTheme.dimens.spacing8)) {
|
||||
val feeAmount = feeSelectorUM.selectedFeeItem.fee.amount
|
||||
SelectorRowItem(
|
||||
titleRes = com.tangem.common.ui.R.string.common_fee_selector_option_market,
|
||||
iconRes = com.tangem.common.ui.R.drawable.ic_bird_24,
|
||||
preDot = stringReference(
|
||||
feeAmount.value.format {
|
||||
crypto(
|
||||
symbol = feeAmount.currencySymbol,
|
||||
decimals = feeAmount.decimals,
|
||||
).fee(canBeLower = feeExtraInfo.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (feeExtraInfo.isFeeConvertibleToFiat && feeFiatRateUM != null) {
|
||||
getFiatReference(feeAmount.value, feeFiatRateUM.rate, feeFiatRateUM.appCurrency)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = feeAmount.currencySymbol.length,
|
||||
isSelected = true,
|
||||
showDivider = false,
|
||||
showSelectedAppearance = false,
|
||||
paddingValues = PaddingValues(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DestinationBlock(address: DestinationTextFieldUM.RecipientAddress, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.padding(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.send_recipient),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = address.value,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
IdentIcon(
|
||||
address = address.value,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size36)
|
||||
.clip(RoundedCornerShape(18.dp))
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO remove [REDACTED_TASK_KEY]
|
||||
@Composable
|
||||
private fun DoneButtons(pairButtonsUM: Pair<NavigationButton, NavigationButton>?, modifier: Modifier = Modifier) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = pairButtonsUM != null,
|
||||
modifier = modifier,
|
||||
enter = slideInVertically().plus(fadeIn()),
|
||||
exit = slideOutVertically().plus(fadeOut()),
|
||||
label = "Animate show sent state buttons",
|
||||
) {
|
||||
val (leftButton, rightButton) = remember(this) { requireNotNull(pairButtonsUM) }
|
||||
Row {
|
||||
SecondaryButtonIconStart(
|
||||
text = leftButton.textReference.resolveReference(),
|
||||
iconResId = requireNotNull(leftButton.iconRes),
|
||||
onClick = {
|
||||
singleEvent {
|
||||
leftButton.onClick()
|
||||
}
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
SpacerW12()
|
||||
SecondaryButtonIconStart(
|
||||
text = rightButton.textReference.resolveReference(),
|
||||
iconResId = requireNotNull(rightButton.iconRes),
|
||||
onClick = {
|
||||
singleEvent {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
rightButton.onClick()
|
||||
}
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360, heightDp = 720)
|
||||
@Preview(showBackground = true, widthDp = 360, heightDp = 720, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun SendWithSwapSuccessContent_Preview() {
|
||||
TangemThemePreview {
|
||||
SendWithSwapSuccessContent(
|
||||
sendWithSwapUM = SendWithSwapUM(
|
||||
amountUM = SwapAmountContentPreview.defaultState,
|
||||
destinationUM = DestinationUM.Content(
|
||||
isPrimaryButtonEnabled = false,
|
||||
addressTextField = DestinationTextFieldUM.RecipientAddress(
|
||||
value = "0x391316d97a07027a0702c8A002c8A0C25d8470",
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
placeholder = TextReference.EMPTY,
|
||||
label = resourceReference(R.string.send_recipient),
|
||||
isError = false,
|
||||
error = null,
|
||||
isValuePasted = false,
|
||||
blockchainAddress = "0x391316d97a07027a0702c8A002c8A0C25d8470",
|
||||
),
|
||||
memoTextField = null,
|
||||
recent = persistentListOf(),
|
||||
wallets = persistentListOf(),
|
||||
networkName = "Polygon",
|
||||
isValidating = false,
|
||||
isInitialized = false,
|
||||
isRedesignEnabled = false,
|
||||
),
|
||||
feeSelectorUM = FeeSelectorUM.Content(
|
||||
fees = TransactionFee.Single(
|
||||
normal = Fee.Common(
|
||||
BigDecimal.ONE.convertToSdkAmount(
|
||||
SwapAmountContentPreview.cryptoCurrencyStatus.currency,
|
||||
),
|
||||
),
|
||||
),
|
||||
feeItems = persistentListOf(),
|
||||
selectedFeeItem = FeeItem.Market(
|
||||
Fee.Common(
|
||||
BigDecimal.ONE.convertToSdkAmount(
|
||||
SwapAmountContentPreview.cryptoCurrencyStatus.currency,
|
||||
),
|
||||
),
|
||||
),
|
||||
feeExtraInfo = FeeExtraInfo(
|
||||
isFeeApproximate = false,
|
||||
isFeeConvertibleToFiat = false,
|
||||
isTronToken = false,
|
||||
),
|
||||
feeFiatRateUM = null,
|
||||
feeNonce = FeeNonce.None,
|
||||
),
|
||||
confirmUM = ConfirmUM.Success(
|
||||
isPrimaryButtonEnabled = true,
|
||||
transactionDate = 8960,
|
||||
txUrl = "https://tangem.com",
|
||||
provider = ExpressProvider(
|
||||
providerId = "changelly",
|
||||
rateTypes = listOf(),
|
||||
name = "Changelly",
|
||||
type = ExpressProviderType.CEX,
|
||||
imageLarge = "https://s3.eu-central-1.amazonaws.com/tangem.api/express/changelly-1024.png",
|
||||
termsOfUse = "",
|
||||
privacyPolicy = "",
|
||||
isRecommended = false,
|
||||
slippage = null,
|
||||
),
|
||||
swapDataModel = SwapDataModel(
|
||||
toTokenAmount = BigDecimal.TEN,
|
||||
transaction = SwapDataTransactionModel.CEX(
|
||||
fromAmount = BigDecimal.TEN,
|
||||
toAmount = BigDecimal.TEN,
|
||||
txValue = "cetero",
|
||||
txId = "oporteat",
|
||||
txTo = "graecis",
|
||||
txExtraId = "expetendis",
|
||||
externalTxId = "atomorum",
|
||||
externalTxUrl = "https://tangem.com",
|
||||
txExtraIdName = "Jeffry Blackwell",
|
||||
),
|
||||
),
|
||||
),
|
||||
navigationUM = NavigationUM.Content(
|
||||
title = TextReference.EMPTY,
|
||||
subtitle = null,
|
||||
backIconRes = R.drawable.ic_close_24,
|
||||
backIconClick = {},
|
||||
additionalIconRes = null,
|
||||
additionalIconClick = null,
|
||||
primaryButton = NavigationButton(
|
||||
textReference = resourceReference(R.string.common_close),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
secondaryPairButtonsUM = NavigationButton(
|
||||
textReference = resourceReference(R.string.common_explore),
|
||||
iconRes = R.drawable.ic_web_24,
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
) to NavigationButton(
|
||||
textReference = resourceReference(R.string.common_share),
|
||||
iconRes = R.drawable.ic_share_24,
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
Loading…
Add table
Add a link
Reference in a new issue