Updated on 2026-08-14
This commit is contained in:
parent
6796e868c6
commit
ef389a6735
22 changed files with 867 additions and 36 deletions
|
|
@ -89,6 +89,12 @@
|
|||
<string name="common_exchange">Обменять</string>
|
||||
<string name="common_explore_transaction_history">Посмотреть историю транзакций</string>
|
||||
<string name="common_explorer">Обозреватель</string>
|
||||
<string name="common_fee_selector_title">Скорость и комиссия</string>
|
||||
<string name="common_fee_selector_footer">Сетевые комиссии за транзакции используются для поддержки безопасности сети, поощрения валидаторов, выделения ресурсов и определения приоритета транзакции.</string>
|
||||
<string name="common_fee_selector_option_slow">Медленно</string>
|
||||
<string name="common_fee_selector_option_market">По рынку</string>
|
||||
<string name="common_fee_selector_option_fast">Быстро</string>
|
||||
<string name="common_fee_selector_option_custom">Свое</string>
|
||||
<string name="common_generate_addresses">Сгенерировать адреса</string>
|
||||
<string name="common_import">Импортировать</string>
|
||||
<string name="common_like">Нравится</string>
|
||||
|
|
@ -100,6 +106,7 @@
|
|||
<string name="common_no_data">Нет данных</string>
|
||||
<string name="common_ok">OK</string>
|
||||
<string name="common_origin_card">Основная карта</string>
|
||||
<string name="common_paste">Вставить</string>
|
||||
<string name="common_receive">Получить</string>
|
||||
<string name="common_reject">Отклонить</string>
|
||||
<string name="common_reload">Перезагрузить</string>
|
||||
|
|
@ -384,19 +391,52 @@
|
|||
<string name="scan_card_settings_message">Отсканируйте карту, чтобы изменить ее настройки. Изменения затронут только ту карту, которую вы отсканировали, и не повлияют на другие карты, привязанные к вашему кошельку.</string>
|
||||
<string name="scan_card_settings_title">Приготовьте свою карту</string>
|
||||
<string name="send_amount_label">Сумма</string>
|
||||
<string name="send_amount_substract">Вычесть из суммы отправки</string>
|
||||
<string name="send_amount_substract_footer">Сумма к получению %1$s</string>
|
||||
<string name="send_destination_hint_address">Адрес</string>
|
||||
<string name="send_destination_tag_field">Код назначения</string>
|
||||
<string name="send_datetime_formatter">%1$s в %2$s</string>
|
||||
<string name="send_enter_address_field">Введите адрес</string>
|
||||
<string name="send_error_address_same_as_wallet">Адрес совпадает с адресом кошелька</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>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_recent_transactions">Последние</string>
|
||||
<string name="send_recipient_address_footer">Убедитесь, что вы отправляете средства на адрес кошелька %1$s. Ошибки могут привести к потере ваших токенов.</string>
|
||||
<string name="send_recipient_memo_footer">Мемо/Код назначения - это код, разделяющий транзакции к общему получателю в сети криптовалют. Внимание: отсутствие мемо может привести к потере средств.</string>
|
||||
<string name="send_fee_include_description">Включая комиссию</string>
|
||||
<string name="send_fee_label">Комиссия</string>
|
||||
<string name="send_fee_picker_low">Низкая</string>
|
||||
<string name="send_fee_picker_normal">Нормальная</string>
|
||||
<string name="send_fee_picker_priority">Приоритетная</string>
|
||||
<string name="send_gas_price">Цена газа</string>
|
||||
<string name="send_gas_price_footer">Цена газа влияет на скорость транзакции. При сильно низкой, транзакция может быть не обработана.</string>
|
||||
<string name="send_gas_limit">Лимит газа</string>
|
||||
<string name="send_max_amount_label">Максимальная сумма</string>
|
||||
<string name="send_max_amount">Всё</string>
|
||||
<string name="send_max_fee_footer">Максимальная cумма комиссии</string>
|
||||
<string name="send_max_fee">Комиссия не превысит</string>
|
||||
<string name="send_network_fee_title">Сетевая комиссия</string>
|
||||
<string name="send_network_fee_warning_title">Покрытие сетевой комиссии</string>
|
||||
<string name="send_network_fee_warning_content">Сумма отправки будет уменьшена для покрытия выбранного уровня комиссии</string>
|
||||
<string name="send_notification_transaction_delay_text">Обратите внимание, что при определенных параметрах комиссии возможны задержки по вашей транзакции</string>
|
||||
<string name="send_notification_exceed_balance_title">Недостаточно средств</string>
|
||||
<string name="send_notification_exceed_balance_text">Недостаточно средств для перевода, так как сумма комиссии и сумма перевода в совокупности больше имеющегося баланса.</string>
|
||||
<string name="send_notification_invalid_amount_title">Недопустимая сумма</string>
|
||||
<string name="send_notification_invalid_amount_text">Включенная комиссия превышает сумму перевода, что приводит к отрицательному значению.</string>
|
||||
<string name="send_notification_invalid_minimum_amount_text">Минимальная сумма отправки - %1$s. Пожалуйста, убедитесь, что остаток после отправки также не будет меньше %1$s.</string>
|
||||
<string name="send_notification_invalid_reserve_amount_title">Сумма резерва не может быть менее %1$s.</string>
|
||||
<string name="send_notification_top_up_text">Пожалуйста, пополните свой баланс, чтобы продолжить.</string>
|
||||
<string name="send_notification_high_fee_title">Увеличение комиссии</string>
|
||||
<string name="send_notification_high_fee_text">Комиссия при переводе всего баланса выше. Для того, чтобы снизить комиссию Вы можете оставить 0.01.</string>
|
||||
<string name="send_notification_exceed_fee_title">Комиссия превышает баланс</string>
|
||||
<string name="send_notification_exceed_fee_text">Размер комиссии превышает баланс сети. Для продолжения необходимо пополнить баланс сети.</string>
|
||||
<string name="send_notification_transaction_delay_title">Возможны задержки по транзакции</string>
|
||||
<string name="send_optional_field">Необязательное</string>
|
||||
<string name="send_qrcode_scan_amount_alert_title">QR код содержит информацию о сумме отправки равной %s</string>
|
||||
<string name="send_recipient">Получатель</string>
|
||||
<string name="send_recipient_wallets_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>
|
||||
|
|
|
|||
|
|
@ -87,6 +87,12 @@
|
|||
<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_fee_selector_title">Speed and fee</string>
|
||||
<string name="common_fee_selector_footer">Network transaction fees are used to support network security, incentivize validators, allocate resources, and determine transaction priority</string>
|
||||
<string name="common_fee_selector_option_slow">Slow</string>
|
||||
<string name="common_fee_selector_option_market">Market</string>
|
||||
<string name="common_fee_selector_option_fast">Fast</string>
|
||||
<string name="common_fee_selector_option_custom">Custom</string>
|
||||
<string name="common_generate_addresses">Generate addresses</string>
|
||||
<string name="common_import">Import</string>
|
||||
<string name="common_learn_and_earn">Learn & Earn</string>
|
||||
|
|
@ -99,6 +105,7 @@
|
|||
<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_paste">Paste</string>
|
||||
<string name="common_receive">Receive</string>
|
||||
<string name="common_reject">Reject</string>
|
||||
<string name="common_reload">Reload</string>
|
||||
|
|
@ -383,20 +390,64 @@
|
|||
<string name="scan_card_settings_message">Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet.</string>
|
||||
<string name="scan_card_settings_title">Get your card ready!</string>
|
||||
<string name="send_amount_label">Amount</string>
|
||||
<string name="send_amount_substract">Subtract from send amount</string>
|
||||
<string name="send_amount_substract_footer">The recipient will receive %1$s</string>
|
||||
<string name="send_destination_hint_address">Address</string>
|
||||
<string name="send_destination_tag_field">Destination Tag</string>
|
||||
<string name="send_datetime_formatter">%1$s at %2$s</string>
|
||||
<string name="send_enter_address_field">Enter address</string>
|
||||
<string name="send_error_address_same_as_wallet">Address is the same as wallet address</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>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_insufficient_funds">Insufficient funds for transfer</string>
|
||||
<string name="send_fee_include_description">Include fee</string>
|
||||
<string name="send_fee_label">Fee</string>
|
||||
<string name="send_fee_picker_low">Low</string>
|
||||
<string name="send_fee_picker_normal">Normal</string>
|
||||
<string name="send_fee_picker_priority">Priority</string>
|
||||
<string name="send_fee_unreachable_error_title">Network fee info unreachable</string>
|
||||
<string name="send_fee_unreachable_error_text">Check your network connection</string>
|
||||
<string name="send_gas_limit">Gas limit</string>
|
||||
<string name="send_gas_limit_footer">Gas Limit is auto-calculated; raise it during network congestion</string>
|
||||
<string name="send_gas_price">Gas price</string>
|
||||
<string name="send_gas_price_footer">Gas Price affects transaction speed. If it\'s too low, the transaction might not be processed.</string>
|
||||
<string name="send_max_amount_label">Maximum amount</string>
|
||||
<string name="send_max_amount">Max</string>
|
||||
<string name="send_max_fee_footer">Maximum fee amount</string>
|
||||
<string name="send_max_fee">Max fee</string>
|
||||
<string name="send_memo_destination_tag_error">Numbers only for Destination Tag</string>
|
||||
<string name="send_network_fee_title">Network fee</string>
|
||||
<string name="send_network_fee_warning_title">Network fee coverage</string>
|
||||
<string name="send_network_fee_warning_content">Sending amount will be reduced to cover the selected fee level</string>
|
||||
<string name="send_notification_transaction_delay_text">Kindly be aware that your transaction may experience delays under specific fee settings</string>
|
||||
<string name="send_notification_exceed_balance_title">Total exceeds balance</string>
|
||||
<string name="send_notification_exceed_balance_text">Insufficient funds for the transfer, as the total of the fee and transfer amount exceeds the existing balance.</string>
|
||||
<string name="send_notification_invalid_amount_title">Invalid amount</string>
|
||||
<string name="send_notification_invalid_amount_text">The included commission exceeds the transfer amount, leading to a negative value.</string>
|
||||
<string name="send_notification_invalid_minimum_amount_text">The minimum sending amount is %1$s. Please ensure that the remaining balance after sending will not be less than %1$s.</string>
|
||||
<string name="send_notification_invalid_reserve_amount_title">The balance amount must be at least %1$s.</string>
|
||||
<string name="send_notification_invalid_reserve_amount_text">Please top up your balance to continue.</string>
|
||||
<string name="send_notification_high_fee_title">Fee is increased</string>
|
||||
<string name="send_notification_high_fee_text">The fee for transferring the entire balance is higher. To reduce the commission, you can leave 0.01.</string>
|
||||
<string name="send_notification_exceed_fee_title">Fee exceeds balance</string>
|
||||
<string name="send_notification_exceed_fee_text">The commission fee exceeds the network balance. To continue, it is necessary to replenish the network balance.</string>
|
||||
<string name="send_notification_transaction_delay_title">Transaction delays are possible</string>
|
||||
<string name="send_optional_field">Optional</string>
|
||||
<string name="send_qrcode_scan_info">Please align your QR code with the square to scan it. Ensure you scan %s network address.</string>
|
||||
<string name="send_qrcode_scan_address_success">Recipient’s address scanned</string>
|
||||
<string name="send_qrcode_scan_memo_success">Sending amount was changed</string>
|
||||
<string name="send_qrcode_scan_amount_alert_title">QR code contains information about the sending amount equal to %s</string>
|
||||
<string name="send_qrcode_scan_amount_alert_text">Change the entered amount?</string>
|
||||
<string name="send_qrcode_alert_change">Change</string>
|
||||
<string name="send_qrcode_alert_decline">Decline</string>
|
||||
<string name="send_recent_transactions">Recent</string>
|
||||
<string name="send_recipient">Recipient</string>
|
||||
<string name="send_recipient_address_error">Not a valid address</string>
|
||||
<string name="send_recipient_wallets_title">My wallets</string>
|
||||
<string name="send_recipient_address_footer">Ensure that you are sending funds to an %1$s wallet address. Errors may result in the loss of your tokens.</string>
|
||||
<string name="send_recipient_memo_footer">A Memo/Destination Tag is a unique ID for differentiating transactions sent to the same recipient on the same network. Caution: Omitting a memo may lead to misplaced funds.</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>
|
||||
|
|
@ -404,7 +455,6 @@
|
|||
<string name="send_total_subtitle_format">%s will be sent</string>
|
||||
<string name="send_transaction_success">Transaction has been successfully signed and sent to the blockchain node. Wallet balance will be updated in a while</string>
|
||||
<string name="send_validation_invalid_address">Invalid address</string>
|
||||
<string name="send_insufficient_funds">Insufficient funds for transfer</string>
|
||||
<string name="shop_buy_now">Buy now</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code…</string>
|
||||
<string name="shop_one_wallet">Tangem Wallet</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
package com.tangem.core.ui.components.icons.identicon
|
||||
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.floor
|
||||
|
||||
/**
|
||||
* Ident icon. Blockies algorithm.
|
||||
* @see [Blockies](https://github.com/ethereum/blockies)
|
||||
*
|
||||
* @param address Address to generate the ident icon
|
||||
*/
|
||||
@Suppress("MagicNumber")
|
||||
internal data class Blockies(
|
||||
val address: String,
|
||||
) {
|
||||
|
||||
val primaryColor: Int
|
||||
val backgroundColor: Int
|
||||
val spotColor: Int
|
||||
val data: MutableList<Float>
|
||||
|
||||
init {
|
||||
val seed = seedFromAddress(address)
|
||||
// IMPORTANT! Color generation is based on the seed, thus ORDER is important.
|
||||
primaryColor = colorFromSeed(seed)
|
||||
backgroundColor = colorFromSeed(seed)
|
||||
spotColor = colorFromSeed(seed)
|
||||
data = dataFromSeed(seed)
|
||||
}
|
||||
|
||||
private fun seedFromAddress(address: String): MutableList<Long> {
|
||||
val seed = MutableList(SIZE) { DEFAULT_VALUE_L }
|
||||
address.indices.forEach { index ->
|
||||
seed[index % HALF_SIZE] =
|
||||
(seed[index % HALF_SIZE] shl 5) - seed[index % HALF_SIZE] + Character.codePointAt(address, index)
|
||||
}
|
||||
|
||||
// Important cast to preserve JavaScript type behavior
|
||||
seed.indices.map { seed[it] = seed[it].toInt().toLong() }
|
||||
return seed
|
||||
}
|
||||
|
||||
private fun colorFromSeed(seed: MutableList<Long>): Int {
|
||||
val h = floor(nextSeed(seed) * DEGREE_CIRCLE_F)
|
||||
val s = nextSeed(seed) * SATURATION_MAX + SATURATION_MIN
|
||||
val l = (nextSeed(seed) + nextSeed(seed) + nextSeed(seed) + nextSeed(seed)) * PROBABILITY_LIGHTNESS
|
||||
return toRgb(h, s, l)
|
||||
}
|
||||
|
||||
private fun nextSeed(seed: MutableList<Long>): Float {
|
||||
val t = (seed[0] xor (seed[0] shl 11)).toInt()
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = seed[3]
|
||||
seed[3] = seed[3] xor (seed[3] shr 19) xor t.toLong() xor (t shr 8).toLong()
|
||||
|
||||
return abs(seed[3]).toFloat() / Integer.MAX_VALUE
|
||||
}
|
||||
|
||||
private fun dataFromSeed(seed: MutableList<Long>) = MutableList(SIZE * SIZE) { DEFAULT_VALUE_F }.apply {
|
||||
(0 until SIZE).forEach { row ->
|
||||
(0 until HALF_SIZE).forEach { column ->
|
||||
val value = floor(nextSeed(seed) * PROBABILITY_COLOR)
|
||||
this[row * SIZE + column] = value
|
||||
this[(row + 1) * SIZE - column - 1] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toRgb(paramH: Float, paramS: Float, paramL: Float): Int {
|
||||
val h = paramH % DEGREE_CIRCLE_F / DEGREE_CIRCLE_F
|
||||
val s = paramS / PERCENT_MAX
|
||||
val l = paramL / PERCENT_MAX
|
||||
|
||||
val q = if (l < 0.5) l * (1 + s) else l + s - s * l
|
||||
val p = 2 * l - q
|
||||
|
||||
val r = hueToRGB(p, q, h + 1f / 3f).coerceIn(0f, 1f)
|
||||
val g = hueToRGB(p, q, h).coerceIn(0f, 1f)
|
||||
val b = hueToRGB(p, q, h - 1f / 3f).coerceIn(0f, 1f)
|
||||
|
||||
val red = (r * HEX_COLOR_MAX).toInt()
|
||||
val green = (g * HEX_COLOR_MAX).toInt()
|
||||
val blue = (b * HEX_COLOR_MAX).toInt()
|
||||
return RGB_ALPHA_PART shl RGB_R_PART or (red shl RGB_G_PART) or (green shl RGB_B_PART) or blue
|
||||
}
|
||||
|
||||
private fun hueToRGB(p: Float, q: Float, h: Float): Float {
|
||||
var hue = h
|
||||
if (hue < 0) hue += 1f
|
||||
if (hue > 1) hue -= 1f
|
||||
if (6 * hue < 1) return p + (q - p) * 6f * hue
|
||||
if (2 * hue < 1) return q
|
||||
|
||||
return if (3 * hue < 2) p + (q - p) * 6f * (2f / 3f - hue) else p
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal const val SIZE = 8
|
||||
private const val HALF_SIZE = SIZE / 2
|
||||
private const val DEFAULT_VALUE_L = 0L
|
||||
private const val DEFAULT_VALUE_F = 0f
|
||||
private const val DEGREE_CIRCLE_F = 360.0f
|
||||
private const val HEX_COLOR_MAX = 255
|
||||
private const val PERCENT_MAX = 100f
|
||||
private const val SATURATION_MIN = 40f
|
||||
private const val SATURATION_MAX = 60f
|
||||
private const val PROBABILITY_LIGHTNESS = 25f
|
||||
private const val PROBABILITY_COLOR = 2.3f
|
||||
private const val RGB_ALPHA_PART = 0xFF
|
||||
private const val RGB_R_PART = 24
|
||||
private const val RGB_G_PART = 16
|
||||
private const val RGB_B_PART = 8
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.tangem.core.ui.components.icons.identicon
|
||||
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.intl.Locale
|
||||
import androidx.compose.ui.text.toLowerCase
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.res.LocalIsInDarkTheme
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
private const val GAP_WIDTH = 1f
|
||||
private const val ALPHA = 0.9f
|
||||
|
||||
/**
|
||||
* Ident icon
|
||||
*
|
||||
* @param address to generate ident icon from
|
||||
* @param modifier to apply to ident icon
|
||||
*/
|
||||
@Suppress("MagicNumber")
|
||||
@Composable
|
||||
fun IdentIcon(address: String, modifier: Modifier = Modifier) {
|
||||
if (address.isBlank()) {
|
||||
Box(modifier = modifier)
|
||||
} else {
|
||||
val blockies = Blockies(address.toLowerCase(Locale.current))
|
||||
Canvas(
|
||||
modifier = modifier
|
||||
.then(
|
||||
if (LocalIsInDarkTheme.current) {
|
||||
Modifier.alpha(ALPHA)
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
),
|
||||
) {
|
||||
val cellWidth = size.width / Blockies.SIZE
|
||||
blockies.data.forEachIndexed { index, item ->
|
||||
val y = index / Blockies.SIZE
|
||||
val x = index % Blockies.SIZE
|
||||
val colorInt = when (item) {
|
||||
1f -> blockies.primaryColor
|
||||
2f -> blockies.spotColor
|
||||
else -> blockies.backgroundColor
|
||||
}
|
||||
drawRect(
|
||||
color = Color(colorInt),
|
||||
topLeft = Offset(x * cellWidth, y * cellWidth),
|
||||
size = Size(cellWidth + GAP_WIDTH, cellWidth + GAP_WIDTH),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//region preview
|
||||
@Preview
|
||||
@Composable
|
||||
private fun IdentIconPreview_Light() {
|
||||
TangemTheme {
|
||||
IdentIcon(
|
||||
address = "0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359",
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size40),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun IdentIconPreview_Dark() {
|
||||
TangemTheme(isDark = true) {
|
||||
IdentIcon(
|
||||
address = "0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359",
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size40),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
|
@ -31,6 +31,7 @@ data class TangemDimens internal constructor(
|
|||
val radius14: Dp = 14.dp,
|
||||
val radius16: Dp = 16.dp,
|
||||
val radius18: Dp = 18.dp,
|
||||
val radius20: Dp = 20.dp,
|
||||
val radius24: Dp = 24.dp,
|
||||
val radius26: Dp = 26.dp,
|
||||
val radius28: Dp = 28.dp,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue