Updated on 2026-08-14

This commit is contained in:
Tangem 2023-06-29 13:33:17 +03:00
commit 2822193ff8
156 changed files with 4469 additions and 3234 deletions

View file

@ -0,0 +1,29 @@
package com.tangem.datasource.api.promotion
import com.tangem.datasource.api.promotion.models.*
import retrofit2.http.*
/**
*
* Promotion API
* @see <a href = "https://www.notion.so/tangem/Promotion-Program-API-0907159c3fdb4975aac761be632f44da">Documentation<a/>
[REDACTED_AUTHOR]
*/
interface PromotionApi {
@Headers("Cache-Control: max-age=3600")
@GET("promotion")
suspend fun getPromotionInfo(@Query("programName") name: String): PromotionInfoResponse
@POST("promotion/code/validate")
suspend fun validateCode(@Body request: CodeValidateRequestBody): CodeValidateResponse
@POST("promotion/code/award")
suspend fun requestAwardByCode(@Body request: CodeAwardRequestBody): CodeAwardResponse
@POST("promotion/validate")
suspend fun validate(@Body request: ValidateRequestBody): ValidateResponse
@POST("promotion/award")
suspend fun requestAward(@Body request: AwardRequestBody): AwardResponse
}

View file

@ -0,0 +1,18 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
abstract class AbstractPromotionResponse {
abstract val error: Error?
fun isError(): Boolean = error != null
data class Error(
@Json(name = "code") val code: Int,
@Json(name = "message") val message: String,
)
}

View file

@ -0,0 +1,12 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class AwardRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "address") val address: String,
@Json(name = "programName") val programName: String,
)

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class AwardResponse(
@Json(name = "status") val status: Boolean?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse()

View file

@ -0,0 +1,12 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class CodeAwardRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "address") val address: String,
@Json(name = "code") val code: String?,
)

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class CodeAwardResponse(
@Json(name = "status") val status: Boolean?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse()

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class CodeValidateRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "code") val code: String?,
)

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class CodeValidateResponse(
@Json(name = "valid") val valid: Boolean?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse()

View file

@ -0,0 +1,40 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class PromotionInfoResponse(
@Json(name = "newCard") val newCard: Data?,
@Json(name = "oldCard") val oldCard: Data?,
@Json(name = "awardPaymentToken") val awardPaymentToken: TokenData?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse() {
data class Data(
@Json(name = "status") val status: Status,
@Json(name = "award") val award: Double,
)
enum class Status(val value: String) {
@Json(name = "pending")
PENDING("pending"),
@Json(name = "active")
ACTIVE("active"),
@Json(name = "finished")
FINISHED("finished"),
}
data class TokenData(
@Json(name = "id") val id: String,
@Json(name = "name") val name: String,
@Json(name = "symbol") val symbol: String,
@Json(name = "active") val active: Boolean,
@Json(name = "networkId") val networkId: String,
@Json(name = "contractAddress") val contractAddress: String,
@Json(name = "decimalCount") val decimalCount: Int,
)
}

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class ValidateRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "programName") val programName: String,
)

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class ValidateResponse(
@Json(name = "valid") val valid: Boolean?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse()

View file

@ -17,7 +17,6 @@ interface ConfigManager {
fun resetToDefault(name: String)
companion object {
const val IS_SENDING_TO_PAY_ID_ENABLED = "isSendingToPayIdEnabled"
const val IS_CREATING_TWIN_CARDS_ALLOWED = "isCreatingTwinCardsAllowed"
const val IS_TOP_UP_ENABLED = "isTopUpEnabled"
}

View file

@ -1,13 +1,7 @@
package com.tangem.datasource.config
import com.tangem.blockchain.common.BlockchainSdkConfig
import com.tangem.blockchain.common.BlockchairCredentials
import com.tangem.blockchain.common.GetBlockCredentials
import com.tangem.blockchain.common.NowNodeCredentials
import com.tangem.blockchain.common.QuickNodeCredentials
import com.tangem.blockchain.common.TonCenterCredentials
import com.tangem.blockchain.common.*
import com.tangem.datasource.config.ConfigManager.Companion.IS_CREATING_TWIN_CARDS_ALLOWED
import com.tangem.datasource.config.ConfigManager.Companion.IS_SENDING_TO_PAY_ID_ENABLED
import com.tangem.datasource.config.ConfigManager.Companion.IS_TOP_UP_ENABLED
import com.tangem.datasource.config.models.Config
import com.tangem.datasource.config.models.ConfigModel
@ -34,7 +28,6 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
override fun turnOff(name: String) {
when (name) {
IS_SENDING_TO_PAY_ID_ENABLED -> config = config.copy(isSendingToPayIdEnabled = false)
IS_TOP_UP_ENABLED -> config = config.copy(isTopUpEnabled = false)
IS_CREATING_TWIN_CARDS_ALLOWED -> config = config.copy(isCreatingTwinCardsAllowed = false)
}
@ -42,13 +35,13 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
override fun resetToDefault(name: String) {
when (name) {
IS_SENDING_TO_PAY_ID_ENABLED ->
config =
config.copy(isSendingToPayIdEnabled = defaultConfig.isSendingToPayIdEnabled)
IS_TOP_UP_ENABLED -> config = config.copy(isTopUpEnabled = defaultConfig.isTopUpEnabled)
IS_CREATING_TWIN_CARDS_ALLOWED ->
config =
config.copy(isCreatingTwinCardsAllowed = defaultConfig.isCreatingTwinCardsAllowed)
IS_TOP_UP_ENABLED -> {
config = config.copy(isTopUpEnabled = defaultConfig.isTopUpEnabled)
}
IS_CREATING_TWIN_CARDS_ALLOWED -> {
config = config.copy(isCreatingTwinCardsAllowed = defaultConfig.isCreatingTwinCardsAllowed)
}
else -> Unit
}
}
@ -57,12 +50,11 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
config = config.copy(
isTopUpEnabled = model.isTopUpEnabled,
isSendingToPayIdEnabled = model.isSendingToPayIdEnabled,
isCreatingTwinCardsAllowed = model.isCreatingTwinCardsAllowed,
)
defaultConfig = defaultConfig.copy(
isTopUpEnabled = model.isTopUpEnabled,
isSendingToPayIdEnabled = model.isSendingToPayIdEnabled,
isCreatingTwinCardsAllowed = model.isCreatingTwinCardsAllowed,
)
}
@ -111,6 +103,7 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
zendesk = configValues.zendesk,
swapReferrerAccount = configValues.swapReferrerAccount,
walletConnectProjectId = configValues.walletConnectProjectId,
tangemComAuthorization = configValues.tangemComAuthorization,
)
}
}

View file

