Updated on 2026-08-14
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9eaedddd9bfe5a1f216887d31eda0fabeba1c11d
|
Subproject commit fad890b2a0b552be60d124949ca0a3a4d672dac1
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
package com.tangem.tap.features.tokens.impl.presentation.states
|
package com.tangem.tap.features.tokens.impl.presentation.states
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network item state
|
* Token item state.
|
||||||
|
* All subclasses is stable, but @Immutable annotation is required to use this sealed class like as
|
||||||
|
* field of TokensListStateHolder.
|
||||||
*
|
*
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
|
@Immutable
|
||||||
sealed interface TokenItemState {
|
sealed interface TokenItemState {
|
||||||
|
|
||||||
/** Token id */
|
/** Token id */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.tap.features.tokens.impl.presentation.states
|
package com.tangem.tap.features.tokens.impl.presentation.states
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.paging.LoadState
|
import androidx.paging.LoadState
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
@ -9,6 +10,7 @@ import kotlinx.coroutines.flow.Flow
|
||||||
*
|
*
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
|
@Immutable
|
||||||
internal sealed interface TokensListStateHolder {
|
internal sealed interface TokensListStateHolder {
|
||||||
|
|
||||||
/** Toolbar state */
|
/** Toolbar state */
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
package com.tangem.tap.features.tokens.impl.presentation.states
|
package com.tangem.tap.features.tokens.impl.presentation.states
|
||||||
|
|
||||||
/** Toolbar state */
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toolbar state.
|
||||||
|
* All subclasses is stable, but @Immutable annotation is required to use this sealed class like as
|
||||||
|
* field of TokensListStateHolder.
|
||||||
|
*/
|
||||||
|
@Immutable
|
||||||
sealed interface TokensListToolbarState {
|
sealed interface TokensListToolbarState {
|
||||||
|
|
||||||
/** Callback to be invoked when BackButton is being clicked */
|
/** Callback to be invoked when BackButton is being clicked */
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,22 @@ object MultipleAddressUiHelper {
|
||||||
return when (id) {
|
return when (id) {
|
||||||
R.id.chip_default -> {
|
R.id.chip_default -> {
|
||||||
when (blockchain) {
|
when (blockchain) {
|
||||||
Blockchain.Bitcoin, Blockchain.BitcoinTestnet, Blockchain.Litecoin -> BitcoinAddressType.Segwit
|
Blockchain.Bitcoin,
|
||||||
|
Blockchain.BitcoinTestnet,
|
||||||
|
Blockchain.Litecoin,
|
||||||
|
Blockchain.BitcoinCash,
|
||||||
|
-> BitcoinAddressType.Segwit
|
||||||
Blockchain.CardanoShelley -> CardanoAddressType.Shelley
|
Blockchain.CardanoShelley -> CardanoAddressType.Shelley
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.chip_legacy -> {
|
R.id.chip_legacy -> {
|
||||||
when (blockchain) {
|
when (blockchain) {
|
||||||
Blockchain.Bitcoin, Blockchain.BitcoinTestnet, Blockchain.Litecoin -> BitcoinAddressType.Legacy
|
Blockchain.Bitcoin,
|
||||||
|
Blockchain.BitcoinTestnet,
|
||||||
|
Blockchain.Litecoin,
|
||||||
|
Blockchain.BitcoinCash,
|
||||||
|
-> BitcoinAddressType.Legacy
|
||||||
Blockchain.CardanoShelley -> CardanoAddressType.Byron
|
Blockchain.CardanoShelley -> CardanoAddressType.Byron
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import com.tangem.tap.common.extensions.toFormattedCurrencyString
|
||||||
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
||||||
import com.tangem.tap.domain.model.WalletDataModel
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.model.WalletStoreModel
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
|
import com.tangem.tap.features.wallet.models.PendingTransactionType
|
||||||
import com.tangem.tap.features.wallet.models.WalletWarning
|
import com.tangem.tap.features.wallet.models.WalletWarning
|
||||||
import com.tangem.tap.features.wallet.redux.WalletMainButton
|
import com.tangem.tap.features.wallet.redux.WalletMainButton
|
||||||
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||||
|
|
@ -19,9 +20,24 @@ import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal fun WalletDataModel.mainButton(blockchainAmount: BigDecimal): WalletMainButton = WalletMainButton.SendButton(
|
internal fun WalletDataModel.mainButton(blockchainAmount: BigDecimal): WalletMainButton = WalletMainButton.SendButton(
|
||||||
enabled = !isEmptyAmount && status.pendingTransactions.isEmpty() && !blockchainAmount.isZero(),
|
enabled = !isEmptyAmount &&
|
||||||
|
hasPendingTransactions() &&
|
||||||
|
!blockchainAmount.isZero(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal fun WalletDataModel.hasPendingTransactions(): Boolean {
|
||||||
|
// for now check pending ongoing only just for BTC, later test and add other utxo networks
|
||||||
|
val isBitcoinBlockchain =
|
||||||
|
currency.blockchain == Blockchain.Bitcoin || currency.blockchain == Blockchain.BitcoinTestnet
|
||||||
|
if (currency.isBlockchain() && isBitcoinBlockchain) {
|
||||||
|
val outgoingTransactions = status.pendingTransactions.filter {
|
||||||
|
it.type == PendingTransactionType.Outgoing
|
||||||
|
}
|
||||||
|
return outgoingTransactions.isEmpty()
|
||||||
|
}
|
||||||
|
return status.pendingTransactions.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
internal fun WalletDataModel.getFormattedAmount(): String {
|
internal fun WalletDataModel.getFormattedAmount(): String {
|
||||||
return status.amount.toFormattedCurrencyString(
|
return status.amount.toFormattedCurrencyString(
|
||||||
decimals = currency.decimals,
|
decimals = currency.decimals,
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,7 @@ import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.material.Divider
|
import androidx.compose.material.Divider
|
||||||
import androidx.compose.material.Surface
|
import androidx.compose.material.Surface
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
|
|
@ -27,11 +20,7 @@ import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import com.tangem.core.ui.components.SelectorButton
|
import com.tangem.core.ui.components.*
|
||||||
import com.tangem.core.ui.components.SpacerH12
|
|
||||||
import com.tangem.core.ui.components.SpacerH4
|
|
||||||
import com.tangem.core.ui.components.SpacerW16
|
|
||||||
import com.tangem.core.ui.components.SpacerW4
|
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.tap.common.entities.FiatCurrency
|
import com.tangem.tap.common.entities.FiatCurrency
|
||||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
|
|
@ -42,7 +31,8 @@ import java.math.BigDecimal
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.text.NumberFormat
|
import java.text.NumberFormat
|
||||||
import java.util.*
|
import java.util.Currency
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
internal class TotalBalanceCard @JvmOverloads constructor(
|
internal class TotalBalanceCard @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|
@ -125,7 +115,7 @@ private fun TotalBalanceCardContent(state: TotalBalanceCardState, modifier: Modi
|
||||||
-> LoadedAmount(
|
-> LoadedAmount(
|
||||||
amount = buildAmountString(
|
amount = buildAmountString(
|
||||||
amount = state.amount,
|
amount = state.amount,
|
||||||
fiatCurrencySymbol = state.fiatCurrency.symbol,
|
fiatCurrency = state.fiatCurrency,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -228,30 +218,45 @@ private fun LoadedAmount(amount: AnnotatedString, modifier: Modifier = Modifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun buildAmountString(amount: BigDecimal?, fiatCurrencySymbol: String): AnnotatedString {
|
private fun buildAmountString(amount: BigDecimal?, fiatCurrency: FiatCurrency): AnnotatedString {
|
||||||
if (amount == null) return AnnotatedString(text = UNKNOWN_AMOUNT_SIGN)
|
if (amount == null) return AnnotatedString(text = UNKNOWN_AMOUNT_SIGN)
|
||||||
|
|
||||||
val formatter = NumberFormat.getInstance(Locale.getDefault()) as? DecimalFormat
|
val locale = Locale.getDefault()
|
||||||
?: return AnnotatedString("${amount.toPlainString()} $fiatCurrencySymbol")
|
val fractionDigits = 2
|
||||||
val decimalFormat = formatter.apply {
|
val formatter = NumberFormat.getCurrencyInstance(locale) as? DecimalFormat
|
||||||
maximumFractionDigits = 2
|
?: return AnnotatedString("${amount.toPlainString()} ${fiatCurrency.symbol}")
|
||||||
minimumFractionDigits = 2
|
|
||||||
isGroupingUsed = true
|
val currencyToShow = "${fiatCurrency.symbol} "
|
||||||
this.roundingMode = RoundingMode.HALF_UP
|
val scaledAmount = Currency.getInstance(fiatCurrency.code)?.let { currency ->
|
||||||
|
formatter.currency = currency
|
||||||
|
formatter.maximumFractionDigits = fractionDigits
|
||||||
|
formatter.minimumFractionDigits = fractionDigits
|
||||||
|
formatter.isGroupingUsed = true
|
||||||
|
formatter.roundingMode = RoundingMode.HALF_UP
|
||||||
|
formatter.format(amount).replace(currency.symbol, currencyToShow)
|
||||||
|
} ?: formatter.format(amount)
|
||||||
|
|
||||||
|
val integer = scaledAmount.substringBefore(formatter.decimalFormatSymbols.decimalSeparator)
|
||||||
|
var reminder = scaledAmount.substringAfter(formatter.decimalFormatSymbols.decimalSeparator)
|
||||||
|
|
||||||
|
// if locale formatted currency at the end, remember it and place out of AnnotatedString
|
||||||
|
val currency = if (reminder.endsWith(currencyToShow)) {
|
||||||
|
reminder = reminder.dropLast(currencyToShow.length)
|
||||||
|
currencyToShow
|
||||||
|
} else {
|
||||||
|
""
|
||||||
}
|
}
|
||||||
val scaledAmount = decimalFormat.format(amount)
|
|
||||||
val integer = scaledAmount.substringBefore(decimalFormat.decimalFormatSymbols.decimalSeparator)
|
|
||||||
val reminder = scaledAmount.substringAfter(decimalFormat.decimalFormatSymbols.decimalSeparator)
|
|
||||||
|
|
||||||
return buildAnnotatedString {
|
return buildAnnotatedString {
|
||||||
append(integer)
|
append(integer)
|
||||||
append(decimalFormat.decimalFormatSymbols.decimalSeparator)
|
append(formatter.decimalFormatSymbols.decimalSeparator)
|
||||||
append(
|
append(
|
||||||
AnnotatedString(
|
AnnotatedString(
|
||||||
text = "$reminder $fiatCurrencySymbol",
|
text = reminder,
|
||||||
spanStyle = TangemTheme.typography.h3.toSpanStyle(),
|
spanStyle = TangemTheme.typography.h3.toSpanStyle(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
append(currency) // it is not empty if was placed at the end after locale formatting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/drawable-hdpi/ic_eth.webp
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 307 KiB |
BIN
app/src/main/res/drawable-hdpi/meet_tangem.webp
Normal file
|
After Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 284 KiB |
BIN
app/src/main/res/drawable-hdpi/revolutionary_wallet.webp
Normal file
|
After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 205 KiB |
BIN
app/src/main/res/drawable-hdpi/wallet_for_everyone.webp
Normal file
|
After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/drawable-ldpi/ic_eth.webp
Normal file
|
After Width: | Height: | Size: 926 B |
|
Before Width: | Height: | Size: 7.6 KiB |
BIN
app/src/main/res/drawable-ldpi/ic_qcx.webp
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/drawable-mdpi/ic_eth.webp
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 154 KiB |
BIN
app/src/main/res/drawable-mdpi/meet_tangem.webp
Normal file
|
After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 124 KiB |
BIN
app/src/main/res/drawable-mdpi/revolutionary_wallet.webp
Normal file
|
After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 99 KiB |
BIN
app/src/main/res/drawable-mdpi/wallet_for_everyone.webp
Normal file
|
After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_eth.webp
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 495 KiB |
BIN
app/src/main/res/drawable-xhdpi/meet_tangem.webp
Normal file
|
After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 455 KiB |
BIN
app/src/main/res/drawable-xhdpi/revolutionary_wallet.webp
Normal file
|
After Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 355 KiB |
BIN
app/src/main/res/drawable-xhdpi/wallet_for_everyone.webp
Normal file
|
After Width: | Height: | Size: 230 KiB |
|
Before Width: | Height: | Size: 7.9 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_eth.webp
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 997 KiB |
BIN
app/src/main/res/drawable-xxhdpi/meet_tangem.webp
Normal file
|
After Width: | Height: | Size: 512 KiB |
|
Before Width: | Height: | Size: 920 KiB |
BIN
app/src/main/res/drawable-xxhdpi/revolutionary_wallet.webp
Normal file
|
After Width: | Height: | Size: 616 KiB |
|
Before Width: | Height: | Size: 693 KiB |
BIN
app/src/main/res/drawable-xxhdpi/wallet_for_everyone.webp
Normal file
|
After Width: | Height: | Size: 450 KiB |
|
Before Width: | Height: | Size: 11 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_eth.webp
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 1.6 MiB |
BIN
app/src/main/res/drawable-xxxhdpi/meet_tangem.webp
Normal file
|
After Width: | Height: | Size: 819 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
BIN
app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.webp
Normal file
|
After Width: | Height: | Size: 917 KiB |
|
Before Width: | Height: | Size: 1.1 MiB |
BIN
app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.webp
Normal file
|
After Width: | Height: | Size: 748 KiB |
|
Before Width: | Height: | Size: 48 KiB |
BIN
app/src/main/res/drawable/currency0.webp
Normal file
|
After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 40 KiB |
BIN
app/src/main/res/drawable/currency1.webp
Normal file
|
After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 42 KiB |
BIN
app/src/main/res/drawable/currency2.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 50 KiB |
BIN
app/src/main/res/drawable/currency3.webp
Normal file
|
After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 40 KiB |
BIN
app/src/main/res/drawable/currency4.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 28 KiB |
BIN
app/src/main/res/drawable/dapps0.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 30 KiB |
BIN
app/src/main/res/drawable/dapps1.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 34 KiB |
BIN
app/src/main/res/drawable/dapps2.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 32 KiB |
BIN
app/src/main/res/drawable/dapps3.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 28 KiB |
BIN
app/src/main/res/drawable/dapps4.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 19 KiB |
BIN
app/src/main/res/drawable/dapps5.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 43 KiB |
BIN
app/src/main/res/drawable/ic_voyr.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 984 B |
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 604 B |
|
Before Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 4 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp
Normal file
|
After Width: | Height: | Size: 54 B |
|
Before Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
Normal file
|
After Width: | Height: | Size: 484 B |
|
|
@ -46,6 +46,8 @@
|
||||||
<string name="chat_button_title">Чат</string>
|
<string name="chat_button_title">Чат</string>
|
||||||
<string name="common_accept">Принять</string>
|
<string name="common_accept">Принять</string>
|
||||||
<string name="common_add">Добавить</string>
|
<string name="common_add">Добавить</string>
|
||||||
|
<string name="common_apply">Применить</string>
|
||||||
|
<string name="common_approval">Одобрение</string>
|
||||||
<string name="common_attention">Внимание</string>
|
<string name="common_attention">Внимание</string>
|
||||||
<string name="common_balance">Баланс: %s</string>
|
<string name="common_balance">Баланс: %s</string>
|
||||||
<string name="common_biometric_authentication">биометрическую аутентификацию</string>
|
<string name="common_biometric_authentication">биометрическую аутентификацию</string>
|
||||||
|
|
@ -73,7 +75,9 @@
|
||||||
<string name="common_start">Начать</string>
|
<string name="common_start">Начать</string>
|
||||||
<string name="common_submit">Отправить</string>
|
<string name="common_submit">Отправить</string>
|
||||||
<string name="common_success">Успешно</string>
|
<string name="common_success">Успешно</string>
|
||||||
|
<string name="common_swap">Обмен</string>
|
||||||
<string name="common_terms_and_conditions">условия участия</string>
|
<string name="common_terms_and_conditions">условия участия</string>
|
||||||
|
<string name="common_transfer">Перевод</string>
|
||||||
<string name="common_understand">Я понял</string>
|
<string name="common_understand">Я понял</string>
|
||||||
<string name="common_yes">Да</string>
|
<string name="common_yes">Да</string>
|
||||||
<string name="contract_address_copied_message">Адрес контракта скопирован!</string>
|
<string name="contract_address_copied_message">Адрес контракта скопирован!</string>
|
||||||
|
|
@ -255,6 +259,9 @@
|
||||||
<string name="onboarding_wallet_info_title_fourth">Восстановление кода доступа</string>
|
<string name="onboarding_wallet_info_title_fourth">Восстановление кода доступа</string>
|
||||||
<string name="onboarding_wallet_info_title_second">Идентичные карты</string>
|
<string name="onboarding_wallet_info_title_second">Идентичные карты</string>
|
||||||
<string name="onboarding_wallet_info_title_third">Код доступа</string>
|
<string name="onboarding_wallet_info_title_third">Код доступа</string>
|
||||||
|
<string name="organize_tokens_group">Группировка</string>
|
||||||
|
<string name="organize_tokens_sort_by_balance">По балансу</string>
|
||||||
|
<string name="organize_tokens_title">Сортировка токенов</string>
|
||||||
<string name="referral_button_participate">Участвовать</string>
|
<string name="referral_button_participate">Участвовать</string>
|
||||||
<string name="referral_error_failed_to_load_info">Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже.</string>
|
<string name="referral_error_failed_to_load_info">Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже.</string>
|
||||||
<string name="referral_error_failed_to_load_info_with_reason">Не удалось загрузить информацию по реферальной программе. Код ошибки: %s. Пожалуйста, попробуйте позже.</string>
|
<string name="referral_error_failed_to_load_info_with_reason">Не удалось загрузить информацию по реферальной программе. Код ошибки: %s. Пожалуйста, попробуйте позже.</string>
|
||||||
|
|
@ -382,7 +389,6 @@
|
||||||
<string name="swapping_permission_unlimited">Безлимитно</string>
|
<string name="swapping_permission_unlimited">Безлимитно</string>
|
||||||
<string name="swapping_success_view_explorer_button_title">Открыть в обозревателе</string>
|
<string name="swapping_success_view_explorer_button_title">Открыть в обозревателе</string>
|
||||||
<string name="swapping_success_view_title">В процессе</string>
|
<string name="swapping_success_view_title">В процессе</string>
|
||||||
<string name="swapping_swap">Обмен</string>
|
|
||||||
<string name="swapping_swap_action">Обменять</string>
|
<string name="swapping_swap_action">Обменять</string>
|
||||||
<string name="swapping_swap_of_to">Обмен %s на</string>
|
<string name="swapping_swap_of_to">Обмен %s на</string>
|
||||||
<string name="swapping_tangem_fee_disclaimer">Котировки включают дополнительную комиссию Tangem в размере %s. Это помогает нам предоставлять первоклассный продукт.</string>
|
<string name="swapping_tangem_fee_disclaimer">Котировки включают дополнительную комиссию Tangem в размере %s. Это помогает нам предоставлять первоклассный продукт.</string>
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@
|
||||||
<string name="common_start">開始</string>
|
<string name="common_start">開始</string>
|
||||||
<string name="common_submit">提交</string>
|
<string name="common_submit">提交</string>
|
||||||
<string name="common_success">成功</string>
|
<string name="common_success">成功</string>
|
||||||
|
<string name="common_swap">交換</string>
|
||||||
<string name="common_terms_and_conditions">條款和條件</string>
|
<string name="common_terms_and_conditions">條款和條件</string>
|
||||||
<string name="common_understand">我了解</string>
|
<string name="common_understand">我了解</string>
|
||||||
<string name="common_yes">是</string>
|
<string name="common_yes">是</string>
|
||||||
|
|
@ -367,7 +368,6 @@
|
||||||
<string name="swapping_permission_subheader">要繼續,您需要允許 1inch 智能合約使用您的 %s</string>
|
<string name="swapping_permission_subheader">要繼續,您需要允許 1inch 智能合約使用您的 %s</string>
|
||||||
<string name="swapping_success_view_explorer_button_title">在瀏覽器中查看</string>
|
<string name="swapping_success_view_explorer_button_title">在瀏覽器中查看</string>
|
||||||
<string name="swapping_success_view_title">進行中</string>
|
<string name="swapping_success_view_title">進行中</string>
|
||||||
<string name="swapping_swap">交換</string>
|
|
||||||
<string name="swapping_swap_action">交易</string>
|
<string name="swapping_swap_action">交易</string>
|
||||||
<string name="swapping_swap_of_to">交易 %s 至</string>
|
<string name="swapping_swap_of_to">交易 %s 至</string>
|
||||||
<string name="swapping_tangem_fee_disclaimer">此外,報價包括%s的 Tangem 費用。這有助於我們提供一流的產品</string>
|
<string name="swapping_tangem_fee_disclaimer">此外,報價包括%s的 Tangem 費用。這有助於我們提供一流的產品</string>
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@
|
||||||
<string name="chat_button_title">Support</string>
|
<string name="chat_button_title">Support</string>
|
||||||
<string name="common_accept">Accept</string>
|
<string name="common_accept">Accept</string>
|
||||||
<string name="common_add">Add</string>
|
<string name="common_add">Add</string>
|
||||||
|
<string name="common_apply">Apply</string>
|
||||||
|
<string name="common_approval">Approval</string>
|
||||||
<string name="common_attention">Attention</string>
|
<string name="common_attention">Attention</string>
|
||||||
<string name="common_balance">Balance: %s</string>
|
<string name="common_balance">Balance: %s</string>
|
||||||
<string name="common_biometric_authentication">biometric authentication</string>
|
<string name="common_biometric_authentication">biometric authentication</string>
|
||||||
|
|
@ -71,7 +73,9 @@
|
||||||
<string name="common_start">Start</string>
|
<string name="common_start">Start</string>
|
||||||
<string name="common_submit">Submit</string>
|
<string name="common_submit">Submit</string>
|
||||||
<string name="common_success">Success</string>
|
<string name="common_success">Success</string>
|
||||||
|
<string name="common_swap">Swap</string>
|
||||||
<string name="common_terms_and_conditions">terms and conditions</string>
|
<string name="common_terms_and_conditions">terms and conditions</string>
|
||||||
|
<string name="common_transfer">Transfer</string>
|
||||||
<string name="common_understand">I understand</string>
|
<string name="common_understand">I understand</string>
|
||||||
<string name="common_yes">Yes</string>
|
<string name="common_yes">Yes</string>
|
||||||
<string name="contract_address_copied_message">Contract address copied!</string>
|
<string name="contract_address_copied_message">Contract address copied!</string>
|
||||||
|
|
@ -253,6 +257,9 @@
|
||||||
<string name="onboarding_wallet_info_title_fourth">Access code restore</string>
|
<string name="onboarding_wallet_info_title_fourth">Access code restore</string>
|
||||||
<string name="onboarding_wallet_info_title_second">Identical cards</string>
|
<string name="onboarding_wallet_info_title_second">Identical cards</string>
|
||||||
<string name="onboarding_wallet_info_title_third">Access code</string>
|
<string name="onboarding_wallet_info_title_third">Access code</string>
|
||||||
|
<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="referral_button_participate">Participate</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">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>
|
<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>
|
||||||
|
|
@ -378,7 +385,6 @@
|
||||||
<string name="swapping_permission_unlimited">Unlimited</string>
|
<string name="swapping_permission_unlimited">Unlimited</string>
|
||||||
<string name="swapping_success_view_explorer_button_title">View in Explorer</string>
|
<string name="swapping_success_view_explorer_button_title">View in Explorer</string>
|
||||||
<string name="swapping_success_view_title">In progress</string>
|
<string name="swapping_success_view_title">In progress</string>
|
||||||
<string name="swapping_swap">Swap</string>
|
|
||||||
<string name="swapping_swap_action">Swap</string>
|
<string name="swapping_swap_action">Swap</string>
|
||||||
<string name="swapping_swap_of_to">Swap of %s to</string>
|
<string name="swapping_swap_of_to">Swap of %s to</string>
|
||||||
<string name="swapping_tangem_fee_disclaimer">Quotes include an additional Tangem commission of %s. This helps us deliver a top-of-the-line product.</string>
|
<string name="swapping_tangem_fee_disclaimer">Quotes include an additional Tangem commission of %s. This helps us deliver a top-of-the-line product.</string>
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ dependencies {
|
||||||
implementation(deps.androidx.fragment.ktx)
|
implementation(deps.androidx.fragment.ktx)
|
||||||
|
|
||||||
/** Compose */
|
/** Compose */
|
||||||
|
implementation(deps.compose.constraintLayout)
|
||||||
implementation(deps.compose.foundation)
|
implementation(deps.compose.foundation)
|
||||||
implementation(deps.compose.material)
|
implementation(deps.compose.material)
|
||||||
|
implementation(deps.compose.material3)
|
||||||
implementation(deps.compose.ui.tooling)
|
implementation(deps.compose.ui.tooling)
|
||||||
|
|
||||||
/** Other libraries */
|
/** Other libraries */
|
||||||
|
|
|
||||||
|
|
@ -312,14 +312,8 @@ private fun TangemButton(
|
||||||
textStyle: TextStyle = TangemTheme.typography.button,
|
textStyle: TextStyle = TangemTheme.typography.button,
|
||||||
) {
|
) {
|
||||||
Button(
|
Button(
|
||||||
modifier = modifier
|
modifier = modifier.heightIn(min = size.toHeightDp()),
|
||||||
.width(IntrinsicSize.Min)
|
onClick = { if (!showProgress) onClick() },
|
||||||
.heightIn(min = size.toHeightDp()),
|
|
||||||
onClick = {
|
|
||||||
if (!showProgress) {
|
|
||||||
onClick()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
elevation = elevation,
|
elevation = elevation,
|
||||||
shape = size.toShape(),
|
shape = size.toShape(),
|
||||||
|
|
@ -588,59 +582,44 @@ private open class TangemButtonColors(
|
||||||
|
|
||||||
// region Preview
|
// region Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun PrimaryButtonSample(modifier: Modifier = Modifier) {
|
private fun PrimaryButtonSample() {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = Modifier.background(TangemTheme.colors.background.primary),
|
||||||
.background(TangemTheme.colors.background.primary),
|
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||||
) {
|
) {
|
||||||
PrimaryButton(
|
PrimaryButton(modifier = Modifier.fillMaxWidth(), text = "Manage tokens", onClick = { })
|
||||||
modifier = Modifier.fillMaxWidth(),
|
PrimaryButton(modifier = Modifier.fillMaxWidth(), showProgress = true, text = "Manage tokens", onClick = { })
|
||||||
text = "Manage tokens",
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
PrimaryButton(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
showProgress = true,
|
|
||||||
text = "Manage tokens",
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
PrimaryButtonIconEnd(
|
PrimaryButtonIconEnd(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
PrimaryButtonIconStart(
|
PrimaryButtonIconStart(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
enabled = false,
|
enabled = false,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
PrimaryButtonIconEnd(
|
PrimaryButtonIconEnd(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
enabled = false,
|
enabled = false,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
PrimaryButtonIconStart(
|
PrimaryButtonIconStart(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
enabled = false,
|
enabled = false,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -662,59 +641,44 @@ private fun PrimaryButtonPreview_Dark() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SecondaryButtonSample(modifier: Modifier = Modifier) {
|
private fun SecondaryButtonSample() {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = Modifier.background(TangemTheme.colors.background.primary),
|
||||||
.background(TangemTheme.colors.background.primary),
|
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||||
) {
|
) {
|
||||||
SecondaryButton(
|
SecondaryButton(modifier = Modifier.fillMaxWidth(), text = "Manage tokens", onClick = { })
|
||||||
modifier = Modifier.fillMaxWidth(),
|
SecondaryButton(modifier = Modifier.fillMaxWidth(), showProgress = true, text = "Manage tokens", onClick = { })
|
||||||
text = "Manage tokens",
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
SecondaryButton(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
showProgress = true,
|
|
||||||
text = "Manage tokens",
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
SecondaryButtonIconEnd(
|
SecondaryButtonIconEnd(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
SecondaryButtonIconStart(
|
SecondaryButtonIconStart(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
SecondaryButton(
|
SecondaryButton(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
enabled = false,
|
enabled = false,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
SecondaryButtonIconEnd(
|
SecondaryButtonIconEnd(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
enabled = false,
|
enabled = false,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
SecondaryButtonIconStart(
|
SecondaryButtonIconStart(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = "Manage tokens",
|
text = "Manage tokens",
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
enabled = false,
|
enabled = false,
|
||||||
onClick = { /* no-op */ },
|
onClick = { },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -736,50 +700,23 @@ private fun SecondaryButtonPreview_Dark() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TextButtonSample(modifier: Modifier = Modifier) {
|
private fun TextButtonSample() {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = Modifier.background(TangemTheme.colors.background.primary),
|
||||||
.background(TangemTheme.colors.background.primary),
|
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||||
) {
|
) {
|
||||||
TextButton(
|
TextButton(text = "Enabled", onClick = { })
|
||||||
text = "Enabled",
|
TextButtonIconStart(text = "Enabled", iconResId = R.drawable.ic_plus_24, onClick = { })
|
||||||
onClick = { /* no-op */ },
|
TextButton(text = "Enabled", enabled = false, onClick = { })
|
||||||
)
|
TextButtonIconStart(text = "Enabled", iconResId = R.drawable.ic_plus_24, enabled = false, onClick = { })
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
WarningTextButton(text = "Delete", onClick = { })
|
||||||
TextButtonIconStart(
|
SelectorButton(text = "USD", onClick = { })
|
||||||
text = "Enabled",
|
|
||||||
iconResId = R.drawable.ic_plus_24,
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
TextButton(
|
|
||||||
text = "Enabled",
|
|
||||||
enabled = false,
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
TextButtonIconStart(
|
|
||||||
text = "Enabled",
|
|
||||||
iconResId = R.drawable.ic_plus_24,
|
|
||||||
enabled = false,
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
WarningTextButton(
|
|
||||||
text = "Delete",
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
SelectorButton(
|
|
||||||
text = "USD",
|
|
||||||
onClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(showBackground = true, widthDp = 360)
|
@Preview(showBackground = true, widthDp = 360)
|
||||||
@Composable
|
@Composable
|
||||||
private fun TextButtonPreview_Light() {
|
private fun TextButtonPreview_LightTheme() {
|
||||||
TangemTheme {
|
TangemTheme {
|
||||||
TextButtonSample()
|
TextButtonSample()
|
||||||
}
|
}
|
||||||
|
|
@ -787,62 +724,30 @@ private fun TextButtonPreview_Light() {
|
||||||
|
|
||||||
@Preview(showBackground = true, widthDp = 360)
|
@Preview(showBackground = true, widthDp = 360)
|
||||||
@Composable
|
@Composable
|
||||||
private fun TextButtonPreview_Dark() {
|
private fun TextButtonPreview_DarkTheme() {
|
||||||
TangemTheme(isDark = true) {
|
TangemTheme(isDark = true) {
|
||||||
TextButtonSample()
|
TextButtonSample()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ActionButtonSample(modifier: Modifier = Modifier) {
|
private fun ActionButtonSample() {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = Modifier.background(TangemTheme.colors.background.primary),
|
||||||
.background(TangemTheme.colors.background.primary),
|
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||||
) {
|
) {
|
||||||
RoundedActionButton(
|
RoundedActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, onClick = { })
|
||||||
text = "Send",
|
ActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, onClick = { })
|
||||||
iconResId = R.drawable.ic_arrow_up_24,
|
BackgroundActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, onClick = { })
|
||||||
onClick = { /* [REDACTED_TODO_COMMENT]*/ },
|
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 = { })
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
BackgroundActionButton(text = "Send", iconResId = R.drawable.ic_arrow_up_24, enabled = false, onClick = { })
|
||||||
ActionButton(
|
|
||||||
text = "Send",
|
|
||||||
iconResId = R.drawable.ic_arrow_up_24,
|
|
||||||
onClick = { /* [REDACTED_TODO_COMMENT]*/ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
BackgroundActionButton(
|
|
||||||
text = "Send",
|
|
||||||
iconResId = R.drawable.ic_arrow_up_24,
|
|
||||||
onClick = { /* [REDACTED_TODO_COMMENT]*/ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
RoundedActionButton(
|
|
||||||
text = "Send",
|
|
||||||
iconResId = R.drawable.ic_arrow_up_24,
|
|
||||||
enabled = false,
|
|
||||||
onClick = { /* [REDACTED_TODO_COMMENT]*/ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
ActionButton(
|
|
||||||
text = "Send",
|
|
||||||
iconResId = R.drawable.ic_arrow_up_24,
|
|
||||||
enabled = false,
|
|
||||||
onClick = { /* [REDACTED_TODO_COMMENT]*/ },
|
|
||||||
)
|
|
||||||
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
|
|
||||||
BackgroundActionButton(
|
|
||||||
text = "Send",
|
|
||||||
iconResId = R.drawable.ic_arrow_up_24,
|
|
||||||
enabled = false,
|
|
||||||
onClick = { /* [REDACTED_TODO_COMMENT]*/ },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(showBackground = true, widthDp = 360)
|
@Preview(showBackground = true, widthDp = 360)
|
||||||
@Composable
|
@Composable
|
||||||
private fun ActionButtonPreview_Light() {
|
private fun ActionButtonPreview_LightTheme() {
|
||||||
TangemTheme {
|
TangemTheme {
|
||||||
ActionButtonSample()
|
ActionButtonSample()
|
||||||
}
|
}
|
||||||
|
|
@ -850,7 +755,7 @@ private fun ActionButtonPreview_Light() {
|
||||||
|
|
||||||
@Preview(showBackground = true, widthDp = 360)
|
@Preview(showBackground = true, widthDp = 360)
|
||||||
@Composable
|
@Composable
|
||||||
private fun ActionButtonPreview_Dark() {
|
private fun ActionButtonPreview_DarkTheme() {
|
||||||
TangemTheme(isDark = true) {
|
TangemTheme(isDark = true) {
|
||||||
ActionButtonSample()
|
ActionButtonSample()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,342 @@
|
||||||
|
package com.tangem.core.ui.components.transactions
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
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.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||||
|
import androidx.constraintlayout.compose.ConstraintLayout
|
||||||
|
import androidx.constraintlayout.compose.Dimension
|
||||||
|
import com.tangem.core.ui.R
|
||||||
|
import com.tangem.core.ui.components.CircleShimmer
|
||||||
|
import com.tangem.core.ui.components.RectangleShimmer
|
||||||
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction component
|
||||||
|
*
|
||||||
|
* @param state state
|
||||||
|
*
|
||||||
|
* @see <a href = "https://www.figma.com/file/RU7AIgwHtGdMfy83T5UOoR/iOS?type=design&node-id=446-438&t=71jPDxMMk4e0
|
||||||
|
* a025-4">Figma Component</a>
|
||||||
|
*
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun Transaction(state: TransactionState) {
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(TangemTheme.colors.background.primary)
|
||||||
|
.defaultMinSize(minHeight = TangemTheme.dimens.size56)
|
||||||
|
.padding(horizontal = TangemTheme.dimens.spacing12, vertical = TangemTheme.dimens.spacing10),
|
||||||
|
color = TangemTheme.colors.background.primary,
|
||||||
|
) {
|
||||||
|
@Suppress("DestructuringDeclarationWithTooManyEntries")
|
||||||
|
ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
val (iconItem, titleItem, subtitleItem, amountItem, timestampItem) = createRefs()
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
state = state,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(TangemTheme.dimens.size40)
|
||||||
|
.constrainAs(iconItem) {
|
||||||
|
start.linkTo(parent.start)
|
||||||
|
centerVerticallyTo(parent)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Title(
|
||||||
|
state = state,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = TangemTheme.dimens.spacing12)
|
||||||
|
.constrainAs(titleItem) {
|
||||||
|
start.linkTo(iconItem.end)
|
||||||
|
top.linkTo(iconItem.top)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Subtitle(
|
||||||
|
state = state,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = TangemTheme.dimens.spacing6)
|
||||||
|
.padding(horizontal = TangemTheme.dimens.spacing12)
|
||||||
|
.constrainAs(subtitleItem) {
|
||||||
|
start.linkTo(iconItem.end)
|
||||||
|
top.linkTo(amountItem.bottom)
|
||||||
|
end.linkTo(timestampItem.start)
|
||||||
|
width = Dimension.fillToConstraints
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Amount(
|
||||||
|
state = state,
|
||||||
|
modifier = Modifier.constrainAs(amountItem) {
|
||||||
|
start.linkTo(titleItem.end)
|
||||||
|
top.linkTo(titleItem.top)
|
||||||
|
end.linkTo(parent.end)
|
||||||
|
width = Dimension.fillToConstraints
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Timestamp(
|
||||||
|
state = state,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = TangemTheme.dimens.spacing6)
|
||||||
|
.constrainAs(timestampItem) {
|
||||||
|
top.linkTo(amountItem.bottom)
|
||||||
|
end.linkTo(parent.end)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Icon(state: TransactionState, modifier: Modifier = Modifier) {
|
||||||
|
when (state) {
|
||||||
|
is TransactionState.Content -> {
|
||||||
|
Box(
|
||||||
|
modifier = modifier
|
||||||
|
.size(TangemTheme.dimens.size40)
|
||||||
|
.background(
|
||||||
|
color = when (state) {
|
||||||
|
is TransactionState.ProcessedTransactionContent -> {
|
||||||
|
TangemTheme.colors.icon.attention.copy(alpha = 0.1f)
|
||||||
|
}
|
||||||
|
is TransactionState.CompletedTransactionContent -> {
|
||||||
|
TangemTheme.colors.background.secondary
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shape = CircleShape,
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(
|
||||||
|
id = when (state) {
|
||||||
|
is TransactionState.Sending,
|
||||||
|
is TransactionState.Send,
|
||||||
|
-> R.drawable.ic_arrow_up_24
|
||||||
|
|
||||||
|
is TransactionState.Receiving,
|
||||||
|
is TransactionState.Receive,
|
||||||
|
-> R.drawable.ic_arrow_down_24
|
||||||
|
|
||||||
|
is TransactionState.Approving,
|
||||||
|
is TransactionState.Approved,
|
||||||
|
-> R.drawable.ic_doc_24
|
||||||
|
|
||||||
|
is TransactionState.Swapping,
|
||||||
|
is TransactionState.Swapped,
|
||||||
|
-> R.drawable.ic_exchange_vertical_24
|
||||||
|
},
|
||||||
|
),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(TangemTheme.dimens.size20)
|
||||||
|
.align(Alignment.Center),
|
||||||
|
tint = when (state) {
|
||||||
|
is TransactionState.ProcessedTransactionContent -> TangemTheme.colors.icon.attention
|
||||||
|
is TransactionState.CompletedTransactionContent -> TangemTheme.colors.icon.informative
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is TransactionState.Loading -> {
|
||||||
|
CircleShimmer(modifier = modifier.size(TangemTheme.dimens.size40))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Title(state: TransactionState, modifier: Modifier = Modifier) {
|
||||||
|
when (state) {
|
||||||
|
is TransactionState.ProcessedTransactionContent -> {
|
||||||
|
Row(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing6)) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
id = when (state) {
|
||||||
|
is TransactionState.Sending -> R.string.common_transfer
|
||||||
|
is TransactionState.Receiving -> R.string.common_transfer
|
||||||
|
is TransactionState.Approving -> R.string.common_approval
|
||||||
|
is TransactionState.Swapping -> R.string.common_swap
|
||||||
|
},
|
||||||
|
),
|
||||||
|
color = TangemTheme.colors.text.primary1,
|
||||||
|
style = TangemTheme.typography.subtitle2,
|
||||||
|
)
|
||||||
|
|
||||||
|
Image(
|
||||||
|
modifier = Modifier.align(Alignment.CenterVertically),
|
||||||
|
painter = painterResource(id = R.drawable.img_loader_15),
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is TransactionState.CompletedTransactionContent -> {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
id = when (state) {
|
||||||
|
is TransactionState.Send -> R.string.common_transfer
|
||||||
|
is TransactionState.Receive -> R.string.common_transfer
|
||||||
|
is TransactionState.Approved -> R.string.common_approval
|
||||||
|
is TransactionState.Swapped -> R.string.common_swap
|
||||||
|
},
|
||||||
|
),
|
||||||
|
modifier = modifier,
|
||||||
|
color = TangemTheme.colors.text.primary1,
|
||||||
|
style = TangemTheme.typography.subtitle2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TransactionState.Loading -> {
|
||||||
|
RectangleShimmer(
|
||||||
|
modifier = modifier.size(width = TangemTheme.dimens.size70, height = TangemTheme.dimens.size12),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Subtitle(state: TransactionState, modifier: Modifier = Modifier) {
|
||||||
|
when (state) {
|
||||||
|
is TransactionState.Content -> {
|
||||||
|
Text(
|
||||||
|
text = when (state) {
|
||||||
|
is TransactionState.Sending -> "to: ${state.address}"
|
||||||
|
is TransactionState.Send -> "to: ${state.address}"
|
||||||
|
is TransactionState.Receiving -> "from: ${state.address}"
|
||||||
|
is TransactionState.Receive -> "from: ${state.address}"
|
||||||
|
is TransactionState.Approving -> "from: ${state.address}"
|
||||||
|
is TransactionState.Approved -> "from: ${state.address}"
|
||||||
|
is TransactionState.Swapping -> "contract: ${state.address}"
|
||||||
|
is TransactionState.Swapped -> "contract ${state.address}"
|
||||||
|
},
|
||||||
|
modifier = modifier,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
color = TangemTheme.colors.text.tertiary,
|
||||||
|
style = TangemTheme.typography.caption,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TransactionState.Loading -> {
|
||||||
|
RectangleShimmer(
|
||||||
|
modifier = modifier.size(width = TangemTheme.dimens.size52, height = TangemTheme.dimens.size12),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Amount(state: TransactionState, modifier: Modifier = Modifier) {
|
||||||
|
when (state) {
|
||||||
|
is TransactionState.Content -> {
|
||||||
|
Text(
|
||||||
|
text = state.amount,
|
||||||
|
modifier = modifier,
|
||||||
|
textAlign = TextAlign.End,
|
||||||
|
color = TangemTheme.colors.text.primary1,
|
||||||
|
style = TangemTheme.typography.body2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TransactionState.Loading -> {
|
||||||
|
RectangleShimmer(
|
||||||
|
modifier = modifier.size(width = TangemTheme.dimens.size40, height = TangemTheme.dimens.size12),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Timestamp(state: TransactionState, modifier: Modifier = Modifier) {
|
||||||
|
when (state) {
|
||||||
|
is TransactionState.Content -> {
|
||||||
|
Text(
|
||||||
|
text = state.timestamp,
|
||||||
|
modifier = modifier,
|
||||||
|
textAlign = TextAlign.End,
|
||||||
|
color = TangemTheme.colors.text.tertiary,
|
||||||
|
style = TangemTheme.typography.caption,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TransactionState.Loading -> {
|
||||||
|
RectangleShimmer(
|
||||||
|
modifier = modifier.size(width = TangemTheme.dimens.size40, height = TangemTheme.dimens.size12),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun Preview_TransactionItem_LightTheme(
|
||||||
|
@PreviewParameter(TransactionItemStateProvider::class) state: TransactionState,
|
||||||
|
) {
|
||||||
|
TangemTheme(isDark = false) {
|
||||||
|
Transaction(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun Preview_TransactionItem_DarkTheme(
|
||||||
|
@PreviewParameter(TransactionItemStateProvider::class) state: TransactionState,
|
||||||
|
) {
|
||||||
|
TangemTheme(isDark = true) {
|
||||||
|
Transaction(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TransactionItemStateProvider : CollectionPreviewParameterProvider<TransactionState>(
|
||||||
|
collection = listOf(
|
||||||
|
TransactionState.Sending(
|
||||||
|
address = "33BddS...ga2B",
|
||||||
|
amount = "-0.500913 BTC",
|
||||||
|
timestamp = "8:41",
|
||||||
|
),
|
||||||
|
TransactionState.Receiving(
|
||||||
|
address = "33BddS...ga2B",
|
||||||
|
amount = "+0.500913 BTC",
|
||||||
|
timestamp = "8:41",
|
||||||
|
),
|
||||||
|
TransactionState.Approving(
|
||||||
|
address = "33BddS...ga2B",
|
||||||
|
amount = "+0.500913 BTC",
|
||||||
|
timestamp = "8:41",
|
||||||
|
),
|
||||||
|
TransactionState.Swapping(
|
||||||
|
address = "33BddS...ga2B",
|
||||||
|
amount = "+0.500913 BTC",
|
||||||
|
timestamp = "8:41",
|
||||||
|
),
|
||||||
|
TransactionState.Send(
|
||||||
|
address = "33BddS...ga2B",
|
||||||
|
amount = "-0.500913 BTC",
|
||||||
|
timestamp = "8:41",
|
||||||
|
),
|
||||||
|
TransactionState.Receive(
|
||||||
|
address = "33BddS...ga2B",
|
||||||
|
amount = "+0.500913 BTC",
|
||||||
|
timestamp = "8:41",
|
||||||
|
),
|
||||||
|
TransactionState.Approved(
|
||||||
|
address = "33BddS...ga2B",
|
||||||
|
amount = "+0.500913 BTC",
|
||||||
|
timestamp = "8:41",
|
||||||
|
),
|
||||||
|
TransactionState.Swapped(
|
||||||
|
address = "33BddS...ga2B",
|
||||||
|
amount = "+0.500913 BTC",
|
||||||
|
timestamp = "8:41",
|
||||||
|
),
|
||||||
|
TransactionState.Loading,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
package com.tangem.core.ui.components.transactions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction component state
|
||||||
|
*
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
sealed interface TransactionState {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
sealed class Content(
|
||||||
|
open val address: String,
|
||||||
|
open val amount: String,
|
||||||
|
open val timestamp: String,
|
||||||
|
) : TransactionState
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content state for processed transaction
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
sealed class ProcessedTransactionContent(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : Content(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content state for completed transaction
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
sealed class CompletedTransactionContent(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : Content(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processed sending transaction state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
data class Sending(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : ProcessedTransactionContent(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processed receiving transaction state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
data class Receiving(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : ProcessedTransactionContent(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processed approving transaction state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
data class Approving(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : ProcessedTransactionContent(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processed swapping transaction state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
data class Swapping(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : ProcessedTransactionContent(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completed sending transaction state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
data class Send(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : CompletedTransactionContent(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completed receiving transaction state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
data class Receive(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : CompletedTransactionContent(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completed approving transaction state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
data class Approved(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : CompletedTransactionContent(address, amount, timestamp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completed swapping transaction state
|
||||||
|
*
|
||||||
|
* @property address address
|
||||||
|
* @property amount amount
|
||||||
|
* @property timestamp timestamp
|
||||||
|
*/
|
||||||
|
data class Swapped(
|
||||||
|
override val address: String,
|
||||||
|
override val amount: String,
|
||||||
|
override val timestamp: String,
|
||||||
|
) : CompletedTransactionContent(address, amount, timestamp)
|
||||||
|
|
||||||
|
/** Loading state */
|
||||||
|
object Loading : TransactionState
|
||||||
|
}
|
||||||
|
|
@ -2,22 +2,42 @@ package com.tangem.core.ui.extensions
|
||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for creating text as [String] or [StringRes].
|
||||||
|
* It necessary to use [Immutable] annotation because all sealed interface has runtime stability.
|
||||||
|
* All subclasses are stable.
|
||||||
|
*/
|
||||||
|
@Immutable
|
||||||
sealed interface TextReference {
|
sealed interface TextReference {
|
||||||
class Res(@StringRes val id: Int, val formatArgs: List<Any> = emptyList()) : TextReference {
|
|
||||||
constructor(@StringRes id: Int, vararg formatArgs: Any) : this(id, formatArgs.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
class Str(val value: String) : TextReference
|
/**
|
||||||
|
* Text resource id
|
||||||
|
*
|
||||||
|
* @property id resource id
|
||||||
|
* @property formatArgs arguments
|
||||||
|
*
|
||||||
|
* Impossible to use [kotlinx.collections.immutable.ImmutableList] because [Any] is unstable.
|
||||||
|
*/
|
||||||
|
data class Res(@StringRes val id: Int, val formatArgs: WrappedList<Any> = WrappedList(emptyList())) : TextReference
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text string
|
||||||
|
*
|
||||||
|
* @property value value
|
||||||
|
*/
|
||||||
|
data class Str(val value: String) : TextReference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get text */
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
fun TextReference.resolveReference(): String {
|
fun TextReference.resolveReference(): String {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is TextReference.Res -> stringResource(this.id, *this.formatArgs.toTypedArray())
|
is TextReference.Res -> stringResource(id, *formatArgs.toTypedArray())
|
||||||
is TextReference.Str -> this.value
|
is TextReference.Str -> value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.tangem.core.ui.extensions
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
/**
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
@JvmInline
|
||||||
|
@Immutable
|
||||||
|
value class WrappedList<T>(val data: List<T>) : List<T> by data
|
||||||
|
|
@ -56,9 +56,11 @@ data class TangemDimens internal constructor(
|
||||||
val size46: Dp = 46.dp,
|
val size46: Dp = 46.dp,
|
||||||
val size48: Dp = 48.dp,
|
val size48: Dp = 48.dp,
|
||||||
val size50: Dp = 50.dp,
|
val size50: Dp = 50.dp,
|
||||||
|
val size52: Dp = 52.dp,
|
||||||
val size56: Dp = 56.dp,
|
val size56: Dp = 56.dp,
|
||||||
val size62: Dp = 62.dp,
|
val size62: Dp = 62.dp,
|
||||||
val size68: Dp = 68.dp,
|
val size68: Dp = 68.dp,
|
||||||
|
val size70: Dp = 70.dp,
|
||||||
val size72: Dp = 72.dp,
|
val size72: Dp = 72.dp,
|
||||||
val size80: Dp = 80.dp,
|
val size80: Dp = 80.dp,
|
||||||
val size84: Dp = 84.dp,
|
val size84: Dp = 84.dp,
|
||||||
|
|
|
||||||
9
core/ui/src/main/res/drawable/ic_doc_24.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M6,2C5.47,2 4.961,2.211 4.586,2.586C4.211,2.961 4,3.47 4,4V20C4,20.53 4.211,21.039 4.586,21.414C4.961,21.789 5.47,22 6,22H18C18.53,22 19.039,21.789 19.414,21.414C19.789,21.039 20,20.53 20,20V8L14,2H6ZM6,4H13V9H18V20H6V4ZM8,12V14H16V12H8ZM8,16V18H13V16H8Z"
|
||||||
|
android:fillColor="#000000" />
|
||||||
|
</vector>
|
||||||