@ -11,7 +11,6 @@ data class Config(
val appsFlyerDevKey: String = "",
val amplitudeApiKey: String = "",
val blockchainSdkConfig: BlockchainSdkConfig = BlockchainSdkConfig(),
val isSendingToPayIdEnabled: Boolean = true,
val isTopUpEnabled: Boolean = false,
@Deprecated("Not relevant since version 3.23")
val isCreatingTwinCardsAllowed: Boolean = false,
@ -19,4 +18,5 @@ data class Config(
val zendesk: ZendeskConfig? = null,
val swapReferrerAccount: SwapReferrerAccount? = null,
val walletConnectProjectId: String = "",
val tangemComAuthorization: String? = null,
)

View file

@ -8,7 +8,6 @@ import com.squareup.moshi.Json
class FeatureModel(
val isTopUpEnabled: Boolean,
val isSendingToPayIdEnabled: Boolean,
val isCreatingTwinCardsAllowed: Boolean,
)
@ -38,6 +37,7 @@ class ConfigValueModel(
val swapReferrerAccount: SwapReferrerAccount?,
val kaspaSecondaryApiUrl: String,
val walletConnectProjectId: String,
val tangemComAuthorization: String?,
)
data class AppsFlyer(

View file

@ -2,10 +2,13 @@ package com.tangem.datasource.di
import com.squareup.moshi.Moshi
import com.tangem.datasource.api.paymentology.PaymentologyApi
import com.tangem.datasource.api.promotion.PromotionApi
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.utils.RequestHeader.*
import com.tangem.datasource.utils.addHeaders
import com.tangem.datasource.utils.allowLogging
import com.tangem.lib.auth.AuthProvider
import com.tangem.lib.auth.BuildConfig
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -13,6 +16,7 @@ import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
@Module
@ -54,10 +58,37 @@ class NetworkModule {
.create(PaymentologyApi::class.java)
}
@Provides
@Singleton
@PromotionOneInch
fun providePromotionOneInchApi(authProvider: AuthProvider, @NetworkMoshi moshi: Moshi): PromotionApi {
val okClient = OkHttpClient.Builder()
.addHeaders(
AuthenticationHeader(authProvider),
)
.allowLogging()
.callTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.connectTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.readTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.writeTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.build()
return createBasePromotionRetrofit(okClient, moshi)
}
private fun createBasePromotionRetrofit(okHttpClient: OkHttpClient, moshi: Moshi): PromotionApi {
return Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(if (BuildConfig.DEBUG) DEV_TANGEM_TECH_BASE_URL else PROD_TANGEM_TECH_BASE_URL)
.client(okHttpClient)
.build()
.create(PromotionApi::class.java)
}
private companion object {
const val PROD_TANGEM_TECH_BASE_URL = "https://api.tangem-tech.com/v1/"
const val DEV_TANGEM_TECH_BASE_URL = "https://devapi.tangem-tech.com/v1/"
private const val PAYMENTOLOGY_BASE_URL: String = "https://paymentologygate.oa.r.appspot.com/"
const val PAYMENTOLOGY_BASE_URL: String = "https://paymentologygate.oa.r.appspot.com/"
const val API_ONE_INCH_TIMEOUT_MS = 5000L
}
}

View file

@ -0,0 +1,8 @@
package com.tangem.datasource.di
import javax.inject.Qualifier
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class PromotionOneInch

View file

@ -13,7 +13,7 @@ internal fun OkHttpClient.Builder.addHeaders(vararg requestHeaders: RequestHeade
val request = chain.request().newBuilder().apply {
requestHeaders
.flatMap(RequestHeader::values)
.forEach { addHeader(it.first, it.second) }
.forEach { addHeader(it.first, it.second.invoke()) }
}.build()
chain.proceed(request)

View file

@ -7,15 +7,15 @@ import com.tangem.lib.auth.AuthProvider
*
* @param pairs header name and header value pairs
*/
sealed class RequestHeader(vararg pairs: Pair<String, String>) {
sealed class RequestHeader(vararg pairs: Pair<String, () -> String>) {
/** Header list */
val values: List<Pair<String, String>> = pairs.toList()
val values: List<Pair<String, () -> String>> = pairs.toList()
object CacheControlHeader : RequestHeader("Cache-Control" to "max-age=600")
object CacheControlHeader : RequestHeader("Cache-Control" to { "max-age=600" })
class AuthenticationHeader(authProvider: AuthProvider) : RequestHeader(
"card_public_key" to authProvider.getCardPublicKey(),
"card_id" to authProvider.getCardId(),
"card_id" to { authProvider.getCardId() },
"card_public_key" to { authProvider.getCardPublicKey() },
)
}

View file

@ -12,6 +12,7 @@
<string name="common_done">Erledigt</string>
<string name="common_ok">OK</string>
<string name="common_save_changes">Änderungen speichern</string>
<string name="common_send">Absenden</string>
<string name="common_success">Erfolg</string>
<string name="details_manage_security_access_code">Zugangscode</string>
<string name="details_manage_security_access_code_description">Sie müssen den richtigen Zugangscode eingeben, bevor Sie die Karte scannen.</string>
@ -34,11 +35,7 @@
<string name="main_processing_full_amount">Der Betrag enthält nicht einige Ihrer Mittel</string>
<string name="send_amount_label">Betrag</string>
<string name="send_destination_hint_address">Adresse</string>
<string name="send_destination_hint_address_payid">Adresse oder PayString</string>
<string name="send_error_address_same_as_wallet">Die Adresse stimmt mit der Adresse Ihrer Brieftasche überein</string>
<string name="send_error_payid_not_registered">PayString ist nicht registriert</string>
<string name="send_error_payid_request_failed">PayString-Anfrage ist fehlgeschlagen</string>
<string name="send_error_payid_unsupported_by_blockchain">PayString wird von der Blockchain nicht unterstützt</string>
<string name="send_extras_hint_destination_tag">Tag</string>
<string name="send_extras_hint_memo">Memo</string>
<string name="send_fee_include_description">inkl. Gebühr</string>
@ -48,7 +45,6 @@
<string name="send_fee_picker_priority">Priorität</string>
<string name="send_max_amount_label">Höchstbetrag</string>
<string name="send_network_fee_title">Netzgebühr</string>
<string name="send_title">Absenden</string>
<string name="send_total_label">Gesamt</string>
<string name="send_total_subtitle_asset_format">%1$s und %2$s werden gesendet</string>
<string name="send_total_subtitle_fiat_format">≈ %1$s (inkl. Gebühr: %2$s)</string>
@ -57,11 +53,9 @@
<string name="send_validation_invalid_address">Ungültige Adresse</string>
<string name="shop_one_wallet">Tangem Wallet</string>
<string name="twins_recreate_toolbar">Tangem Twin</string>
<string name="wallet_address_button_create_payid">PayString erstellen</string>
<string name="wallet_balance_loading">Die Bilanz wird aufgeladen…</string>
<string name="wallet_balance_tx_in_progress">Die Transaktion läuft…</string>
<string name="wallet_balance_verified">Verifizierte Bilanz</string>
<string name="wallet_button_send">Absenden</string>
<string name="wallet_connect_title">WalletConnect</string>
<string name="wallet_error_no_account">Das Konto ist nicht erstellt</string>
<string name="wallet_error_unsupported_blockchain">Diese Karte wird nicht unterstützt</string>

View file

@ -12,6 +12,7 @@
<string name="common_done">Exécuté</string>
<string name="common_ok">OK</string>
<string name="common_save_changes">Sauvegarder les modifications</string>
<string name="common_send">Envoyer</string>
<string name="common_success">Avec succès</string>
<string name="details_manage_security_access_code">Code d\'accès</string>
<string name="details_manage_security_access_code_description">Vous devrez entrer le mot de passe correct avant de scanner la carte</string>
@ -34,11 +35,7 @@
<string name="main_processing_full_amount">Le montant n\'inclut pas certains de vos fonds</string>
<string name="send_amount_label">Somme</string>
<string name="send_destination_hint_address">Adresse</string>
<string name="send_destination_hint_address_payid">Adresse ou PayString</string>
<string name="send_error_address_same_as_wallet">L\'adresse est la même que celle de votre portefeuille</string>
<string name="send_error_payid_not_registered">PayString non enregistré</string>
<string name="send_error_payid_request_failed">La demande de PayString a échoué</string>
<string name="send_error_payid_unsupported_by_blockchain">PayString non pris en charge par la blockchain</string>
<string name="send_extras_hint_destination_tag">Tag</string>
<string name="send_extras_hint_memo">Memo</string>
<string name="send_fee_include_description">Inclure les commissions</string>
@ -48,7 +45,6 @@
<string name="send_fee_picker_priority">Priorité</string>
<string name="send_max_amount_label">Somme maximale</string>
<string name="send_network_fee_title">Commissions du réseau</string>
<string name="send_title">Envoyer</string>
<string name="send_total_label">Total</string>
<string name="send_total_subtitle_asset_format">Sera envoyé %1$s et %2$s</string>
<string name="send_total_subtitle_fiat_format">≈ %1$s (incl. les commissions : %2$s)</string>
@ -57,11 +53,9 @@
<string name="send_validation_invalid_address">Adresse incorrecte</string>
<string name="shop_one_wallet">Tangem Wallet</string>
<string name="twins_recreate_toolbar">Tangem Twin</string>
<string name="wallet_address_button_create_payid">Créer PayString</string>
<string name="wallet_balance_loading">Solde est en cours de téléchargement…</string>
<string name="wallet_balance_tx_in_progress">Transaction en cours…</string>
<string name="wallet_balance_verified">Solde confirmé</string>
<string name="wallet_button_send">Envoyer</string>
<string name="wallet_connect_title">WalletConnect</string>
<string name="wallet_error_no_account">Compte n\'est pas créé</string>
<string name="wallet_error_unsupported_blockchain">Cette carte n\'est pas prise en charge</string>

View file

@ -12,6 +12,7 @@
<string name="common_done">Fatto</string>
<string name="common_ok">OK</string>
<string name="common_save_changes">Mantieni le modifiche</string>
<string name="common_send">Invia</string>
<string name="common_success">Con successo</string>
<string name="details_manage_security_access_code">Codice di accesso</string>
<string name="details_manage_security_access_code_description">Prima di scansionare la carta sarà necessario inserire il codice di accesso corretto</string>
@ -34,11 +35,7 @@
<string name="main_processing_full_amount">L\'importo non include alcuni dei tuoi fondi</string>
<string name="send_amount_label">Importo</string>
<string name="send_destination_hint_address">Indirizzo</string>
<string name="send_destination_hint_address_payid">Indirizzo o PayString</string>
<string name="send_error_address_same_as_wallet">L\'indirizzo corrisponde all\'indirizzo del tuo portafoglio</string>
<string name="send_error_payid_not_registered">PayString non registrato</string>
<string name="send_error_payid_request_failed">Richiesta PayString fallita</string>
<string name="send_error_payid_unsupported_by_blockchain">PayString non supportato dalla blockchain</string>
<string name="send_extras_hint_destination_tag">Tag</string>
<string name="send_extras_hint_memo">Memo</string>
<string name="send_fee_include_description">Includi commissione</string>
@ -48,7 +45,6 @@
<string name="send_fee_picker_priority">Prioritario</string>
<string name="send_max_amount_label">Importo totale</string>
<string name="send_network_fee_title">Costi della rete</string>
<string name="send_title">Invia</string>
<string name="send_total_label">Totale</string>
<string name="send_total_subtitle_asset_format">Sarà inviato %1$s e %2$s</string>
<string name="send_total_subtitle_fiat_format">≈ %1$s (inc. commissione: %2$s)</string>
@ -57,11 +53,9 @@
<string name="send_validation_invalid_address">Indirizzo non valido</string>
<string name="shop_one_wallet">Tangem Wallet</string>
<string name="twins_recreate_toolbar">Tangem Twin</string>
<string name="wallet_address_button_create_payid">Crea PayString</string>
<string name="wallet_balance_loading">Il saldo sta per essere caricato…</string>
<string name="wallet_balance_tx_in_progress">Transazione in corso…</string>
<string name="wallet_balance_verified">Saldo verificato</string>
<string name="wallet_button_send">Invia</string>
<string name="wallet_connect_title">WalletConnect</string>
<string name="wallet_error_no_account">Conto non creato</string>
<string name="wallet_error_unsupported_blockchain">Questa carta non è supportata</string>

View file

@ -15,7 +15,7 @@
<string name="alert_signed_hashes_message">Эта карта не является платежным средством. В настоящее время мы не можем сопоставить количество подписей на карте с информацией в блокчейне. Это нормально, но в редких случаях может означать, что предыдущий владелец удерживает подписанную транзакцию от публикации, что является поводом для беспокойства.\nНе принимайте эту карту в качестве физического платежа от кого-то, кому вы не доверяете.\nВо всех остальных отношениях эта карта совершенно безопасна.\nTangem — единственный аппаратный кошелек, предлагающий защиту методом подсчета подписей.</string>
<string name="alert_troubleshooting_scan_card_title">У вас возникли трудности со сканированием карты?</string>
<string name="alert_unsupported_card">Эта карта не предназначена для работы с этим приложением</string>
<string name="app_settings_enable_biometrics_description">Перейдите в настройки, чтобы включить биометрическую аутентификацию в приложении Tangem App</string>
<string name="app_settings_enable_biometrics_description">Перейдите в настройки, чтобы включить биометрическую аутентификацию в приложении Tangem</string>
<string name="app_settings_enable_biometrics_title">Включите биометрическую аутентификацию</string>
<string name="app_settings_off_saved_access_code_alert_message">Все сохраненные коды доступа будут удалены. Вам потребуется вводить код доступа при работе с кошельком.</string>
<string name="app_settings_off_saved_wallet_alert_message">При отключении функции сохранения кошелька все ранее сохраненные кошельки будут удалены из приложения.</string>
@ -39,7 +39,7 @@
<string name="card_settings_access_code_recovery_title">Восстановление кода доступа</string>
<string name="card_settings_change_access_code">Смена кода доступа</string>
<string name="card_settings_change_access_code_footer">Код доступа будет изменен только на данной карте</string>
<string name="card_settings_reset_card_to_factory">Сброс к заводским настройкам</string>
<string name="card_settings_reset_card_to_factory">Заводские настройки</string>
<string name="card_settings_security_mode">Тип безопасности</string>
<string name="card_settings_title">Настройки карты</string>
<string name="chat_bot_name">Tangem Bot</string>
@ -52,27 +52,41 @@
<string name="common_balance">Баланс: %s</string>
<string name="common_biometric_authentication">биометрическую аутентификацию</string>
<string name="common_biometrics">биометрией</string>
<string name="common_buy">Купить</string>
<string name="common_camera_denied_alert_message">Вы не предоставили доступ к камере, пожалуйста, измените настройки конфиденциальности.</string>
<string name="common_cancel">Отмена</string>
<string name="common_close">Закрыть</string>
<string name="common_copy">Копировать</string>
<string name="common_copy_address">Скопировать адрес</string>
<string name="common_create">Создать</string>
<string name="common_delete">Удалить</string>
<string name="common_disabled">Отключено</string>
<string name="common_dislike">Не нравится</string>
<string name="common_done">Готово</string>
<string name="common_enable">Включить</string>
<string name="common_enabled">Включено</string>
<string name="common_exchange">Обменять</string>
<string name="common_explore_transaction_history">Посмотреть историю транзакций</string>
<string name="common_explorer">Обозреватель</string>
<string name="common_like">Нравится</string>
<string name="common_main_network">Основная сеть</string>
<string name="common_no">Нет</string>
<string name="common_ok">Ок</string>
<string name="common_no_data">Нет данных</string>
<string name="common_ok">OK</string>
<string name="common_origin_card">Основная карта</string>
<string name="common_receive">Получить</string>
<string name="common_reject">Отклонить</string>
<string name="common_reload">Перезагрузить</string>
<string name="common_save_changes">Сохранить изменения</string>
<string name="common_search">Искать</string>
<string name="common_seed_phrase">Секретная фраза</string>
<string name="common_sell">Продать</string>
<string name="common_send">Отправить</string>
<string name="common_server_unavailable">Сервер недоступен, повторите попытку позднее</string>
<string name="common_share">Поделиться</string>
<string name="common_sign">Подписать</string>
<string name="common_sign_and_send">Подписать и отправить</string>
<string name="common_stake">Стейкинг</string>
<string name="common_start">Начать</string>
<string name="common_submit">Отправить</string>
<string name="common_success">Успешно</string>
@ -81,6 +95,7 @@
<string name="common_transactions">Транзакции</string>
<string name="common_transfer">Перевод</string>
<string name="common_understand">Я понял</string>
<string name="common_unreachable">Недоступно</string>
<string name="common_yes">Да</string>
<string name="contract_address_copied_message">Адрес контракта скопирован!</string>
<string name="currency_subtitle_expanded">Доступные сети</string>
@ -145,11 +160,22 @@
<string name="initial_message_tap_header">Приложите карту</string>
<string name="internal_error_wallet_manager_not_found">Внутренняя ошибка: не удается найти менеджер кошельков</string>
<string name="key_invalidated_warning_description">Вы обновили данные биометрии, отсканируйте свою карту для входа</string>
<string name="main_get_bonus_subtitle">Вы завершили обучение и можете получить свои токены 1inch</string>
<string name="main_get_bonus_title">Получите бонус</string>
<plurals name="main_learn_subtitle">
<item quantity="one">Пройдите обучение и получите %d токен 1inch на свой кошелек</item>
<item quantity="few">Пройдите обучение и получите %d токена 1inch на свой кошелек</item>
<item quantity="many">Пройдите обучение и получите %d токена 1inch на свой кошелек</item>
<item quantity="other">Пройдите обучение и получите %d токенов 1inch на свой кошелек</item>
</plurals>
<string name="main_learn_title">Бонус за обучение</string>
<string name="main_manage_tokens">Управление токенами</string>
<string name="main_no_backup_warning_subtitle">Чтобы защитить свои активы, мы советуем вам выполнить эту процедуру</string>
<string name="main_no_backup_warning_title">Бэкап кошелька не был произведен</string>
<string name="main_page_balance">Баланс</string>
<string name="main_processing_full_amount">В сумме учтены не все монеты</string>
<string name="main_promotion_credited">Токены 1inch будут зачислены на адрес вашего кошелька в течение 2 дней</string>
<string name="main_promotion_no_purchase">По вашему промокоду не было покупки кошелька, а значит вы не можете получить бонус. Купите кошелек Tangem, отсканируйте его в приложении и получите бонус.</string>
<string name="main_scan_card_warning_view_subtitle">Чтобы получить доступ ко всем сетям, вам необходимо отсканировать карту</string>
<string name="main_scan_card_warning_view_title">Отсканируйте карту</string>
<string name="onboarding_access_code_feature_1_description">Вам необходимо установить единый код доступа для защиты всех ваших карт</string>
@ -173,11 +199,8 @@
<string name="onboarding_button_claim">Запросить</string>
<string name="onboarding_button_continue_wallet">Перейти к моему кошельку</string>
<string name="onboarding_button_finalize_backup">Завершение бэкапа</string>
<string name="onboarding_button_kyc_start">Верифицировать (Utorg)</string>
<string name="onboarding_button_kyc_waiting">Обновить</string>
<string name="onboarding_button_pin">Установить Код доступа</string>
<string name="onboarding_button_receive_crypto">Получить криптовалюту</string>
<string name="onboarding_button_register_wallet">Зарегистрироваться</string>
<string name="onboarding_button_scan_origin_card">Сканировать основную карту</string>
<string name="onboarding_button_skip_backup">Пропустить</string>
<string name="onboarding_button_what_does_it_mean">Как это работает?</string>
@ -192,19 +215,9 @@
<string name="onboarding_exit_alert_message">В этом случае вам будет необходимо начать процесс заново.</string>
<string name="onboarding_exit_alert_title">Вы хотите выйти из процесса активации?</string>
<string name="onboarding_getting_started">Подготовка</string>
<string name="onboarding_linking_error_card_with_wallets">Другой кошелек уже был создан на карте, которую вы пытаетесь добавить. Хотите сбросить его и использовать карту для бэкапа?</string>
<string name="onboarding_navbar_kyc_progress">Подтвердите свою личность</string>
<string name="onboarding_navbar_kyc_start">Верификация клиента</string>
<string name="onboarding_navbar_pin">Код доступа</string>
<string name="onboarding_navbar_register_wallet">Подключиться</string>
<string name="onboarding_navbar_title_creating_backup">Резервная копия</string>
<string name="onboarding_saltpay_button_backup_origin">Приложите SaltPay карту</string>
<string name="onboarding_saltpay_subtitle_no_backup_cards">Для начала процесса бэкапа вам необходимо добавить Tangem карту</string>
<string name="onboarding_saltpay_subtitle_one_backup_card">Завершите процесс бэкапа создав код доступа</string>
<string name="onboarding_saltpay_title_backup_card">Приложите Tangem карту</string>
<string name="onboarding_saltpay_title_no_backup_card">Бэкап карта не добавлена</string>
<string name="onboarding_saltpay_title_one_backup_card">Бэкап карта создана</string>
<string name="onboarding_saltpay_title_prepare_origin">Приготовьте SaltPay карту</string>
<string name="onboarding_seed_button_read_more">Читать про секретную фразу</string>
<string name="onboarding_seed_generate_message">Запишите эти 12 слов в порядке, указанном ниже, и сохраните их в надежном месте.</string>
<string name="onboarding_seed_generate_title">Ваша секретная фраза</string>
@ -220,13 +233,8 @@
<string name="onboarding_seed_user_validation_title">Итак, проверим</string>
<string name="onboarding_subtitle_claim">Для начала работы просто запросите начисление wxDAI на свой кошелек</string>
<string name="onboarding_subtitle_claim_progress">Это займет несколько секунд</string>
<string name="onboarding_subtitle_kyc_retry">Более подробная информация отправлена на ваш адрес электронной почты.</string>
<string name="onboarding_subtitle_kyc_start">Для начала работы с картой вам необходимо завершить процесс подтверждения личности</string>
<string name="onboarding_subtitle_kyc_waiting">Пожалуйста дождитесь завершения процесса подтверждения личности. Вы будете уведомлены через e-mail. Обычно это занимает не более часа. Вы можете закрыть приложение и вернуться позже.</string>
<string name="onboarding_subtitle_no_backup_cards">Чтобы начать процесс резервного копирования, добавьте одну или две резервные карты.</string>
<string name="onboarding_subtitle_one_backup_card">Вы можете добавить еще одну карту или завершить процесс резервного копирования</string>
<string name="onboarding_subtitle_pin">Установите 4-х значный код.\nОн будет использован для платежей.</string>
<string name="onboarding_subtitle_register_wallet">Подключите вашу карту к децентрализованной платежной системе</string>
<string name="onboarding_subtitle_scan_backup_card_format">Подготовьте резервную карту с номером %s</string>
<string name="onboarding_subtitle_scan_origin_card">Подготовьте основную карту</string>
<string name="onboarding_subtitle_scan_primary_card_format">Подготовьте основную карту с номером %s</string>
@ -237,13 +245,9 @@
<string name="onboarding_title_backup_card_format">Резервная карта #%d</string>
<string name="onboarding_title_claim">Запросить %s</string>
<string name="onboarding_title_claim_progress">Запрашивается</string>
<string name="onboarding_title_kyc_retry">Что-то пошло не так</string>
<string name="onboarding_title_kyc_start">Подтвердите свою личность</string>
<string name="onboarding_title_kyc_waiting">Подтверждение личности в процессе</string>
<string name="onboarding_title_no_backup_cards">Нет резервных карт</string>
<string name="onboarding_title_one_backup_card">Добавлена ​​одна резервная карта</string>
<string name="onboarding_title_pin">Код доступа</string>
<string name="onboarding_title_register_wallet">Подключите свою карту</string>
<string name="onboarding_title_scan_origin_card">Подготовьте свою карту</string>
<string name="onboarding_title_two_backup_cards">Добавлены две резервные карты</string>
<string name="onboarding_top_up_body">Пополните кошелек на любую сумму, чтобы начать пользоваться картой</string>
@ -264,6 +268,9 @@
<string name="organize_tokens_group">Группировка</string>
<string name="organize_tokens_sort_by_balance">По балансу</string>
<string name="organize_tokens_title">Сортировка токенов</string>
<string name="organize_tokens_ungroup">Разгруппировать</string>
<string name="receive_bottom_sheet_title">%1$s %2$s адрес в сети %3$s</string>
<string name="receive_bottom_sheet_warning_message">%1$s (%2$s) в сети %3$s</string>
<string name="referral_button_participate">Участвовать</string>
<string name="referral_error_failed_to_load_info">Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже.</string>
<string name="referral_error_failed_to_load_info_with_reason">Не удалось загрузить информацию по реферальной программе. Код ошибки: %s. Пожалуйста, попробуйте позже.</string>
@ -295,12 +302,6 @@
<string name="reset_card_without_backup_to_factory_message">Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек.</string>
<string name="russian_bank_card_warning_subtitle">У вас есть карта банка другой страны или платежной системы UnionPay?</string>
<string name="russian_bank_card_warning_title">Карты банков РФ в данный момент не принимаются</string>
<string name="saltpay_error_empty_backup_message">Приложите карту с логотипом Visa</string>
<string name="saltpay_error_empty_backup_title">Внимание</string>
<string name="saltpay_error_no_gas_message">Пожалуйста обратитесь в службу поддержки</string>
<string name="saltpay_error_no_gas_title">Недостаточно средств для активации</string>
<string name="saltpay_error_pin_weak_message">Данный Код доступа может быть легко взломан</string>
<string name="saltpay_error_pin_weak_title">Ввод одинаковых цифр является не безопасным</string>
<string name="save_user_wallet_agreement_access_description">Войдите в приложение и следите за своим балансом без сканирования карты</string>
<string name="save_user_wallet_agreement_access_title">Доступ в приложение</string>
<string name="save_user_wallet_agreement_allow_biometrics">Использовать биометрию</string>
@ -317,11 +318,7 @@
<string name="search_tokens_title">Поиск валют</string>
<string name="send_amount_label">Сумма</string>
<string name="send_destination_hint_address">Адрес</string>
<string name="send_destination_hint_address_payid">Адрес или PayString</string>
<string name="send_error_address_same_as_wallet">Адрес совпадает с адресом кошелька</string>
<string name="send_error_payid_not_registered">PayString не зарегистрирован</string>
<string name="send_error_payid_request_failed">Не удалось выполнить запрос PayString</string>
<string name="send_error_payid_unsupported_by_blockchain">PayString не поддерживается блокчейном</string>
<string name="send_extras_error_invalid_destination_tag">Недопустимый Tag. Он не будет добавлен в транзакцию.</string>
<string name="send_extras_error_invalid_memo">Недопустимый Memo. Он не будет добавлен в транзакцию.</string>
<string name="send_extras_hint_destination_tag">Tag</string>
@ -333,7 +330,6 @@
<string name="send_fee_picker_priority">Приоритетная</string>
<string name="send_max_amount_label">Максимальная сумма</string>
<string name="send_network_fee_title">Сетевая комиссия</string>
<string name="send_title">Отправить</string>
<string name="send_title_currency_format">Отправка %s</string>
<string name="send_total_label">Всего</string>
<string name="send_total_subtitle_asset_format">%1$s и %2$s будет отправлено</string>
@ -350,6 +346,7 @@
<string name="solana_rent_warning">Сеть Solana взимает арендную плату в размере %1$s каждые 2 дня. Аккаунты, которые не могут позволить себе арендную плату, удаляются из сети. Пополните свой счет более чем на %2$s, чтобы не платить арендную плату.</string>
<string name="story_awe_description">Держите свои криптосбережения в безопасности. Приватные ключи надежно хранятся на карте.</string>
<string name="story_awe_title">Революционный аппаратный кошелек</string>
<string name="story_backup_description">До **трех карт** с одним кошельком</string>
<string name="story_backup_description_1">До</string>
<string name="story_backup_description_2_bold">трех карт</string>
<string name="story_backup_description_3">с одним кошельком</string>
@ -358,6 +355,9 @@
<string name="story_currencies_title">Тысячи криптовалют</string>
<string name="story_finish_description">Используйте его на ходу, в любом месте, в любое время. Без проводов и батареек. Как только понадобится крипта, просто приложите карту к телефону.</string>
<string name="story_finish_title">Кошелек для каждого</string>
<string name="story_learn_description">Пройдите обучение и получите возможность купить кошелек Tangem со скидкой и токены 1inch в качестве бонуса</string>
<string name="story_learn_learn">Пройти обучение</string>
<string name="story_learn_title">Получите свой бонус</string>
<string name="story_meet_borrow">Занимайте</string>
<string name="story_meet_buy">Покупайте</string>
<string name="story_meet_exchange">Обменивайте</string>
@ -410,6 +410,7 @@
<string name="token_details_hide_token">Скрыть токен</string>
<string name="token_details_send_blocked_fee_format">%1$s — это токен в сети %2$s. Чтобы отправить транзакцию %3$s, необходимо пополнить баланс %4$s (%5$s) для оплаты комиссии сети.</string>
<string name="token_details_send_blocked_tx_format">Пожалуйста, дождитесь завершения транзакции %s, чтобы иметь возможность отправить средства</string>
<string name="token_details_token_type_subtitle">%1$s токен в сети %%image%% %2$s</string>
<string name="token_details_unable_hide_alert_message">Токен %1$s является основной валютой в сети %2$s и не может быть скрыт до тех пор, пока у вас в списке есть другие токены этой сети.</string>
<string name="token_details_unable_hide_alert_title">Невозможно скрыть %s</string>
<string name="token_item_no_rate">Нет цены</string>
@ -424,6 +425,7 @@
<string name="transaction_history_error_failed_to_load">Не удалось загрузить историю транзакций.\nНажмите на кнопку перезагрузки, чтобы обновить информацию.</string>
<string name="transaction_history_not_supported_description">История транзакций в настоящее время не поддерживается для этого блокчейна. Но не волнуйтесь, мы работаем над этим! А пока вы можете проверить ее в обозревателе.</string>
<string name="transaction_history_transaction_from_address">от: %s</string>
<string name="transaction_history_transaction_to_address">на: %s</string>
<string name="transaction_history_tx_in_progress">В процессе…</string>
<string name="twin_error_same_card">Вы отсканировали ту же карту. Для создания twin-кошелька вам необходимо отсканировать карту с номером %d</string>
<string name="twins_onboarding_description_format">Это карта, которую вы держите в руках. У парной карты номер %s.\n\nОбе карты можно использовать для вывода средств из этого кошелька.</string>
@ -445,7 +447,6 @@
<string name="user_wallet_list_single_header">Одновалютные</string>
<string name="user_wallet_list_title">Мои кошельки</string>
<string name="user_wallet_list_unlock_all">Разблокировать все с %s</string>
<string name="wallet_address_button_create_payid">Создать PayString</string>
<string name="wallet_address_button_explore">История транзакций</string>
<string name="wallet_balance_blockchain_unreachable">Сеть недоступна</string>
<string name="wallet_balance_blockchain_unreachable_try_later">Блокчейн недоступен. Попробуй позже.</string>
@ -454,21 +455,26 @@
<string name="wallet_balance_tx_in_progress">Транзакция подтверждается…</string>
<string name="wallet_balance_verified">Подтвержденный баланс</string>
<string name="wallet_button_actions">Действия</string>
<string name="wallet_button_buy">Купить</string>
<string name="wallet_button_sell">Продать</string>
<string name="wallet_button_send">Отправить</string>
<string name="wallet_choose_trade_action">Вы хотите купить или продать криптовалюту?</string>
<string name="wallet_connect_alert_sign_message">Запрос на подпись сообщения.\n\n%s</string>
<string name="wallet_connect_bnb_sign_message">Dapp %1$s, запрос на\nподпись транзакции с BNB.\n\n%2$s</string>
<string name="wallet_connect_bnb_trade_order_message">Торговый ордер на %1$s\nЦена: %2$s\nСумма к получению: %3$s\nСумма к оплате: %4$s</string>
<string name="wallet_connect_bnb_transaction_message">Детали транзакции:\nОт: %1$s\nК: %2$s\nСумма: %3$s</string>
<string name="wallet_connect_bnb_transaction_signed">Транзакция с BNB успешно подписана и отправлена ​​в Dapp.</string>
<string name="wallet_connect_clipboard_alert">Буфер обмена содержит код WalletConnect. Использовать скопированное значение или отсканировать QR-код</string>
<string name="wallet_connect_create_tx_message">Запрос на создание транзакции для %1$s\n%2$s\n\nСумма: %3$s\nКомиссия: %4$s\nВсего: %5$s\nБаланс: %6$s</string>
<string name="wallet_connect_create_tx_not_enough_funds">Невозможно отправить транзакцию. Недостаточно средств.</string>
<string name="wallet_connect_error_failed_to_connect">Не удалось установить сессию WalletConnect. Пожалуйста, повторите попытку позже.</string>
<string name="wallet_connect_error_missing_blockchains">Не все токены добавлены в ваш список. Пожалуйста, добавьте их в начале, а потом попробуйте снова. Недостающие токены: \n</string>
<string name="wallet_connect_error_sing_failed">Не удалось подписать сообщение.\nПожалуйста, попробуйте еще раз</string>
<string name="wallet_connect_error_timeout">Не удалось установить сессию WalletConnect за отведённое время. Пожалуйста, повторите попытку позже.</string>
<string name="wallet_connect_error_unsupported_blockchains">Запрос на подключение через WalletConnect содержит неподдерживаемые блокчеины. Неподдерживаемые блокчеины:\n</string>
<string name="wallet_connect_error_unsupported_dapp">Cоединение с этим Dapp сервисом не может быть установлено из-за его технической реализации.</string>
<string name="wallet_connect_error_with_framework_message">Произошла непредвиденная ошибка. Сообщение ошибки: %s Попробуйте, пожалуйста, позже. Если проблема будет продолжать возникать - обратитесь в службу поддержки.</string>
<string name="wallet_connect_error_wrong_card_selected">Неверная карта выбрана в приложении Tangem</string>
<string name="wallet_connect_failed_to_build_tx">Не удалось создать транзакцию из данных Dapp. Код: %s</string>
<string name="wallet_connect_generic_error_with_code">Произошла непредвиденная ошибка. Код ошибки: %d Попробуйте, пожалуйста, позже. Если проблема будет продолжать возникать - обратитесь в службу поддержки.</string>
<string name="wallet_connect_message_signed">Сообщение было успешно подписано и отправлено в Dapp</string>
<string name="wallet_connect_network_not_found_format">Сеть %s не найдена. Пожалуйста, добавьте её и попробуйте заново.</string>
<string name="wallet_connect_paste_from_clipboard">Вставить из буфера обмена</string>
<string name="wallet_connect_request_session_start">Запрос на открытие сессии для\n%1$s\n\nСЕТЬ: %2$s\n\nURL: %3$s</string>
@ -477,8 +483,12 @@
<string name="wallet_connect_scanner_error_not_valid_card">Эту карту нельзя использовать с WalletConnect.</string>
<string name="wallet_connect_scanner_error_unsupported_network">Сеть не поддерживается. Пожалуйста, выберите другую сеть.</string>
<string name="wallet_connect_select_network">Выберите сеть</string>
<string name="wallet_connect_service_no_chain_id">Dapp не предоставил необходимые данные для открытия сессии WalletConnect</string>
<string name="wallet_connect_subtitle">Подключение к Dapps</string>
<string name="wallet_connect_title">WalletConnect</string>
<string name="wallet_connect_transaction_signed">Транзакция успешно подписана и отправлена ​​в Dapp</string>
<string name="wallet_connect_transaction_signed_and_send">Транзакция успешно подписана и отправлена ​​в блокчейн</string>
<string name="wallet_connect_tx_not_found">Не удалось найти хэш транзакции</string>
<string name="wallet_currency_subtitle">Сеть %s</string>
<string name="wallet_error_no_account">Аккаунт не создан</string>
<string name="wallet_error_unsupported_blockchain">Эта карта не поддерживается</string>

View file

@ -46,23 +46,29 @@
<string name="common_balance">餘額: %s</string>
<string name="common_biometric_authentication">生物識別</string>
<string name="common_biometrics">生物</string>
<string name="common_buy">購買</string>
<string name="common_camera_denied_alert_message">您尚未授予相機訪問權限,請更改您的隱私設置</string>
<string name="common_cancel">刪除</string>
<string name="common_close">關閉</string>
<string name="common_copy">複製</string>
<string name="common_copy_address">複製地址</string>
<string name="common_create">創造</string>
<string name="common_delete">刪除</string>
<string name="common_disabled">禁用</string>
<string name="common_dislike">不喜歡</string>
<string name="common_done">完成</string>
<string name="common_enable">允許</string>
<string name="common_enabled">啟用</string>
<string name="common_exchange">交易</string>
<string name="common_like">喜歡</string>
<string name="common_no"></string>
<string name="common_ok">OK</string>
<string name="common_origin_card">主卡片</string>
<string name="common_reject">拒絕</string>
<string name="common_save_changes">保存設置</string>
<string name="common_search">搜索</string>
<string name="common_sell">銷售</string>
<string name="common_send">發送</string>
<string name="common_server_unavailable">伺服器不可用,請稍後在試</string>
<string name="common_share">分享</string>
<string name="common_sign">簽署</string>
@ -74,6 +80,7 @@
<string name="common_terms_and_conditions">條款和條件</string>
<string name="common_transactions">交易</string>
<string name="common_understand">我了解</string>
<string name="common_unreachable">無法觸達</string>
<string name="common_yes"></string>
<string name="contract_address_copied_message">已複製代幣地址</string>
<string name="currency_subtitle_expanded">支持的網路</string>
@ -164,11 +171,8 @@
<string name="onboarding_button_claim">獲取</string>
<string name="onboarding_button_continue_wallet">繼續至我的錢包</string>
<string name="onboarding_button_finalize_backup">完成備份過程</string>
<string name="onboarding_button_kyc_start">通過Utorg驗證</string>
<string name="onboarding_button_kyc_waiting">刷新</string>
<string name="onboarding_button_pin">設置PIN碼</string>
<string name="onboarding_button_receive_crypto">接收貨幣</string>
<string name="onboarding_button_register_wallet">註冊</string>
<string name="onboarding_button_scan_origin_card">掃描主卡</string>
<string name="onboarding_button_skip_backup">暫時略過</string>
<string name="onboarding_button_what_does_it_mean">它是如何運作的?</string>
@ -183,18 +187,9 @@
<string name="onboarding_exit_alert_message">這此情況,您必須要重新開始</string>
<string name="onboarding_exit_alert_title">您想要離開啟用程序嗎?</string>
<string name="onboarding_getting_started">開始</string>
<string name="onboarding_navbar_kyc_progress">驗證身分</string>
<string name="onboarding_navbar_kyc_start">KYC</string>
<string name="onboarding_navbar_pin">PIN 碼</string>
<string name="onboarding_navbar_register_wallet">連接</string>
<string name="onboarding_navbar_title_creating_backup">創建備份</string>
<string name="onboarding_saltpay_button_backup_origin">點擊 SaltPay 卡</string>
<string name="onboarding_saltpay_subtitle_no_backup_cards">要開始備份過程,您必須添加 Tangem 卡片作為備份</string>
<string name="onboarding_saltpay_subtitle_one_backup_card">通過創建訪問密碼完成備份</string>
<string name="onboarding_saltpay_title_backup_card">點擊 Tangem 卡片</string>
<string name="onboarding_saltpay_title_no_backup_card">沒有備份卡片</string>
<string name="onboarding_saltpay_title_one_backup_card">備份卡片已準備完成</string>
<string name="onboarding_saltpay_title_prepare_origin">準備SaltPay卡</string>
<string name="onboarding_seed_button_read_more">閱讀更多關於助記詞的訊息</string>
<string name="onboarding_seed_generate_message">按照下面給出的順序寫下這 12 個單詞,並將它們存放在安全秘密的地方。</string>
<string name="onboarding_seed_generate_title">您的助記詞</string>
@ -210,13 +205,8 @@
<string name="onboarding_seed_user_validation_title">那麼,讓我們檢查一下</string>
<string name="onboarding_subtitle_claim">要開始,只需將 wxDAI 獲取到您的錢包</string>
<string name="onboarding_subtitle_claim_progress">這會花上幾秒</string>
<string name="onboarding_subtitle_kyc_retry">請查看Email已獲得更多指示</string>
<string name="onboarding_subtitle_kyc_start">要開始使用您的卡,您必須通過 KYC驗證</string>
<string name="onboarding_subtitle_kyc_waiting">請等待驗證完成,您將收到電子郵件通知。通常最多需要 1 小時。您可以關閉該應用程序,稍後再回來</string>
<string name="onboarding_subtitle_no_backup_cards">要開始備份過程,最多可添加兩張備份卡。</string>
<string name="onboarding_subtitle_one_backup_card">您可以再添加一張卡或完成備份過程</string>
<string name="onboarding_subtitle_pin">設置一個 4 位密碼。 \n它將用在付款時使用。</string>
<string name="onboarding_subtitle_register_wallet">將您的卡片連接到去中心化支付系統</string>
<string name="onboarding_subtitle_scan_backup_card_format">準備編號為 %s 的備份卡</string>
<string name="onboarding_subtitle_scan_origin_card">準備主卡</string>
<string name="onboarding_subtitle_scan_primary_card_format">準備編號為 %s 的主卡</string>
@ -227,13 +217,9 @@
<string name="onboarding_title_backup_card_format">備份卡 #%d</string>
<string name="onboarding_title_claim">獲取%s</string>
<string name="onboarding_title_claim_progress">獲取中</string>
<string name="onboarding_title_kyc_retry">有東西出錯了</string>
<string name="onboarding_title_kyc_start">確認你的身分</string>
<string name="onboarding_title_kyc_waiting">KYC 認證中</string>
<string name="onboarding_title_no_backup_cards">沒有備用卡</string>
<string name="onboarding_title_one_backup_card">添加了一張備用卡</string>
<string name="onboarding_title_pin">PIN 碼</string>
<string name="onboarding_title_register_wallet">連接你的錢包</string>
<string name="onboarding_title_scan_origin_card">準備好你的卡片</string>
<string name="onboarding_title_two_backup_cards">添加了兩張備用卡</string>
<string name="onboarding_top_up_body">要開始使用,只需為錢包充值任意金額</string>
@ -279,12 +265,6 @@
<string name="reset_card_without_backup_to_factory_message">恢復原廠設置將從所選卡中完全刪除錢包並將其從應用程序中刪除。您將無法恢復當前錢包</string>
<string name="russian_bank_card_warning_subtitle">您有其他國家的銀行卡或銀聯卡嗎?</string>
<string name="russian_bank_card_warning_title">目前不接受俄羅斯銀行卡</string>
<string name="saltpay_error_empty_backup_message">輕觸帶有 visa 標誌的卡片</string>
<string name="saltpay_error_empty_backup_title">注意</string>
<string name="saltpay_error_no_gas_message">請聯繫客服</string>
<string name="saltpay_error_no_gas_title">沒有激活資金</string>
<string name="saltpay_error_pin_weak_message">這樣的 PIN 很容易被暴力破解</string>
<string name="saltpay_error_pin_weak_title">四個相同的數字不安全</string>
<string name="save_user_wallet_agreement_access_description">登錄應用程序並在不掃描卡片的情況下檢查您的資產</string>
<string name="save_user_wallet_agreement_access_title">訪問應用程序</string>
<string name="save_user_wallet_agreement_allow_biometrics">允許使用生物辨識</string>
@ -301,11 +281,7 @@
<string name="search_tokens_title">搜尋代幣</string>
<string name="send_amount_label">數量</string>
<string name="send_destination_hint_address">地址</string>
<string name="send_destination_hint_address_payid">地址或 PayString</string>
<string name="send_error_address_same_as_wallet">地址與錢包地址相同</string>
<string name="send_error_payid_not_registered">PayString 未註冊</string>
<string name="send_error_payid_request_failed">PayString 請求失敗</string>
<string name="send_error_payid_unsupported_by_blockchain">PayString 不被區塊鏈支持</string>
<string name="send_extras_error_invalid_destination_tag">標籤無效。它不會被添加到交易中</string>
<string name="send_extras_error_invalid_memo">Memo無效。 它不會被添加到交易中</string>
<string name="send_extras_hint_destination_tag">Tag</string>
@ -317,7 +293,6 @@
<string name="send_fee_picker_priority">優先</string>
<string name="send_max_amount_label">最大值</string>
<string name="send_network_fee_title">網路費</string>
<string name="send_title">發送</string>
<string name="send_title_currency_format">發送 %s</string>
<string name="send_total_label">總計</string>
<string name="send_total_subtitle_asset_format">%1$s 和 %2$s 將被發送</string>
@ -333,6 +308,7 @@
<string name="solana_rent_warning">Solana 網絡每 2 天收取 %1$s 的費用。無法付此費用的帳戶將從網絡中清除。向您的帳戶存入超過 %2$s 即可免費使用</string>
<string name="story_awe_description">安全地存儲您的加密貨幣,同時將私鑰保存在您的卡中</string>
<string name="story_awe_title">創新式的硬體錢包</string>
<string name="story_backup_description">最多 **3張實體卡片** 到一個錢包</string>
<string name="story_backup_description_1">最多</string>
<string name="story_backup_description_2_bold">3張實體卡片</string>
<string name="story_backup_description_3">到一個錢包</string>
@ -415,7 +391,6 @@
<string name="user_wallet_list_single_header">單一幣種</string>
<string name="user_wallet_list_title">我的錢包</string>
<string name="user_wallet_list_unlock_all">用 %s 解鎖全部</string>
<string name="wallet_address_button_create_payid">創建支付字符串</string>
<string name="wallet_address_button_explore">交易記錄</string>
<string name="wallet_balance_blockchain_unreachable">網路無法使用</string>
<string name="wallet_balance_blockchain_unreachable_try_later">區塊鍊無法使用。稍後再試</string>
@ -424,21 +399,26 @@
<string name="wallet_balance_tx_in_progress">交易進行中</string>
<string name="wallet_balance_verified">檢視餘額</string>
<string name="wallet_button_actions">動作</string>
<string name="wallet_button_buy">購買</string>
<string name="wallet_button_sell">銷售</string>
<string name="wallet_button_send">發送</string>
<string name="wallet_choose_trade_action">您想要購買或賣出交易貨幣?</string>
<string name="wallet_connect_alert_sign_message">請求籤署消息。%s</string>
<string name="wallet_connect_bnb_sign_message">Dapp %1$s請求\n簽署 BNB 交易。\n%2$s</string>
<string name="wallet_connect_bnb_trade_order_message">%1$s 的交易訂單\n價格 %2$s\n接收金額%3$s\n支付數量 %4$s</string>
<string name="wallet_connect_bnb_transaction_message">交易明細:\n從 %1$s\n到 %2$s\n數量 %3$s</string>
<string name="wallet_connect_bnb_transaction_signed">BNB 交易已成功簽署並發送至 Dapp</string>
<string name="wallet_connect_clipboard_alert">剪貼板包含 WalletConnect 代碼。使用複制的值或掃描二維碼</string>
<string name="wallet_connect_create_tx_message">請求為 %1$s 創建交易\n%2$s\n\n數量 %3$s\n費用 %4$s\n全部的 %5$s\n餘額 %6$s</string>
<string name="wallet_connect_create_tx_not_enough_funds">無法交易,無足夠資金</string>
<string name="wallet_connect_error_failed_to_connect">未能建立 WalletConnect 連接。請稍後再試</string>
<string name="wallet_connect_error_missing_blockchains">並非所有代幣都已添加到您的列表中。請先添加它們,然後重試。缺少標記:\n</string>
<string name="wallet_connect_error_sing_failed">無法簽署消息。請重試</string>
<string name="wallet_connect_error_timeout">無法建立 WalletConnect 連接:超時錯誤。請稍後再試</string>
<string name="wallet_connect_error_unsupported_blockchains">會話請求包含不支持 WalletConnect 連接的區塊鏈。不支持的區塊鏈:</string>
<string name="wallet_connect_error_unsupported_blockchains">會話請求包含不支持 WalletConnect 連接的區塊鏈。不支持的區塊鏈:\n</string>
<string name="wallet_connect_error_unsupported_dapp">由於技術問題,無法與此 Dapp 建立連接</string>
<string name="wallet_connect_error_with_framework_message">我們遇到了未知錯誤。錯誤信息:%s。如果問題仍然存在-請隨時聯繫我們的客服人員</string>
<string name="wallet_connect_error_wrong_card_selected">在 Tangem App 中選擇了錯誤的卡</string>
<string name="wallet_connect_failed_to_build_tx">無法從 Dapp 數據創建交易。代碼: %s</string>
<string name="wallet_connect_generic_error_with_code">我們遇到了未知錯誤。錯誤代碼:%d。如果問題仍然存在-請隨時聯繫我們的支持人員</string>
<string name="wallet_connect_message_signed">消息已成功簽名並發送至Dapp</string>
<string name="wallet_connect_network_not_found_format">沒有 %s 網路,請先加入後再試一次</string>
<string name="wallet_connect_paste_from_clipboard">從剪貼板貼上</string>
<string name="wallet_connect_request_session_start">請求開始會話\n%1$s\n\n網絡 %2$s\n\n網址%3$s</string>
@ -447,8 +427,12 @@
<string name="wallet_connect_scanner_error_not_valid_card">此卡不能用於建立 WalletConnect 連接</string>
<string name="wallet_connect_scanner_error_unsupported_network">不支持此網絡。請選擇其他網絡</string>
<string name="wallet_connect_select_network">選擇網路</string>
<string name="wallet_connect_service_no_chain_id">Dapp 沒有提供必要的數據來建立 WalletConnect 連接</string>
<string name="wallet_connect_subtitle">連結到Dapps</string>
<string name="wallet_connect_title">WalletConnect</string>
<string name="wallet_connect_transaction_signed">交易已成功簽署並發送至 Dapp</string>
<string name="wallet_connect_transaction_signed_and_send">交易已成功簽署並發送至區塊鏈</string>
<string name="wallet_connect_tx_not_found">未能找到交易哈希</string>
<string name="wallet_currency_subtitle">%s 網路</string>
<string name="wallet_error_no_account">帳號尚未被創造</string>
<string name="wallet_error_unsupported_blockchain">不支持此卡</string>

View file

@ -50,27 +50,41 @@
<string name="common_balance">Balance: %s</string>
<string name="common_biometric_authentication">biometric authentication</string>
<string name="common_biometrics">biometrics</string>
<string name="common_buy">Buy</string>
<string name="common_camera_denied_alert_message">You have not given access to your camera, please adjust your privacy settings</string>
<string name="common_cancel">Cancel</string>
<string name="common_close">Close</string>
<string name="common_copy">Copy</string>
<string name="common_copy_address">Copy address</string>
<string name="common_create">Create</string>
<string name="common_delete">Delete</string>
<string name="common_disabled">Disabled</string>
<string name="common_dislike">Dislike</string>
<string name="common_done">Done</string>
<string name="common_enable">Enable</string>
<string name="common_enabled">Enabled</string>
<string name="common_exchange">Exchange</string>
<string name="common_explore_transaction_history">Explore transaction history</string>
<string name="common_explorer">Explorer</string>
<string name="common_like">Like</string>
<string name="common_main_network">Main network</string>
<string name="common_no">No</string>
<string name="common_no_data">No data</string>
<string name="common_ok">OK</string>
<string name="common_origin_card">Primary Card</string>
<string name="common_receive">Receive</string>
<string name="common_reject">Reject</string>
<string name="common_reload">Reload</string>
<string name="common_save_changes">Save changes</string>
<string name="common_search">Search</string>
<string name="common_seed_phrase">Seed phrase</string>
<string name="common_sell">Sell</string>
<string name="common_send">Send</string>
<string name="common_server_unavailable">The server is not available, please try again later</string>
<string name="common_share">Share</string>
<string name="common_sign">Sign</string>
<string name="common_sign_and_send">Sign and send</string>
<string name="common_stake">Stake</string>
<string name="common_start">Start</string>
<string name="common_submit">Submit</string>
<string name="common_success">Success</string>
@ -79,6 +93,7 @@
<string name="common_transactions">Transactions</string>
<string name="common_transfer">Transfer</string>
<string name="common_understand">I understand</string>
<string name="common_unreachable">Unreachable</string>
<string name="common_yes">Yes</string>
<string name="contract_address_copied_message">Contract address copied!</string>
<string name="currency_subtitle_expanded">Available networks</string>
@ -143,11 +158,20 @@
<string name="initial_message_tap_header">Tap the card</string>
<string name="internal_error_wallet_manager_not_found">Internal error: wallet manager not found</string>
<string name="key_invalidated_warning_description">You have updated biometrics, scan your card to enter</string>
<string name="main_get_bonus_subtitle">You have completed the training and can get your 1inch tokens</string>
<string name="main_get_bonus_title">Get a bonus</string>
<plurals name="main_learn_subtitle">
<item quantity="one">Complete the training and get %d 1inch token on your wallet</item>
<item quantity="other">Complete the training and get %d 1inch tokens on your wallet</item>
</plurals>
<string name="main_learn_title">Learn &amp; Earn</string>
<string name="main_manage_tokens">Manage tokens</string>
<string name="main_no_backup_warning_subtitle">To protect your assets, we advise you to carry out this procedure</string>
<string name="main_no_backup_warning_title">Your wallet has not been backed up</string>
<string name="main_page_balance">Total balance</string>
<string name="main_processing_full_amount">The amount does not include some of your funds</string>
<string name="main_promotion_credited">1inch tokens will be credited to your wallet address within 2 days</string>
<string name="main_promotion_no_purchase">There was no purchase of a wallet using your promo code, which means you cannot receive a bonus. Buy Tangem wallet, scan it in the app, and get the bonus.</string>
<string name="main_scan_card_warning_view_subtitle">To access all the networks you need to scan the card</string>
<string name="main_scan_card_warning_view_title">Scan your card</string>
<string name="onboarding_access_code_feature_1_description">You have to set up a single access code to protect all your wallets</string>
@ -171,11 +195,8 @@
<string name="onboarding_button_claim">Claim</string>
<string name="onboarding_button_continue_wallet">Continue to my wallet</string>
<string name="onboarding_button_finalize_backup">Finalize the backup</string>
<string name="onboarding_button_kyc_start">Verify via Utorg</string>
<string name="onboarding_button_kyc_waiting">Refresh</string>
<string name="onboarding_button_pin">Set PIN code</string>
<string name="onboarding_button_receive_crypto">Receive crypto</string>
<string name="onboarding_button_register_wallet">Register</string>
<string name="onboarding_button_scan_origin_card">Scan primary card</string>
<string name="onboarding_button_skip_backup">Skip for later</string>
<string name="onboarding_button_what_does_it_mean">How does it work?</string>
@ -191,18 +212,9 @@
<string name="onboarding_exit_alert_title">Do you want to exit the activation process?</string>
<string name="onboarding_getting_started">Getting started</string>
<string name="onboarding_linking_error_card_with_wallets">Another wallet has already been created on the card you\'re trying to add. Do you want to reset it and use the card for a new wallet?</string>
<string name="onboarding_navbar_kyc_progress">Verify your identity</string>
<string name="onboarding_navbar_kyc_start">KYC</string>
<string name="onboarding_navbar_pin">Pin code</string>
<string name="onboarding_navbar_register_wallet">Connect</string>
<string name="onboarding_navbar_title_creating_backup">Creating a backup</string>
<string name="onboarding_saltpay_button_backup_origin">Tap the SaltPay card</string>
<string name="onboarding_saltpay_subtitle_no_backup_cards">To start the backup process you have to add the Tangem card as your backup</string>
<string name="onboarding_saltpay_subtitle_one_backup_card">Finalize the backup process by creating an access code</string>
<string name="onboarding_saltpay_title_backup_card">Tap the Tangem card</string>
<string name="onboarding_saltpay_title_no_backup_card">No backup card</string>
<string name="onboarding_saltpay_title_one_backup_card">Backup card ready</string>
<string name="onboarding_saltpay_title_prepare_origin">Prepare the SaltPay card</string>
<string name="onboarding_seed_button_read_more">Read more about seed phrases</string>
<string name="onboarding_seed_generate_message">Write these 12 words down in the order given below and store them in a safe and secret place.</string>
<string name="onboarding_seed_generate_title">Your secret phrase</string>
@ -218,13 +230,8 @@
<string name="onboarding_seed_user_validation_title">So, lets check</string>
<string name="onboarding_subtitle_claim">To get started, simply claim wxDAI to your wallet</string>
<string name="onboarding_subtitle_claim_progress">It will take a few seconds</string>
<string name="onboarding_subtitle_kyc_retry">Please check your email for further instructions</string>
<string name="onboarding_subtitle_kyc_start">To start using your card you have to pass the KYC process</string>
<string name="onboarding_subtitle_kyc_waiting">Please wait until the verification is completed. You\'ll be notified via email. Usually it takes up to 1 hour. You can close the app and come back later.</string>
<string name="onboarding_subtitle_no_backup_cards">To start the backup process add up to two backup cards.</string>
<string name="onboarding_subtitle_one_backup_card">You can add one more card or finalize the backup process</string>
<string name="onboarding_subtitle_pin">Set up a 4-digit code.\nIt will be used for payments.</string>
<string name="onboarding_subtitle_register_wallet">Connect your card to the decentralized payment system</string>
<string name="onboarding_subtitle_scan_backup_card_format">Prepare the backup card with number %s</string>
<string name="onboarding_subtitle_scan_origin_card">Prepare the primary card</string>
<string name="onboarding_subtitle_scan_primary_card_format">Prepare the primary card with number %s</string>
@ -235,13 +242,9 @@
<string name="onboarding_title_backup_card_format">Backup card #%d</string>
<string name="onboarding_title_claim">Claim %s</string>
<string name="onboarding_title_claim_progress">Claiming</string>
<string name="onboarding_title_kyc_retry">Something went wrong</string>
<string name="onboarding_title_kyc_start">Verify your identity</string>
<string name="onboarding_title_kyc_waiting">KYC is in progress</string>
<string name="onboarding_title_no_backup_cards">No backup cards</string>
<string name="onboarding_title_one_backup_card">One backup card added</string>
<string name="onboarding_title_pin">PIN Code</string>
<string name="onboarding_title_register_wallet">Connect your card</string>
<string name="onboarding_title_scan_origin_card">Prepare your card</string>
<string name="onboarding_title_two_backup_cards">Two backup cards added</string>
<string name="onboarding_top_up_body">To get started, simply top up the wallet with any amount</string>
@ -262,6 +265,10 @@
<string name="organize_tokens_group">Group</string>
<string name="organize_tokens_sort_by_balance">By balance</string>
<string name="organize_tokens_title">Organize tokens</string>
<string name="organize_tokens_ungroup">Ungroup</string>
<string name="receive_bottom_sheet_title">%1$s %2$s address on %3$s network</string>
<string name="receive_bottom_sheet_warning_message">%1$s (%2$s) on %3$s network</string>
<string name="receive_bottom_sheet_warning_message_full">Send only %s to this address. Sending any other currency will result in its irreversible loss.</string>
<string name="referral_button_participate">Participate</string>
<string name="referral_error_failed_to_load_info">Failed to load the information about the referral program. Please try again later.</string>
<string name="referral_error_failed_to_load_info_with_reason">Failed to load the information about the referral program. Error code: %s. Please try again later.</string>
@ -291,12 +298,6 @@
<string name="reset_card_without_backup_to_factory_message">Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet.</string>
<string name="russian_bank_card_warning_subtitle">Do you have a bank card of another country or a UnionPay card?</string>
<string name="russian_bank_card_warning_title">Russian bank cards are not accepted at the moment</string>
<string name="saltpay_error_empty_backup_message">Tap the card with the visa logo</string>
<string name="saltpay_error_empty_backup_title">Attention</string>
<string name="saltpay_error_no_gas_message">Please contact support</string>
<string name="saltpay_error_no_gas_title">No funds for activation</string>
<string name="saltpay_error_pin_weak_message">Such a PIN can be brute-forced easily</string>
<string name="saltpay_error_pin_weak_title">Four identical digits isn\'t safe</string>
<string name="save_user_wallet_agreement_access_description">Log into the app and check your balance without scanning the card</string>
<string name="save_user_wallet_agreement_access_title">Access the app</string>
<string name="save_user_wallet_agreement_allow_biometrics">Allow to use biometrics</string>
@ -313,11 +314,7 @@
<string name="search_tokens_title">Search tokens</string>
<string name="send_amount_label">Amount</string>
<string name="send_destination_hint_address">Address</string>
<string name="send_destination_hint_address_payid">Address or PayString</string>
<string name="send_error_address_same_as_wallet">Address is the same as wallet address</string>
<string name="send_error_payid_not_registered">PayString not registered</string>
<string name="send_error_payid_request_failed">PayString request failed</string>
<string name="send_error_payid_unsupported_by_blockchain">PayString unsupported by blockchain</string>
<string name="send_extras_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction.</string>
<string name="send_extras_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction.</string>
<string name="send_extras_hint_destination_tag">Tag</string>
@ -329,7 +326,6 @@
<string name="send_fee_picker_priority">Priority</string>
<string name="send_max_amount_label">Maximum amount</string>
<string name="send_network_fee_title">Network fee</string>
<string name="send_title">Send</string>
<string name="send_title_currency_format">Sending %s</string>
<string name="send_total_label">Total</string>
<string name="send_total_subtitle_asset_format">%1$s and %2$s will be sent</string>
@ -346,6 +342,7 @@
<string name="solana_rent_warning">Solana network charges a rent of %1$s every 2 days. Accounts that can\'t afford the rent are purged from the network. Deposit your account with more than %2$s to use it for free.</string>
<string name="story_awe_description">Store your crypto assets secure while keeping private keys contained in your card</string>
<string name="story_awe_title">Revolutionary Hardware Wallet</string>
<string name="story_backup_description">Up to **3 physical cards** to one wallet</string>
<string name="story_backup_description_1">Up to</string>
<string name="story_backup_description_2_bold">3 physical cards</string>
<string name="story_backup_description_3">to one wallet</string>
@ -354,6 +351,9 @@
<string name="story_currencies_title">Thousands of Currencies</string>
<string name="story_finish_description">Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto.</string>
<string name="story_finish_title">The Wallet for Everyone</string>
<string name="story_learn_description">Complete the training, get the opportunity to buy Tangem wallet with a discount and receive 1inch tokens on your wallet</string>
<string name="story_learn_learn">Learn</string>
<string name="story_learn_title">Learn and get a bonus</string>
<string name="story_meet_borrow">Borrow</string>
<string name="story_meet_buy">Buy</string>
<string name="story_meet_exchange">Exchange</string>
@ -404,6 +404,7 @@
<string name="token_details_hide_token">Hide token</string>
<string name="token_details_send_blocked_fee_format">%1$s is a token in the %2$s network. To make a %3$s transaction you need to deposit some %4$s (%5$s) to cover the network fee.</string>
<string name="token_details_send_blocked_tx_format">Please wait for %s transaction to complete to be able to send funds</string>
<string name="token_details_token_type_subtitle">%1$s token in %%image%% %2$s network</string>
<string name="token_details_unable_hide_alert_message">The %1$s token is the main currency on the %2$s network and cannot be hidden as long as you have other tokens on this network in the list.</string>
<string name="token_details_unable_hide_alert_title">Unable to hide %s</string>
<string name="token_item_no_rate">No rate</string>
@ -438,7 +439,6 @@
<string name="user_wallet_list_single_header">Single-currency</string>
<string name="user_wallet_list_title">My Wallets</string>
<string name="user_wallet_list_unlock_all">Unlock all with %s</string>
<string name="wallet_address_button_create_payid">Create PayString</string>
<string name="wallet_address_button_explore">Transaction history</string>
<string name="wallet_balance_blockchain_unreachable">Network is unreachable</string>
<string name="wallet_balance_blockchain_unreachable_try_later">Blockchain is unreachable. Try later</string>
@ -447,21 +447,26 @@
<string name="wallet_balance_tx_in_progress">Transaction is in progress…</string>
<string name="wallet_balance_verified">Verified Balance</string>
<string name="wallet_button_actions">Actions</string>
<string name="wallet_button_buy">Buy</string>
<string name="wallet_button_sell">Sell</string>
<string name="wallet_button_send">Send</string>
<string name="wallet_choose_trade_action">Do you want to buy or sell crypto?</string>
<string name="wallet_connect_alert_sign_message">Requesting to sign a message.\n\n%s</string>
<string name="wallet_connect_bnb_sign_message">Dapp %1$s, requesting to\nsign BNB transaction.\n\n%2$s</string>
<string name="wallet_connect_bnb_trade_order_message">Trade order for %1$s\nPrice: %2$s\nAmount to receive: %3$s\nAmount to pay: %4$s</string>
<string name="wallet_connect_bnb_transaction_message">Transaction details:\nFrom: %1$s\nTo: %2$s\nAmount: %3$s</string>
<string name="wallet_connect_bnb_transaction_signed">The BNB transaction has been successfully signed and sent to the Dapp</string>
<string name="wallet_connect_clipboard_alert">Clipboard contain WalletConnect code. Use copied value or scan QR-code</string>
<string name="wallet_connect_create_tx_message">Request to create transaction for %1$s\n%2$s\n\nAmount: %3$s\nFee: %4$s\nTotal: %5$s\nBalance: %6$s</string>
<string name="wallet_connect_create_tx_not_enough_funds">Can\'t send transaction. Not enough funds.</string>
<string name="wallet_connect_error_failed_to_connect">Failed to establish WalletConnect session. Please, try again later.</string>
<string name="wallet_connect_error_missing_blockchains">Not all tokens were added to your list. Please add them first and try again. Missing tokens:\n</string>
<string name="wallet_connect_error_sing_failed">Failed to sign message.\nPlease, try again</string>
<string name="wallet_connect_error_timeout">Failed to establish WalletConnect session: timeout error. Please, try again later.</string>
<string name="wallet_connect_error_unsupported_blockchains">Session request contains unsupported blockchains for WalletConnect connection. Unsupported blockchains:\n</string>
<string name="wallet_connect_error_unsupported_dapp">Connection with this Dapp cannot be established due to its technical implementation.</string>
<string name="wallet_connect_error_with_framework_message">We\'ve encountered unknown error. Error message: %s. If the problem persists — feel free to contact our support</string>
<string name="wallet_connect_error_wrong_card_selected">Wrong card selected in Tangem App</string>
<string name="wallet_connect_failed_to_build_tx">Failed to create transaction from Dapp data. Code: %s</string>
<string name="wallet_connect_generic_error_with_code">We\'ve encountered unknown error. Error code: %d. If the problem persists — feel free to contact our support</string>
<string name="wallet_connect_message_signed">The message has been successfully signed and sent to the Dapp</string>
<string name="wallet_connect_network_not_found_format">%s network not found. Please, add it first and try again.</string>
<string name="wallet_connect_paste_from_clipboard">Paste from clipboard</string>
<string name="wallet_connect_request_session_start">Request to start a session for\n%1$s\n\nNETWORK: %2$s\n\nURL: %3$s</string>
@ -470,8 +475,12 @@
<string name="wallet_connect_scanner_error_not_valid_card">This card can\'t be used to establish WalletConnect session</string>
<string name="wallet_connect_scanner_error_unsupported_network">This network is not supported. Please select another network.</string>
<string name="wallet_connect_select_network">Select network</string>
<string name="wallet_connect_service_no_chain_id">Dapp didn\'t provide essential data to establish WalletConnect session</string>
<string name="wallet_connect_subtitle">Connect to Dapps</string>
<string name="wallet_connect_title">WalletConnect</string>
<string name="wallet_connect_transaction_signed">The transaction has been successfully signed and sent to the Dapp</string>
<string name="wallet_connect_transaction_signed_and_send">The transaction has been succesfully signed and sent to the blockchain</string>
<string name="wallet_connect_tx_not_found">Failed to find transaction hash</string>
<string name="wallet_currency_subtitle">%s network</string>
<string name="wallet_error_no_account">Account is not created</string>
<string name="wallet_error_unsupported_blockchain">This card is not supported</string>

View file

@ -2,19 +2,17 @@ package com.tangem.core.ui.components
import androidx.annotation.DrawableRes
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R
import com.tangem.core.ui.components.buttons.common.TangemButton
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
import com.tangem.core.ui.res.TangemTheme
// region TextButton
@ -26,7 +24,7 @@ fun TextButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier,
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.None,
icon = TangemButtonIconPosition.None,
onClick = onClick,
enabled = enabled,
showProgress = false,
@ -49,7 +47,7 @@ fun TextButtonIconStart(
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Start(iconResId),
icon = TangemButtonIconPosition.Start(iconResId),
onClick = onClick,
enabled = enabled,
showProgress = false,
@ -63,7 +61,7 @@ fun WarningTextButton(text: String, onClick: () -> Unit, modifier: Modifier = Mo
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.None,
icon = TangemButtonIconPosition.None,
onClick = onClick,
enabled = enabled,
showProgress = false,
@ -85,7 +83,7 @@ fun PrimaryButton(
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.None,
icon = TangemButtonIconPosition.None,
onClick = onClick,
colors = TangemButtonsDefaults.primaryButtonColors,
enabled = enabled,
@ -108,7 +106,7 @@ fun PrimaryButtonIconEnd(
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.End(iconResId),
icon = TangemButtonIconPosition.End(iconResId),
onClick = onClick,
colors = TangemButtonsDefaults.primaryButtonColors,
enabled = enabled,
@ -131,7 +129,7 @@ fun PrimaryButtonIconStart(
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Start(iconResId),
icon = TangemButtonIconPosition.Start(iconResId),
onClick = onClick,
colors = TangemButtonsDefaults.primaryButtonColors,
enabled = enabled,
@ -152,7 +150,7 @@ fun SecondaryButton(
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.None,
icon = TangemButtonIconPosition.None,
onClick = onClick,
colors = TangemButtonsDefaults.secondaryButtonColors,
enabled = enabled,
@ -175,7 +173,7 @@ fun SecondaryButtonIconEnd(
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.End(iconResId),
icon = TangemButtonIconPosition.End(iconResId),
onClick = onClick,
colors = TangemButtonsDefaults.secondaryButtonColors,
enabled = enabled,
@ -198,7 +196,7 @@ fun SecondaryButtonIconStart(
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Start(iconResId),
icon = TangemButtonIconPosition.Start(iconResId),
onClick = onClick,
colors = TangemButtonsDefaults.secondaryButtonColors,
enabled = enabled,
@ -214,7 +212,7 @@ fun SelectorButton(text: String, onClick: () -> Unit, modifier: Modifier = Modif
modifier = modifier,
text = text,
textStyle = TangemTheme.typography.subtitle2,
icon = TangemButtonIcon.End(iconResId = R.drawable.ic_chevron_24),
icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24),
onClick = onClick,
colors = TangemButtonsDefaults.selectorButtonColors,
showProgress = false,
@ -224,362 +222,6 @@ fun SelectorButton(text: String, onClick: () -> Unit, modifier: Modifier = Modif
}
// endregion Other
// region Action
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=290-305&t=3z98eFnTeyIx5TH5-4)
* */
@Composable
fun RoundedActionButton(
text: String,
@DrawableRes iconResId: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Start(iconResId),
onClick = onClick,
enabled = enabled,
showProgress = false,
colors = TangemButtonsDefaults.secondaryButtonColors,
size = TangemButtonSize.RoundedAction,
)
}
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=1208-1395&t=3z98eFnTeyIx5TH5-4)
* */
@Composable
fun ActionButton(
text: String,
@DrawableRes iconResId: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Start(iconResId),
onClick = onClick,
enabled = enabled,
showProgress = false,
colors = TangemButtonsDefaults.secondaryButtonColors,
size = TangemButtonSize.Action,
)
}
/**
* Same as [RoundedActionButton] but colored in primary background color
* */
@Composable
fun BackgroundActionButton(
text: String,
@DrawableRes iconResId: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Start(iconResId),
onClick = onClick,
enabled = enabled,
showProgress = false,
colors = TangemButtonsDefaults.backgroundButtonColors,
size = TangemButtonSize.RoundedAction,
)
}
// endregion Action
// region Defaults
@Suppress("LongParameterList")
@Composable
private fun TangemButton(
text: String,
icon: TangemButtonIcon,
onClick: () -> Unit,
colors: ButtonColors,
showProgress: Boolean,
enabled: Boolean,
modifier: Modifier = Modifier,
size: TangemButtonSize = TangemButtonSize.Default,
elevation: ButtonElevation = TangemButtonsDefaults.elevation,
textStyle: TextStyle = TangemTheme.typography.button,
) {
Button(
modifier = modifier.heightIn(min = size.toHeightDp()),
onClick = { if (!showProgress) onClick() },
enabled = enabled,
elevation = elevation,
shape = size.toShape(),
colors = colors,
contentPadding = size.toContentPadding(icon = icon),
) {
ButtonContent(
text = text,
textStyle = textStyle,
buttonIcon = icon,
colors = colors,
showProgress = showProgress,
enabled = enabled,
size = size,
)
}
}
@Suppress("LongParameterList")
@Composable
private fun ButtonContent(
text: String,
textStyle: TextStyle,
buttonIcon: TangemButtonIcon,
colors: ButtonColors,
size: TangemButtonSize,
enabled: Boolean,
showProgress: Boolean,
) {
val icon = @Composable { iconResId: Int ->
Icon(
modifier = Modifier.size(TangemTheme.dimens.size20),
painter = painterResource(id = iconResId),
tint = colors.contentColor(enabled = enabled).value,
contentDescription = null,
)
}
if (showProgress) {
Box(modifier = Modifier.wrapContentSize()) {
CircularProgressIndicator(
modifier = Modifier
.align(Alignment.Center)
.size(TangemTheme.dimens.size24),
color = colors.contentColor(enabled = enabled).value,
strokeWidth = TangemTheme.dimens.size4,
)
}
} else {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(size.toIconPadding()),
) {
if (buttonIcon is TangemButtonIcon.Start) {
icon(buttonIcon.iconResId)
}
Text(
text = text,
style = textStyle,
color = colors.contentColor(enabled = enabled).value,
maxLines = 1,
)
if (buttonIcon is TangemButtonIcon.End) {
icon(buttonIcon.iconResId)
}
}
}
}
@Immutable
private sealed interface TangemButtonIcon {
val iconResId: Int?
data class Start(override val iconResId: Int) : TangemButtonIcon
data class End(override val iconResId: Int) : TangemButtonIcon
object None : TangemButtonIcon {
override val iconResId: Int? = null
}
}
private enum class TangemButtonSize {
Default,
Text,
Selector,
Action,
RoundedAction,
}
@Composable
@ReadOnlyComposable
private fun TangemButtonSize.toHeightDp(): Dp = when (this) {
TangemButtonSize.Default -> TangemTheme.dimens.size48
TangemButtonSize.Text -> TangemTheme.dimens.size40
TangemButtonSize.Selector -> TangemTheme.dimens.size24
TangemButtonSize.Action,
TangemButtonSize.RoundedAction,
-> TangemTheme.dimens.size36
}
@Composable
@ReadOnlyComposable
private fun TangemButtonSize.toShape(): Shape = when (this) {
TangemButtonSize.Default -> TangemTheme.shapes.roundedCornersMedium
TangemButtonSize.Text -> TangemTheme.shapes.roundedCornersSmall
TangemButtonSize.Selector -> TangemTheme.shapes.roundedCornersSmall
TangemButtonSize.Action -> TangemTheme.shapes.roundedCornersMedium
TangemButtonSize.RoundedAction -> TangemTheme.shapes.roundedCornersLarge
}
@Composable
@ReadOnlyComposable
private fun TangemButtonSize.toIconPadding(): Dp = when (this) {
TangemButtonSize.Default -> TangemTheme.dimens.spacing8
TangemButtonSize.Text -> TangemTheme.dimens.spacing8
TangemButtonSize.Selector -> 0.dp
TangemButtonSize.Action,
TangemButtonSize.RoundedAction,
-> TangemTheme.dimens.spacing8
}
@Composable
@ReadOnlyComposable
private fun TangemButtonSize.toContentPadding(icon: TangemButtonIcon): PaddingValues {
val horizontalPadding = this.toHorizontalContentPadding(icon = icon)
return when (this) {
TangemButtonSize.Default -> PaddingValues(
top = TangemTheme.dimens.spacing14,
bottom = TangemTheme.dimens.spacing14,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
TangemButtonSize.Text -> PaddingValues(
top = TangemTheme.dimens.spacing10,
bottom = TangemTheme.dimens.spacing10,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
TangemButtonSize.Selector -> PaddingValues(
top = TangemTheme.dimens.spacing0_5,
bottom = TangemTheme.dimens.spacing0_5,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
TangemButtonSize.Action,
TangemButtonSize.RoundedAction,
-> PaddingValues(
top = TangemTheme.dimens.spacing8,
bottom = TangemTheme.dimens.spacing8,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
}
}
@Composable
@ReadOnlyComposable
private fun TangemButtonSize.toHorizontalContentPadding(icon: TangemButtonIcon): Pair<Dp, Dp> {
return when (this) {
TangemButtonSize.Default -> TangemTheme.dimens.spacing32 to TangemTheme.dimens.spacing32
TangemButtonSize.Text -> when (icon) {
is TangemButtonIcon.None -> TangemTheme.dimens.spacing16 to TangemTheme.dimens.spacing16
is TangemButtonIcon.Start -> TangemTheme.dimens.spacing14 to TangemTheme.dimens.spacing16
is TangemButtonIcon.End -> TangemTheme.dimens.spacing16 to TangemTheme.dimens.spacing14
}
TangemButtonSize.Selector -> TangemTheme.dimens.spacing0_5 to TangemTheme.dimens.spacing0_5
TangemButtonSize.Action,
TangemButtonSize.RoundedAction,
-> when (icon) {
is TangemButtonIcon.None -> TangemTheme.dimens.spacing24 to TangemTheme.dimens.spacing24
is TangemButtonIcon.Start -> TangemTheme.dimens.spacing16 to TangemTheme.dimens.spacing24
is TangemButtonIcon.End -> TangemTheme.dimens.spacing24 to TangemTheme.dimens.spacing16
}
}
}
private object TangemButtonsDefaults {
val elevation: ButtonElevation
@Composable get() = ButtonDefaults
.elevation(
defaultElevation = TangemTheme.dimens.elevation0,
pressedElevation = TangemTheme.dimens.elevation0,
)
val primaryButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.button.primary,
contentColor = TangemTheme.colors.text.primary2,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val secondaryButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.button.secondary,
contentColor = TangemTheme.colors.text.primary1,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val defaultTextButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = Color.Transparent,
contentColor = TangemTheme.colors.text.secondary,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val warningTextButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = Color.Transparent,
contentColor = TangemTheme.colors.text.warning,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val selectorButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = Color.Transparent,
contentColor = TangemTheme.colors.text.tertiary,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val backgroundButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.background.primary,
contentColor = TangemTheme.colors.text.primary1,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
}
@Immutable
private open class TangemButtonColors(
private val backgroundColor: Color,
private val contentColor: Color,
private val disabledBackgroundColor: Color,
private val disabledContentColor: Color,
) : ButtonColors {
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(newValue = if (enabled) backgroundColor else disabledBackgroundColor)
}
@Composable
override fun contentColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(newValue = if (enabled) contentColor else disabledContentColor)
}
}
// endregion Defaults
// region Preview
@Composable
private fun PrimaryButtonSample() {
@ -730,34 +372,4 @@ private fun TextButtonPreview_DarkTheme() {
}
}
@Composable
private fun ActionButtonSample() {
Column(
modifier = Modifier.background(TangemTheme.colors.background.primary),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
RoundedActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, onClick = { })
ActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, onClick = { })
BackgroundActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, onClick = { })
RoundedActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, enabled = false, onClick = { })
ActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, enabled = false, onClick = { })
BackgroundActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, enabled = false, onClick = { })
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun ActionButtonPreview_LightTheme() {
TangemTheme {
ActionButtonSample()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun ActionButtonPreview_DarkTheme() {
TangemTheme(isDark = true) {
ActionButtonSample()
}
}
// endregion Preview

View file

@ -1,202 +0,0 @@
package com.tangem.core.ui.components
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
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.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.res.TangemTheme
/**
* Closable notification with custom icon
* Child of parent component
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=1045-807&t=6CVvYDJe0sB7wBKE-0">Figma component</a>
*
* Use to show banner with custom icon and possibility to close
* i.e. Feedback notification
*
* @param title notification title
* @param icon drawable res on icon
* @param iconColor icon color
* @param onClick callback on click
* @param onCloseClick callback on close icon click
*/
@Composable
fun ClosableNotification(
title: String,
@DrawableRes icon: Int,
iconColor: Color,
onClick: (() -> Unit),
onCloseClick: (() -> Unit),
) {
NotificationCardTemplate(onClick) {
Icon(
modifier = Modifier
.size(TangemTheme.dimens.size20)
.align(Alignment.CenterStart),
painter = painterResource(id = icon),
tint = iconColor,
contentDescription = null,
)
Text(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing28)
.align(Alignment.CenterStart),
text = title,
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.subtitle2,
)
Icon(
modifier = Modifier
.size(TangemTheme.dimens.size20)
.align(Alignment.CenterEnd)
.clickable(onClick = onCloseClick),
painter = painterResource(id = R.drawable.ic_close_24),
contentDescription = null,
tint = TangemTheme.colors.icon.informative,
)
}
}
/**
* Notification component from Design system
* There are few states for this component, but only one parent, see link below
*
* Use this for Notification with title, subtitle, clickable or not
*
* @param title notification title
* @param subtitle notification subtitle
* @param onClick click on notification, if its null then no chevron icon
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=1045-807&t=6CVvYDJe0sB7wBKE-0">Figma component</a>
*/
@Composable
fun WarningNotification(title: String, subtitle: String?, onClick: (() -> Unit)?) {
NotificationCardTemplate(onClick) {
Image(
modifier = Modifier
.size(TangemTheme.dimens.size20)
.align(Alignment.CenterStart),
painter = painterResource(id = R.drawable.img_attention_20),
contentDescription = null,
)
Column(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing28)
.align(Alignment.CenterStart),
) {
Text(
text = title,
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.subtitle2,
)
if (!subtitle.isNullOrEmpty()) {
SpacerH2()
Text(
text = subtitle,
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.caption,
)
}
}
if (onClick != null) {
Icon(
modifier = Modifier
.size(TangemTheme.dimens.size20)
.align(Alignment.CenterEnd),
painter = painterResource(id = R.drawable.ic_chevron_right_24),
contentDescription = null,
tint = TangemTheme.colors.icon.informative,
)
}
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun NotificationCardTemplate(onClick: (() -> Unit)? = null, content: @Composable BoxScope.() -> Unit) {
Surface(
color = TangemTheme.colors.button.secondary,
shape = RoundedCornerShape(TangemTheme.dimens.radius18),
onClick = onClick ?: {},
enabled = onClick != null,
) {
Box(
Modifier
.padding(
horizontal = TangemTheme.dimens.spacing12,
vertical = TangemTheme.dimens.spacing8,
)
.wrapContentSize(),
) {
content()
}
}
}
// region Preview
@Composable
private fun WarningNotificationPreview() {
Column(modifier = Modifier.fillMaxWidth()) {
WarningNotification(
title = "Your wallet hasnt been backed up",
subtitle = "Lorem ipsum dolor sit amet, consectetur " +
"adipiscing elit, sed do eiusmod tempor incididunt ut labore et...",
onClick = {},
)
SpacerH32()
WarningNotification(
title = "Your wallet hasnt been backed up",
subtitle = null,
onClick = {},
)
SpacerH32()
WarningNotification(
title = "Your wallet hasnt been backed up",
subtitle = "Lorem ipsum dolor sit amet, consectetur " +
"adipiscing elit, sed do eiusmod tempor incididunt ut labore et...",
onClick = null,
)
SpacerH32()
WarningNotification(
title = "Your wallet hasnt been backed up",
subtitle = null,
onClick = null,
)
SpacerH32()
ClosableNotification(
title = "Like tangem app?",
icon = R.drawable.ic_star_24,
iconColor = TangemTheme.colors.icon.attention,
onClick = {},
onCloseClick = {},
)
}
}
@Preview(showBackground = true)
@Composable
private fun Preview_WarningNotification_InLightTheme() {
TangemTheme(isDark = false) {
WarningNotificationPreview()
}
}
@Preview(showBackground = true)
@Composable
private fun Preview_WarningNotification_InDarkTheme() {
TangemTheme(isDark = true) {
WarningNotificationPreview()
}
}
// endregion Preview

View file

@ -0,0 +1,20 @@
package com.tangem.core.ui.components.buttons.actions
import androidx.annotation.DrawableRes
/**
* Action button config
*
* @property text text
* @property iconResId icon resource id
* @property onClick lambda be invoked when action component is clicked
* @property enabled enabled
*
[REDACTED_AUTHOR]
*/
data class ActionConfig(
val text: String,
@DrawableRes val iconResId: Int,
val onClick: () -> Unit,
val enabled: Boolean = true,
)

View file

@ -0,0 +1,96 @@
package com.tangem.core.ui.components.buttons.actions
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.buttons.common.TangemButton
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
import com.tangem.core.ui.res.TangemTheme
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=290-305&t=3z98eFnTeyIx5TH5-4)
*/
@Composable
fun RoundedActionButton(config: ActionConfig, modifier: Modifier = Modifier) {
TangemButton(
modifier = modifier,
text = config.text,
icon = TangemButtonIconPosition.Start(config.iconResId),
onClick = config.onClick,
enabled = config.enabled,
showProgress = false,
colors = TangemButtonsDefaults.secondaryButtonColors,
size = TangemButtonSize.RoundedAction,
)
}
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=1208-1395&t=3z98eFnTeyIx5TH5-4)
*/
@Composable
fun ActionButton(config: ActionConfig, modifier: Modifier = Modifier) {
TangemButton(
modifier = modifier,
text = config.text,
icon = TangemButtonIconPosition.Start(config.iconResId),
onClick = config.onClick,
enabled = config.enabled,
showProgress = false,
colors = TangemButtonsDefaults.secondaryButtonColors,
size = TangemButtonSize.Action,
)
}
/**
* Same as [RoundedActionButton] but colored in primary background color
*/
@Composable
fun BackgroundActionButton(config: ActionConfig, modifier: Modifier = Modifier) {
TangemButton(
modifier = modifier,
text = config.text,
icon = TangemButtonIconPosition.Start(config.iconResId),
onClick = config.onClick,
enabled = config.enabled,
showProgress = false,
colors = TangemButtonsDefaults.backgroundButtonColors,
size = TangemButtonSize.RoundedAction,
)
}
@Preview(showBackground = true)
@Composable
private fun Preview_ActionButton_Light(@PreviewParameter(ActionStateProvider::class) state: ActionConfig) {
TangemTheme(isDark = false) {
Column {
RoundedActionButton(state)
ActionButton(state)
BackgroundActionButton(state)
}
}
}
@Preview(showBackground = true)
@Composable
private fun Preview_ActionButton_Dark(@PreviewParameter(ActionStateProvider::class) state: ActionConfig) {
TangemTheme {
Column {
RoundedActionButton(state)
ActionButton(state)
BackgroundActionButton(state)
}
}
}
private class ActionStateProvider : CollectionPreviewParameterProvider<ActionConfig>(
collection = listOf(
ActionConfig(text = "Send", iconResId = R.drawable.ic_arrow_up_24, onClick = {}),
ActionConfig(text = "Receive", iconResId = R.drawable.ic_arrow_down_24, enabled = false, onClick = {}),
),
)

View file

@ -0,0 +1,96 @@
package com.tangem.core.ui.components.buttons.common
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import com.tangem.core.ui.res.TangemTheme
@Suppress("LongParameterList")
@Composable
internal fun TangemButton(
text: String,
icon: TangemButtonIconPosition,
onClick: () -> Unit,
colors: ButtonColors,
showProgress: Boolean,
enabled: Boolean,
modifier: Modifier = Modifier,
size: TangemButtonSize = TangemButtonSize.Default,
elevation: ButtonElevation = TangemButtonsDefaults.elevation,
textStyle: TextStyle = TangemTheme.typography.button,
) {
Button(
modifier = modifier.heightIn(min = size.toHeightDp()),
onClick = { if (!showProgress) onClick() },
enabled = enabled,
elevation = elevation,
shape = size.toShape(),
colors = colors,
contentPadding = size.toContentPadding(icon = icon),
) {
ButtonContent(
text = text,
textStyle = textStyle,
buttonIcon = icon,
colors = colors,
showProgress = showProgress,
enabled = enabled,
size = size,
)
}
}
@Suppress("LongParameterList")
@Composable
private fun ButtonContent(
text: String,
textStyle: TextStyle,
buttonIcon: TangemButtonIconPosition,
colors: ButtonColors,
size: TangemButtonSize,
enabled: Boolean,
showProgress: Boolean,
) {
val icon = @Composable { iconResId: Int ->
Icon(
modifier = Modifier.size(TangemTheme.dimens.size20),
painter = painterResource(id = iconResId),
tint = colors.contentColor(enabled = enabled).value,
contentDescription = null,
)
}
if (showProgress) {
Box(modifier = Modifier.wrapContentSize()) {
CircularProgressIndicator(
modifier = Modifier
.align(Alignment.Center)
.size(TangemTheme.dimens.size24),
color = colors.contentColor(enabled = enabled).value,
strokeWidth = TangemTheme.dimens.size4,
)
}
} else {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(size.toIconPadding()),
) {
if (buttonIcon is TangemButtonIconPosition.Start) {
icon(buttonIcon.iconResId)
}
Text(
text = text,
style = textStyle,
color = colors.contentColor(enabled = enabled).value,
maxLines = 1,
)
if (buttonIcon is TangemButtonIconPosition.End) {
icon(buttonIcon.iconResId)
}
}
}
}

View file

@ -0,0 +1,25 @@
package com.tangem.core.ui.components.buttons.common
import androidx.compose.material.ButtonColors
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.graphics.Color
internal class TangemButtonColors(
private val backgroundColor: Color,
private val contentColor: Color,
private val disabledBackgroundColor: Color,
private val disabledContentColor: Color,
) : ButtonColors {
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(newValue = if (enabled) backgroundColor else disabledBackgroundColor)
}
@Composable
override fun contentColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(newValue = if (enabled) contentColor else disabledContentColor)
}
}

View file

@ -0,0 +1,16 @@
package com.tangem.core.ui.components.buttons.common
import androidx.annotation.DrawableRes
internal sealed interface TangemButtonIconPosition {
val iconResId: Int?
data class Start(@DrawableRes override val iconResId: Int) : TangemButtonIconPosition
data class End(@DrawableRes override val iconResId: Int) : TangemButtonIconPosition
object None : TangemButtonIconPosition {
@DrawableRes
override val iconResId: Int? = null
}
}

View file

@ -0,0 +1,105 @@
package com.tangem.core.ui.components.buttons.common
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.res.TangemTheme
internal enum class TangemButtonSize {
Default,
Text,
Selector,
Action,
RoundedAction,
}
@Composable
@ReadOnlyComposable
internal fun TangemButtonSize.toHeightDp(): Dp = when (this) {
TangemButtonSize.Default -> TangemTheme.dimens.size48
TangemButtonSize.Text -> TangemTheme.dimens.size40
TangemButtonSize.Selector -> TangemTheme.dimens.size24
TangemButtonSize.Action,
TangemButtonSize.RoundedAction,
-> TangemTheme.dimens.size36
}
@Composable
@ReadOnlyComposable
internal fun TangemButtonSize.toShape(): Shape = when (this) {
TangemButtonSize.Default -> TangemTheme.shapes.roundedCornersMedium
TangemButtonSize.Text -> TangemTheme.shapes.roundedCornersSmall
TangemButtonSize.Selector -> TangemTheme.shapes.roundedCornersSmall
TangemButtonSize.Action -> TangemTheme.shapes.roundedCornersMedium
TangemButtonSize.RoundedAction -> TangemTheme.shapes.roundedCornersLarge
}
@Composable
@ReadOnlyComposable
internal fun TangemButtonSize.toIconPadding(): Dp = when (this) {
TangemButtonSize.Default -> TangemTheme.dimens.spacing8
TangemButtonSize.Text -> TangemTheme.dimens.spacing8
TangemButtonSize.Selector -> 0.dp
TangemButtonSize.Action,
TangemButtonSize.RoundedAction,
-> TangemTheme.dimens.spacing8
}
@Composable
@ReadOnlyComposable
internal fun TangemButtonSize.toContentPadding(icon: TangemButtonIconPosition): PaddingValues {
val horizontalPadding = this.toHorizontalContentPadding(icon = icon)
return when (this) {
TangemButtonSize.Default -> PaddingValues(
top = TangemTheme.dimens.spacing14,
bottom = TangemTheme.dimens.spacing14,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
TangemButtonSize.Text -> PaddingValues(
top = TangemTheme.dimens.spacing10,
bottom = TangemTheme.dimens.spacing10,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
TangemButtonSize.Selector -> PaddingValues(
top = TangemTheme.dimens.spacing0_5,
bottom = TangemTheme.dimens.spacing0_5,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
TangemButtonSize.Action,
TangemButtonSize.RoundedAction,
-> PaddingValues(
top = TangemTheme.dimens.spacing8,
bottom = TangemTheme.dimens.spacing8,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
}
}
@Composable
@ReadOnlyComposable
internal fun TangemButtonSize.toHorizontalContentPadding(icon: TangemButtonIconPosition): Pair<Dp, Dp> {
return when (this) {
TangemButtonSize.Default -> TangemTheme.dimens.spacing32 to TangemTheme.dimens.spacing32
TangemButtonSize.Text -> when (icon) {
is TangemButtonIconPosition.None -> TangemTheme.dimens.spacing16 to TangemTheme.dimens.spacing16
is TangemButtonIconPosition.Start -> TangemTheme.dimens.spacing14 to TangemTheme.dimens.spacing16
is TangemButtonIconPosition.End -> TangemTheme.dimens.spacing16 to TangemTheme.dimens.spacing14
}
TangemButtonSize.Selector -> TangemTheme.dimens.spacing0_5 to TangemTheme.dimens.spacing0_5
TangemButtonSize.Action,
TangemButtonSize.RoundedAction,
-> when (icon) {
is TangemButtonIconPosition.None -> TangemTheme.dimens.spacing24 to TangemTheme.dimens.spacing24
is TangemButtonIconPosition.Start -> TangemTheme.dimens.spacing16 to TangemTheme.dimens.spacing24
is TangemButtonIconPosition.End -> TangemTheme.dimens.spacing24 to TangemTheme.dimens.spacing16
}
}
}

View file

@ -0,0 +1,78 @@
package com.tangem.core.ui.components.buttons.common
import androidx.compose.material.ButtonColors
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.ButtonElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.graphics.Color
import com.tangem.core.ui.res.TangemTheme
internal object TangemButtonsDefaults {
val elevation: ButtonElevation
@Composable get() = ButtonDefaults.elevation(
defaultElevation = TangemTheme.dimens.elevation0,
pressedElevation = TangemTheme.dimens.elevation0,
)
val primaryButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.button.primary,
contentColor = TangemTheme.colors.text.primary2,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val secondaryButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.button.secondary,
contentColor = TangemTheme.colors.text.primary1,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val defaultTextButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = Color.Transparent,
contentColor = TangemTheme.colors.text.secondary,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val warningTextButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = Color.Transparent,
contentColor = TangemTheme.colors.text.warning,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val selectorButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = Color.Transparent,
contentColor = TangemTheme.colors.text.tertiary,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val backgroundButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.background.primary,
contentColor = TangemTheme.colors.text.primary1,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
}

View file

@ -0,0 +1,171 @@
package com.tangem.core.ui.components.notifications
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
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.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SpacerH2
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
/**
* Notification component from Design system.
* Use this for Notification with title, subtitle, clickable or not.
*
* @param state component state
* @param modifier modifier
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=1045-807&t=6CVvYDJe0sB7wBKE-0"
* >Figma component</a>
*/
@Composable
fun Notification(state: NotificationState, modifier: Modifier = Modifier) {
Surface(
onClick = if (state is NotificationState.Action) {
state.onClick
} else {
{}
},
modifier = modifier,
enabled = when (state) {
is NotificationState.Simple -> false
is NotificationState.Action -> true
},
shape = RoundedCornerShape(TangemTheme.dimens.radius18),
color = TangemTheme.colors.button.secondary,
) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = TangemTheme.dimens.spacing12, vertical = TangemTheme.dimens.spacing8),
) {
NotificationIcon(
iconResId = state.iconResId,
iconTint = state.tint,
modifier = Modifier
.size(size = TangemTheme.dimens.size20)
.align(alignment = Alignment.CenterStart),
)
NotificationInfoBlock(
title = state.title,
subtitle = state.subtitle,
modifier = Modifier.align(alignment = Alignment.CenterStart),
)
if (state is NotificationState.Action) {
Icon(
modifier = Modifier
.size(size = TangemTheme.dimens.size20)
.align(alignment = Alignment.CenterEnd),
painter = painterResource(id = R.drawable.ic_chevron_right_24),
contentDescription = null,
tint = TangemTheme.colors.icon.informative,
)
}
}
}
}
@Composable
private fun NotificationIcon(@DrawableRes iconResId: Int, iconTint: Color?, modifier: Modifier = Modifier) {
if (iconTint != null) {
Icon(
painter = painterResource(id = iconResId),
contentDescription = null,
modifier = modifier,
tint = iconTint,
)
} else {
Image(
painter = painterResource(id = iconResId),
contentDescription = null,
modifier = modifier,
)
}
}
@Composable
private fun NotificationInfoBlock(title: String, subtitle: String?, modifier: Modifier = Modifier) {
Column(modifier = modifier.padding(horizontal = TangemTheme.dimens.spacing30)) {
Text(
text = title,
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.body2,
)
if (!subtitle.isNullOrEmpty()) {
SpacerH2()
Text(
text = subtitle,
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.caption,
)
}
}
}
@Preview
@Composable
private fun Preview_WarningNotification_Light(
@PreviewParameter(NotificationStateProvider::class)
state: NotificationState,
) {
TangemTheme(isDark = false) {
Notification(state)
}
}
@Preview
@Composable
private fun Preview_WarningNotification_Dark(
@PreviewParameter(NotificationStateProvider::class)
state: NotificationState,
) {
TangemTheme(isDark = true) {
Notification(state)
}
}
private class NotificationStateProvider : CollectionPreviewParameterProvider<NotificationState>(
collection = listOf(
NotificationState.Simple(
title = "Your wallet hasnt been backed up",
subtitle = "Lorem ipsum dolor sit amet, consectetur " +
"adipiscing elit, sed do eiusmod tempor incididunt ut labore et...",
iconResId = R.drawable.img_attention_20,
),
NotificationState.Simple(
title = "Your wallet hasnt been backed up",
subtitle = null,
iconResId = R.drawable.ic_alert_circle_24,
tint = TangemColorPalette.Amaranth,
),
NotificationState.Action(
title = "Your wallet hasnt been backed up",
subtitle = "Lorem ipsum dolor sit amet, consectetur " +
"adipiscing elit, sed do eiusmod tempor incididunt ut labore et...",
iconResId = R.drawable.img_attention_20,
onClick = {},
),
NotificationState.Action(
title = "Your wallet hasnt been backed up",
subtitle = null,
iconResId = R.drawable.ic_alert_circle_24,
tint = TangemColorPalette.Amaranth,
onClick = {},
),
),
)

View file

@ -0,0 +1,54 @@
package com.tangem.core.ui.components.notifications
import androidx.annotation.DrawableRes
import androidx.compose.ui.graphics.Color
/**
* Notification component state
*
* @property title title
* @property subtitle subtitle
* @property iconResId icon resource id
* @property tint icon tint
*
[REDACTED_AUTHOR]
*/
sealed class NotificationState(
open val title: String,
open val subtitle: String? = null,
@DrawableRes open val iconResId: Int,
open val tint: Color? = null,
) {
/**
* Simple notification state. Non clickable.
*
* @property title title
* @property subtitle subtitle
* @property iconResId icon resource id
* @property tint icon tint
*/
data class Simple(
override val title: String,
override val subtitle: String? = null,
@DrawableRes override val iconResId: Int,
override val tint: Color? = null,
) : NotificationState(title, subtitle, iconResId, tint)
/**
* Clickable notification state
*
* @property title title
* @property subtitle subtitle
* @property iconResId icon resource id
* @property tint icon tint
* @param onClick lambda be invoked when notification component is clicked
*/
data class Action(
override val title: String,
override val subtitle: String? = null,
@DrawableRes override val iconResId: Int,
override val tint: Color? = null,
val onClick: () -> Unit,
) : NotificationState(title, subtitle, iconResId, tint)
}

View file

@ -1,9 +1,11 @@
package com.tangem.core.ui.extensions
import androidx.annotation.PluralsRes
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
/**
@ -24,6 +26,8 @@ sealed interface TextReference {
*/
data class Res(@StringRes val id: Int, val formatArgs: WrappedList<Any> = WrappedList(emptyList())) : TextReference
data class PluralRes(@PluralsRes val id: Int, val count: Int, val formatArgs: WrappedList<Any>) : TextReference
/**
* Text string
*
@ -38,6 +42,7 @@ sealed interface TextReference {
fun TextReference.resolveReference(): String {
return when (this) {
is TextReference.Res -> stringResource(id, *formatArgs.toTypedArray())
is TextReference.PluralRes -> pluralStringResource(id, count, *formatArgs.toTypedArray())
is TextReference.Str -> value
}
}

View file

@ -76,6 +76,7 @@ data class TangemDimens internal constructor(
val size200: Dp = 200.dp,
// endregion Size
// region Spacing
val spacing0: Dp = 0.dp,
val spacing0_5: Dp = 0.5.dp,
val spacing2: Dp = 2.dp,
val spacing4: Dp = 4.dp,
@ -91,6 +92,7 @@ data class TangemDimens internal constructor(
val spacing24: Dp = 24.dp,
val spacing26: Dp = 26.dp,
val spacing28: Dp = 28.dp,
val spacing30: Dp = 30.dp,
val spacing32: Dp = 32.dp,
val spacing34: Dp = 34.dp,
val spacing36: Dp = 34.dp,

View file

@ -0,0 +1,10 @@
package com.tangem.utils.extensions
import java.lang.ref.WeakReference
/**
[REDACTED_AUTHOR]
*/
fun <T> T.toWeakReference(): WeakReference<T> {
return WeakReference(this)
}