diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config
index 9eaedddd9b..fad890b2a0 160000
--- a/app/src/main/assets/tangem-app-config
+++ b/app/src/main/assets/tangem-app-config
@@ -1 +1 @@
-Subproject commit 9eaedddd9bfe5a1f216887d31eda0fabeba1c11d
+Subproject commit fad890b2a0b552be60d124949ca0a3a4d672dac1
diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokenItemState.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokenItemState.kt
index df128ac9b4..790a83fb5f 100644
--- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokenItemState.kt
+++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokenItemState.kt
@@ -1,12 +1,16 @@
package com.tangem.tap.features.tokens.impl.presentation.states
+import androidx.compose.runtime.Immutable
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]
*/
+@Immutable
sealed interface TokenItemState {
/** Token id */
diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokensListStateHolder.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokensListStateHolder.kt
index e083f7991b..101cdc8f52 100644
--- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokensListStateHolder.kt
+++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokensListStateHolder.kt
@@ -1,5 +1,6 @@
package com.tangem.tap.features.tokens.impl.presentation.states
+import androidx.compose.runtime.Immutable
import androidx.paging.LoadState
import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow
@@ -9,6 +10,7 @@ import kotlinx.coroutines.flow.Flow
*
[REDACTED_AUTHOR]
*/
+@Immutable
internal sealed interface TokensListStateHolder {
/** Toolbar state */
diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokensListToolbarState.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokensListToolbarState.kt
index b4104f692b..a269659991 100644
--- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokensListToolbarState.kt
+++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/states/TokensListToolbarState.kt
@@ -1,6 +1,13 @@
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 {
/** Callback to be invoked when BackButton is being clicked */
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/MultipleAddressUiHelper.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/MultipleAddressUiHelper.kt
index 67e10ca9a6..e82c2f9547 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/ui/MultipleAddressUiHelper.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/MultipleAddressUiHelper.kt
@@ -22,14 +22,22 @@ object MultipleAddressUiHelper {
return when (id) {
R.id.chip_default -> {
when (blockchain) {
- Blockchain.Bitcoin, Blockchain.BitcoinTestnet, Blockchain.Litecoin -> BitcoinAddressType.Segwit
+ Blockchain.Bitcoin,
+ Blockchain.BitcoinTestnet,
+ Blockchain.Litecoin,
+ Blockchain.BitcoinCash,
+ -> BitcoinAddressType.Segwit
Blockchain.CardanoShelley -> CardanoAddressType.Shelley
else -> null
}
}
R.id.chip_legacy -> {
when (blockchain) {
- Blockchain.Bitcoin, Blockchain.BitcoinTestnet, Blockchain.Litecoin -> BitcoinAddressType.Legacy
+ Blockchain.Bitcoin,
+ Blockchain.BitcoinTestnet,
+ Blockchain.Litecoin,
+ Blockchain.BitcoinCash,
+ -> BitcoinAddressType.Legacy
Blockchain.CardanoShelley -> CardanoAddressType.Byron
else -> null
}
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt
index 273d52d384..f2d65a4fcf 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt
@@ -12,6 +12,7 @@ import com.tangem.tap.common.extensions.toFormattedCurrencyString
import com.tangem.tap.common.extensions.toFormattedFiatValue
import com.tangem.tap.domain.model.WalletDataModel
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.redux.WalletMainButton
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
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 {
return status.amount.toFormattedCurrencyString(
decimals = currency.decimals,
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt
index afd1ba8c88..d89d245766 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt
@@ -4,14 +4,7 @@ import android.content.Context
import android.util.AttributeSet
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Arrangement
-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.foundation.layout.*
import androidx.compose.material.Divider
import androidx.compose.material.Surface
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.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
-import com.tangem.core.ui.components.SelectorButton
-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.components.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.domain.model.TotalFiatBalance
@@ -42,7 +31,8 @@ import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
import java.text.NumberFormat
-import java.util.*
+import java.util.Currency
+import java.util.Locale
internal class TotalBalanceCard @JvmOverloads constructor(
context: Context,
@@ -125,7 +115,7 @@ private fun TotalBalanceCardContent(state: TotalBalanceCardState, modifier: Modi
-> LoadedAmount(
amount = buildAmountString(
amount = state.amount,
- fiatCurrencySymbol = state.fiatCurrency.symbol,
+ fiatCurrency = state.fiatCurrency,
),
)
}
@@ -228,30 +218,45 @@ private fun LoadedAmount(amount: AnnotatedString, modifier: Modifier = Modifier)
}
@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)
- val formatter = NumberFormat.getInstance(Locale.getDefault()) as? DecimalFormat
- ?: return AnnotatedString("${amount.toPlainString()} $fiatCurrencySymbol")
- val decimalFormat = formatter.apply {
- maximumFractionDigits = 2
- minimumFractionDigits = 2
- isGroupingUsed = true
- this.roundingMode = RoundingMode.HALF_UP
+ val locale = Locale.getDefault()
+ val fractionDigits = 2
+ val formatter = NumberFormat.getCurrencyInstance(locale) as? DecimalFormat
+ ?: return AnnotatedString("${amount.toPlainString()} ${fiatCurrency.symbol}")
+
+ val currencyToShow = "${fiatCurrency.symbol} "
+ 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 {
append(integer)
- append(decimalFormat.decimalFormatSymbols.decimalSeparator)
+ append(formatter.decimalFormatSymbols.decimalSeparator)
append(
AnnotatedString(
- text = "$reminder $fiatCurrencySymbol",
+ text = reminder,
spanStyle = TangemTheme.typography.h3.toSpanStyle(),
),
)
+ append(currency) // it is not empty if was placed at the end after locale formatting
}
}
diff --git a/app/src/main/res/drawable-hdpi/ic_eth.png b/app/src/main/res/drawable-hdpi/ic_eth.png
deleted file mode 100644
index 9db27f814e..0000000000
Binary files a/app/src/main/res/drawable-hdpi/ic_eth.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_eth.webp b/app/src/main/res/drawable-hdpi/ic_eth.webp
new file mode 100644
index 0000000000..ffe1bc6185
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_eth.webp differ
diff --git a/app/src/main/res/drawable-hdpi/meet_tangem.png b/app/src/main/res/drawable-hdpi/meet_tangem.png
deleted file mode 100644
index 25f2d5a3ba..0000000000
Binary files a/app/src/main/res/drawable-hdpi/meet_tangem.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/meet_tangem.webp b/app/src/main/res/drawable-hdpi/meet_tangem.webp
new file mode 100644
index 0000000000..e9b4ef6b19
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/meet_tangem.webp differ
diff --git a/app/src/main/res/drawable-hdpi/revolutionary_wallet.png b/app/src/main/res/drawable-hdpi/revolutionary_wallet.png
deleted file mode 100644
index f4f384a54d..0000000000
Binary files a/app/src/main/res/drawable-hdpi/revolutionary_wallet.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/revolutionary_wallet.webp b/app/src/main/res/drawable-hdpi/revolutionary_wallet.webp
new file mode 100644
index 0000000000..7e0f631f9c
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/revolutionary_wallet.webp differ
diff --git a/app/src/main/res/drawable-hdpi/wallet_for_everyone.png b/app/src/main/res/drawable-hdpi/wallet_for_everyone.png
deleted file mode 100644
index 6eec2f53dd..0000000000
Binary files a/app/src/main/res/drawable-hdpi/wallet_for_everyone.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/wallet_for_everyone.webp b/app/src/main/res/drawable-hdpi/wallet_for_everyone.webp
new file mode 100644
index 0000000000..e50874dfbf
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/wallet_for_everyone.webp differ
diff --git a/app/src/main/res/drawable-ldpi/ic_eth.png b/app/src/main/res/drawable-ldpi/ic_eth.png
deleted file mode 100644
index b8cd7b26ab..0000000000
Binary files a/app/src/main/res/drawable-ldpi/ic_eth.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_eth.webp b/app/src/main/res/drawable-ldpi/ic_eth.webp
new file mode 100644
index 0000000000..dc633be363
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_eth.webp differ
diff --git a/app/src/main/res/drawable-ldpi/ic_qcx.png b/app/src/main/res/drawable-ldpi/ic_qcx.png
deleted file mode 100644
index 68f2ded287..0000000000
Binary files a/app/src/main/res/drawable-ldpi/ic_qcx.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_qcx.webp b/app/src/main/res/drawable-ldpi/ic_qcx.webp
new file mode 100644
index 0000000000..9cea22a163
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_qcx.webp differ
diff --git a/app/src/main/res/drawable-mdpi/ic_eth.png b/app/src/main/res/drawable-mdpi/ic_eth.png
deleted file mode 100644
index e01e76371f..0000000000
Binary files a/app/src/main/res/drawable-mdpi/ic_eth.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_eth.webp b/app/src/main/res/drawable-mdpi/ic_eth.webp
new file mode 100644
index 0000000000..befd41d571
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_eth.webp differ
diff --git a/app/src/main/res/drawable-mdpi/meet_tangem.png b/app/src/main/res/drawable-mdpi/meet_tangem.png
deleted file mode 100644
index ef04e35830..0000000000
Binary files a/app/src/main/res/drawable-mdpi/meet_tangem.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/meet_tangem.webp b/app/src/main/res/drawable-mdpi/meet_tangem.webp
new file mode 100644
index 0000000000..7bd5ec80c5
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/meet_tangem.webp differ
diff --git a/app/src/main/res/drawable-mdpi/revolutionary_wallet.png b/app/src/main/res/drawable-mdpi/revolutionary_wallet.png
deleted file mode 100644
index 4dba3bffa4..0000000000
Binary files a/app/src/main/res/drawable-mdpi/revolutionary_wallet.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/revolutionary_wallet.webp b/app/src/main/res/drawable-mdpi/revolutionary_wallet.webp
new file mode 100644
index 0000000000..dfc7b106a9
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/revolutionary_wallet.webp differ
diff --git a/app/src/main/res/drawable-mdpi/wallet_for_everyone.png b/app/src/main/res/drawable-mdpi/wallet_for_everyone.png
deleted file mode 100644
index 9ec8c92210..0000000000
Binary files a/app/src/main/res/drawable-mdpi/wallet_for_everyone.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/wallet_for_everyone.webp b/app/src/main/res/drawable-mdpi/wallet_for_everyone.webp
new file mode 100644
index 0000000000..bf0ea6cf64
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/wallet_for_everyone.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_eth.png b/app/src/main/res/drawable-xhdpi/ic_eth.png
deleted file mode 100644
index 5e5807bf8b..0000000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_eth.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_eth.webp b/app/src/main/res/drawable-xhdpi/ic_eth.webp
new file mode 100644
index 0000000000..ba04cee99d
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_eth.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/meet_tangem.png b/app/src/main/res/drawable-xhdpi/meet_tangem.png
deleted file mode 100644
index 958f83e0a6..0000000000
Binary files a/app/src/main/res/drawable-xhdpi/meet_tangem.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/meet_tangem.webp b/app/src/main/res/drawable-xhdpi/meet_tangem.webp
new file mode 100644
index 0000000000..9bc7cba662
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/meet_tangem.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/revolutionary_wallet.png b/app/src/main/res/drawable-xhdpi/revolutionary_wallet.png
deleted file mode 100644
index e72d2ff281..0000000000
Binary files a/app/src/main/res/drawable-xhdpi/revolutionary_wallet.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/revolutionary_wallet.webp b/app/src/main/res/drawable-xhdpi/revolutionary_wallet.webp
new file mode 100644
index 0000000000..ee0435caf1
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/revolutionary_wallet.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/wallet_for_everyone.png b/app/src/main/res/drawable-xhdpi/wallet_for_everyone.png
deleted file mode 100644
index 773a3bb463..0000000000
Binary files a/app/src/main/res/drawable-xhdpi/wallet_for_everyone.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/wallet_for_everyone.webp b/app/src/main/res/drawable-xhdpi/wallet_for_everyone.webp
new file mode 100644
index 0000000000..2eec0c7074
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/wallet_for_everyone.webp differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_eth.png b/app/src/main/res/drawable-xxhdpi/ic_eth.png
deleted file mode 100644
index 1e7a0e7952..0000000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_eth.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_eth.webp b/app/src/main/res/drawable-xxhdpi/ic_eth.webp
new file mode 100644
index 0000000000..440f1fea5c
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_eth.webp differ
diff --git a/app/src/main/res/drawable-xxhdpi/meet_tangem.png b/app/src/main/res/drawable-xxhdpi/meet_tangem.png
deleted file mode 100644
index 4d5144346d..0000000000
Binary files a/app/src/main/res/drawable-xxhdpi/meet_tangem.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/meet_tangem.webp b/app/src/main/res/drawable-xxhdpi/meet_tangem.webp
new file mode 100644
index 0000000000..941a671afb
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/meet_tangem.webp differ
diff --git a/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.png b/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.png
deleted file mode 100644
index 83a8bc7963..0000000000
Binary files a/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.webp b/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.webp
new file mode 100644
index 0000000000..360f004149
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.webp differ
diff --git a/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.png b/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.png
deleted file mode 100644
index 18b099256b..0000000000
Binary files a/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.webp b/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.webp
new file mode 100644
index 0000000000..408f94af76
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.webp differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_eth.png b/app/src/main/res/drawable-xxxhdpi/ic_eth.png
deleted file mode 100644
index 74ead90795..0000000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_eth.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_eth.webp b/app/src/main/res/drawable-xxxhdpi/ic_eth.webp
new file mode 100644
index 0000000000..8a3417ce7b
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_eth.webp differ
diff --git a/app/src/main/res/drawable-xxxhdpi/meet_tangem.png b/app/src/main/res/drawable-xxxhdpi/meet_tangem.png
deleted file mode 100644
index a84bb7b804..0000000000
Binary files a/app/src/main/res/drawable-xxxhdpi/meet_tangem.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/meet_tangem.webp b/app/src/main/res/drawable-xxxhdpi/meet_tangem.webp
new file mode 100644
index 0000000000..8ca89394bc
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/meet_tangem.webp differ
diff --git a/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.png b/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.png
deleted file mode 100644
index bc0d94be7f..0000000000
Binary files a/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.webp b/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.webp
new file mode 100644
index 0000000000..9568833439
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.webp differ
diff --git a/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.png b/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.png
deleted file mode 100644
index 1d99d407ab..0000000000
Binary files a/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.webp b/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.webp
new file mode 100644
index 0000000000..5dc7baec82
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.webp differ
diff --git a/app/src/main/res/drawable/currency0.png b/app/src/main/res/drawable/currency0.png
deleted file mode 100644
index 0d293ec8bb..0000000000
Binary files a/app/src/main/res/drawable/currency0.png and /dev/null differ
diff --git a/app/src/main/res/drawable/currency0.webp b/app/src/main/res/drawable/currency0.webp
new file mode 100644
index 0000000000..a55afc36fe
Binary files /dev/null and b/app/src/main/res/drawable/currency0.webp differ
diff --git a/app/src/main/res/drawable/currency1.png b/app/src/main/res/drawable/currency1.png
deleted file mode 100644
index 37144efffe..0000000000
Binary files a/app/src/main/res/drawable/currency1.png and /dev/null differ
diff --git a/app/src/main/res/drawable/currency1.webp b/app/src/main/res/drawable/currency1.webp
new file mode 100644
index 0000000000..b24e1009ff
Binary files /dev/null and b/app/src/main/res/drawable/currency1.webp differ
diff --git a/app/src/main/res/drawable/currency2.png b/app/src/main/res/drawable/currency2.png
deleted file mode 100644
index bd75790221..0000000000
Binary files a/app/src/main/res/drawable/currency2.png and /dev/null differ
diff --git a/app/src/main/res/drawable/currency2.webp b/app/src/main/res/drawable/currency2.webp
new file mode 100644
index 0000000000..86dfb0f2d4
Binary files /dev/null and b/app/src/main/res/drawable/currency2.webp differ
diff --git a/app/src/main/res/drawable/currency3.png b/app/src/main/res/drawable/currency3.png
deleted file mode 100644
index c517578807..0000000000
Binary files a/app/src/main/res/drawable/currency3.png and /dev/null differ
diff --git a/app/src/main/res/drawable/currency3.webp b/app/src/main/res/drawable/currency3.webp
new file mode 100644
index 0000000000..a6a5da8499
Binary files /dev/null and b/app/src/main/res/drawable/currency3.webp differ
diff --git a/app/src/main/res/drawable/currency4.png b/app/src/main/res/drawable/currency4.png
deleted file mode 100644
index 9a39d5651d..0000000000
Binary files a/app/src/main/res/drawable/currency4.png and /dev/null differ
diff --git a/app/src/main/res/drawable/currency4.webp b/app/src/main/res/drawable/currency4.webp
new file mode 100644
index 0000000000..517c55c0f7
Binary files /dev/null and b/app/src/main/res/drawable/currency4.webp differ
diff --git a/app/src/main/res/drawable/dapps0.png b/app/src/main/res/drawable/dapps0.png
deleted file mode 100644
index 6152b1215b..0000000000
Binary files a/app/src/main/res/drawable/dapps0.png and /dev/null differ
diff --git a/app/src/main/res/drawable/dapps0.webp b/app/src/main/res/drawable/dapps0.webp
new file mode 100644
index 0000000000..65809f5fe4
Binary files /dev/null and b/app/src/main/res/drawable/dapps0.webp differ
diff --git a/app/src/main/res/drawable/dapps1.png b/app/src/main/res/drawable/dapps1.png
deleted file mode 100644
index 2d4effaf8b..0000000000
Binary files a/app/src/main/res/drawable/dapps1.png and /dev/null differ
diff --git a/app/src/main/res/drawable/dapps1.webp b/app/src/main/res/drawable/dapps1.webp
new file mode 100644
index 0000000000..833c952010
Binary files /dev/null and b/app/src/main/res/drawable/dapps1.webp differ
diff --git a/app/src/main/res/drawable/dapps2.png b/app/src/main/res/drawable/dapps2.png
deleted file mode 100644
index f7643c4ec7..0000000000
Binary files a/app/src/main/res/drawable/dapps2.png and /dev/null differ
diff --git a/app/src/main/res/drawable/dapps2.webp b/app/src/main/res/drawable/dapps2.webp
new file mode 100644
index 0000000000..a13cb38ba8
Binary files /dev/null and b/app/src/main/res/drawable/dapps2.webp differ
diff --git a/app/src/main/res/drawable/dapps3.png b/app/src/main/res/drawable/dapps3.png
deleted file mode 100644
index 9e0110179b..0000000000
Binary files a/app/src/main/res/drawable/dapps3.png and /dev/null differ
diff --git a/app/src/main/res/drawable/dapps3.webp b/app/src/main/res/drawable/dapps3.webp
new file mode 100644
index 0000000000..99f594fd3d
Binary files /dev/null and b/app/src/main/res/drawable/dapps3.webp differ
diff --git a/app/src/main/res/drawable/dapps4.png b/app/src/main/res/drawable/dapps4.png
deleted file mode 100644
index 4eae3c0985..0000000000
Binary files a/app/src/main/res/drawable/dapps4.png and /dev/null differ
diff --git a/app/src/main/res/drawable/dapps4.webp b/app/src/main/res/drawable/dapps4.webp
new file mode 100644
index 0000000000..15704d6a6e
Binary files /dev/null and b/app/src/main/res/drawable/dapps4.webp differ
diff --git a/app/src/main/res/drawable/dapps5.png b/app/src/main/res/drawable/dapps5.png
deleted file mode 100644
index 0c581624c7..0000000000
Binary files a/app/src/main/res/drawable/dapps5.png and /dev/null differ
diff --git a/app/src/main/res/drawable/dapps5.webp b/app/src/main/res/drawable/dapps5.webp
new file mode 100644
index 0000000000..5d6370f05a
Binary files /dev/null and b/app/src/main/res/drawable/dapps5.webp differ
diff --git a/app/src/main/res/drawable/ic_voyr.png b/app/src/main/res/drawable/ic_voyr.png
deleted file mode 100644
index 545990d041..0000000000
Binary files a/app/src/main/res/drawable/ic_voyr.png and /dev/null differ
diff --git a/app/src/main/res/drawable/ic_voyr.webp b/app/src/main/res/drawable/ic_voyr.webp
new file mode 100644
index 0000000000..2343599d4b
Binary files /dev/null and b/app/src/main/res/drawable/ic_voyr.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100755
index e307de6027..0000000000
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000000..553cf934c1
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100755
index cfab76de31..0000000000
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000000..166f2867c7
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100755
index bddcb01270..0000000000
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000000..e143972134
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100755
index ac5cb152bb..0000000000
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000000..8c9245318b
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100755
index 533177434c..0000000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000000..3b746049eb
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
deleted file mode 100644
index d32c73f660..0000000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp
new file mode 100644
index 0000000000..541a4842d7
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 9b72259299..0000000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
new file mode 100644
index 0000000000..6b7e439344
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 4d71fe324b..6b0879d8e1 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -46,6 +46,8 @@
Чат
Принять
Добавить
+ Применить
+ Одобрение
Внимание
Баланс: %s
биометрическую аутентификацию
@@ -73,7 +75,9 @@
Начать
Отправить
Успешно
+ Обмен
условия участия
+ Перевод
Я понял
Да
Адрес контракта скопирован!
@@ -255,6 +259,9 @@
Восстановление кода доступа
Идентичные карты
Код доступа
+ Группировка
+ По балансу
+ Сортировка токенов
Участвовать
Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже.
Не удалось загрузить информацию по реферальной программе. Код ошибки: %s. Пожалуйста, попробуйте позже.
@@ -382,7 +389,6 @@
Безлимитно
Открыть в обозревателе
В процессе
- Обмен
Обменять
Обмен %s на
Котировки включают дополнительную комиссию Tangem в размере %s. Это помогает нам предоставлять первоклассный продукт.
diff --git a/core/res/src/main/res/values-zh-rTW/strings.xml b/core/res/src/main/res/values-zh-rTW/strings.xml
index 461c90bc77..ab1801d759 100644
--- a/core/res/src/main/res/values-zh-rTW/strings.xml
+++ b/core/res/src/main/res/values-zh-rTW/strings.xml
@@ -69,6 +69,7 @@
開始
提交
成功
+ 交換
條款和條件
我了解
是
@@ -367,7 +368,6 @@
要繼續,您需要允許 1inch 智能合約使用您的 %s
在瀏覽器中查看
進行中
- 交換
交易
交易 %s 至
此外,報價包括%s的 Tangem 費用。這有助於我們提供一流的產品
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 695c74084b..405c31d86a 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -44,6 +44,8 @@
Support
Accept
Add
+ Apply
+ Approval
Attention
Balance: %s
biometric authentication
@@ -71,7 +73,9 @@
Start
Submit
Success
+ Swap
terms and conditions
+ Transfer
I understand
Yes
Contract address copied!
@@ -253,6 +257,9 @@
Access code restore
Identical cards
Access code
+ Group
+ By balance
+ Organize tokens
Participate
Failed to load the information about the referral program. Please try again later.
Failed to load the information about the referral program. Error code: %s. Please try again later.
@@ -378,7 +385,6 @@
Unlimited
View in Explorer
In progress
- Swap
Swap
Swap of %s to
Quotes include an additional Tangem commission of %s. This helps us deliver a top-of-the-line product.
diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts
index 1dc31c8335..94bb016bdc 100644
--- a/core/ui/build.gradle.kts
+++ b/core/ui/build.gradle.kts
@@ -9,8 +9,10 @@ dependencies {
implementation(deps.androidx.fragment.ktx)
/** Compose */
+ implementation(deps.compose.constraintLayout)
implementation(deps.compose.foundation)
implementation(deps.compose.material)
+ implementation(deps.compose.material3)
implementation(deps.compose.ui.tooling)
/** Other libraries */
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt
index 00a6b2ac03..5ca9a16de8 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt
@@ -312,14 +312,8 @@ private fun TangemButton(
textStyle: TextStyle = TangemTheme.typography.button,
) {
Button(
- modifier = modifier
- .width(IntrinsicSize.Min)
- .heightIn(min = size.toHeightDp()),
- onClick = {
- if (!showProgress) {
- onClick()
- }
- },
+ modifier = modifier.heightIn(min = size.toHeightDp()),
+ onClick = { if (!showProgress) onClick() },
enabled = enabled,
elevation = elevation,
shape = size.toShape(),
@@ -588,59 +582,44 @@ private open class TangemButtonColors(
// region Preview
@Composable
-private fun PrimaryButtonSample(modifier: Modifier = Modifier) {
+private fun PrimaryButtonSample() {
Column(
- modifier = modifier
- .background(TangemTheme.colors.background.primary),
+ modifier = Modifier.background(TangemTheme.colors.background.primary),
+ verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
- PrimaryButton(
- modifier = Modifier.fillMaxWidth(),
- 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))
+ PrimaryButton(modifier = Modifier.fillMaxWidth(), text = "Manage tokens", onClick = { })
+ PrimaryButton(modifier = Modifier.fillMaxWidth(), showProgress = true, text = "Manage tokens", onClick = { })
PrimaryButtonIconEnd(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
iconResId = R.drawable.ic_tangem_24,
- onClick = { /* no-op */ },
+ onClick = { },
)
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButtonIconStart(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
iconResId = R.drawable.ic_tangem_24,
- onClick = { /* no-op */ },
+ onClick = { },
)
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButton(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
enabled = false,
- onClick = { /* no-op */ },
+ onClick = { },
)
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButtonIconEnd(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
iconResId = R.drawable.ic_tangem_24,
enabled = false,
- onClick = { /* no-op */ },
+ onClick = { },
)
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButtonIconStart(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
iconResId = R.drawable.ic_tangem_24,
enabled = false,
- onClick = { /* no-op */ },
+ onClick = { },
)
}
}
@@ -662,59 +641,44 @@ private fun PrimaryButtonPreview_Dark() {
}
@Composable
-private fun SecondaryButtonSample(modifier: Modifier = Modifier) {
+private fun SecondaryButtonSample() {
Column(
- modifier = modifier
- .background(TangemTheme.colors.background.primary),
+ modifier = Modifier.background(TangemTheme.colors.background.primary),
+ verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
- SecondaryButton(
- modifier = Modifier.fillMaxWidth(),
- 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))
+ SecondaryButton(modifier = Modifier.fillMaxWidth(), text = "Manage tokens", onClick = { })
+ SecondaryButton(modifier = Modifier.fillMaxWidth(), showProgress = true, text = "Manage tokens", onClick = { })
SecondaryButtonIconEnd(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
iconResId = R.drawable.ic_tangem_24,
- onClick = { /* no-op */ },
+ onClick = { },
)
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButtonIconStart(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
iconResId = R.drawable.ic_tangem_24,
- onClick = { /* no-op */ },
+ onClick = { },
)
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButton(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
enabled = false,
- onClick = { /* no-op */ },
+ onClick = { },
)
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButtonIconEnd(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
iconResId = R.drawable.ic_tangem_24,
enabled = false,
- onClick = { /* no-op */ },
+ onClick = { },
)
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButtonIconStart(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
iconResId = R.drawable.ic_tangem_24,
enabled = false,
- onClick = { /* no-op */ },
+ onClick = { },
)
}
}
@@ -736,50 +700,23 @@ private fun SecondaryButtonPreview_Dark() {
}
@Composable
-private fun TextButtonSample(modifier: Modifier = Modifier) {
+private fun TextButtonSample() {
Column(
- modifier = modifier
- .background(TangemTheme.colors.background.primary),
+ modifier = Modifier.background(TangemTheme.colors.background.primary),
+ verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
- TextButton(
- text = "Enabled",
- onClick = { /* no-op */ },
- )
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
- TextButtonIconStart(
- 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 */ },
- )
+ TextButton(text = "Enabled", onClick = { })
+ TextButtonIconStart(text = "Enabled", iconResId = R.drawable.ic_plus_24, onClick = { })
+ TextButton(text = "Enabled", enabled = false, onClick = { })
+ TextButtonIconStart(text = "Enabled", iconResId = R.drawable.ic_plus_24, enabled = false, onClick = { })
+ WarningTextButton(text = "Delete", onClick = { })
+ SelectorButton(text = "USD", onClick = { })
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
-private fun TextButtonPreview_Light() {
+private fun TextButtonPreview_LightTheme() {
TangemTheme {
TextButtonSample()
}
@@ -787,62 +724,30 @@ private fun TextButtonPreview_Light() {
@Preview(showBackground = true, widthDp = 360)
@Composable
-private fun TextButtonPreview_Dark() {
+private fun TextButtonPreview_DarkTheme() {
TangemTheme(isDark = true) {
TextButtonSample()
}
}
@Composable
-private fun ActionButtonSample(modifier: Modifier = Modifier) {
+private fun ActionButtonSample() {
Column(
- modifier = modifier
- .background(TangemTheme.colors.background.primary),
+ modifier = Modifier.background(TangemTheme.colors.background.primary),
+ verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
- RoundedActionButton(
- text = "Send",
- iconResId = R.drawable.ic_arrow_up_24,
- onClick = { /* [REDACTED_TODO_COMMENT]*/ },
- )
- Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
- 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]*/ },
- )
+ 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_Light() {
+private fun ActionButtonPreview_LightTheme() {
TangemTheme {
ActionButtonSample()
}
@@ -850,7 +755,7 @@ private fun ActionButtonPreview_Light() {
@Preview(showBackground = true, widthDp = 360)
@Composable
-private fun ActionButtonPreview_Dark() {
+private fun ActionButtonPreview_DarkTheme() {
TangemTheme(isDark = true) {
ActionButtonSample()
}
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt
new file mode 100644
index 0000000000..0f265ecce9
--- /dev/null
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt
@@ -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 Figma Component
+ *
+[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(
+ 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,
+ ),
+)
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/TransactionState.kt b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/TransactionState.kt
new file mode 100644
index 0000000000..f0502a4a21
--- /dev/null
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/TransactionState.kt
@@ -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
+}
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/TextReference.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/TextReference.kt
index e70b0d7015..a27dcb58c4 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/extensions/TextReference.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/TextReference.kt
@@ -2,22 +2,42 @@ package com.tangem.core.ui.extensions
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ReadOnlyComposable
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 {
- class Res(@StringRes val id: Int, val formatArgs: List = 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 = WrappedList(emptyList())) : TextReference
+
+ /**
+ * Text string
+ *
+ * @property value value
+ */
+ data class Str(val value: String) : TextReference
}
+/** Get text */
@Composable
@ReadOnlyComposable
fun TextReference.resolveReference(): String {
return when (this) {
- is TextReference.Res -> stringResource(this.id, *this.formatArgs.toTypedArray())
- is TextReference.Str -> this.value
+ is TextReference.Res -> stringResource(id, *formatArgs.toTypedArray())
+ is TextReference.Str -> value
}
}
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/WrappedList.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/WrappedList.kt
new file mode 100644
index 0000000000..6f529c9574
--- /dev/null
+++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/WrappedList.kt
@@ -0,0 +1,10 @@
+package com.tangem.core.ui.extensions
+
+import androidx.compose.runtime.Immutable
+
+/**
+[REDACTED_AUTHOR]
+ */
+@JvmInline
+@Immutable
+value class WrappedList(val data: List) : List by data
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt
index c2fbac9891..421c82c9e1 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt
@@ -56,9 +56,11 @@ data class TangemDimens internal constructor(
val size46: Dp = 46.dp,
val size48: Dp = 48.dp,
val size50: Dp = 50.dp,
+ val size52: Dp = 52.dp,
val size56: Dp = 56.dp,
val size62: Dp = 62.dp,
val size68: Dp = 68.dp,
+ val size70: Dp = 70.dp,
val size72: Dp = 72.dp,
val size80: Dp = 80.dp,
val size84: Dp = 84.dp,
diff --git a/core/ui/src/main/res/drawable/ic_doc_24.xml b/core/ui/src/main/res/drawable/ic_doc_24.xml
new file mode 100644
index 0000000000..8855153e59
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_doc_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_filter_24.xml b/core/ui/src/main/res/drawable/ic_filter_24.xml
new file mode 100644
index 0000000000..b88ca7dcef
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_filter_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_group_24.xml b/core/ui/src/main/res/drawable/ic_group_24.xml
new file mode 100644
index 0000000000..0f5f5f4487
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_group_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_sort_24.xml b/core/ui/src/main/res/drawable/ic_sort_24.xml
new file mode 100644
index 0000000000..538a24d8e0
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_sort_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
index f5a39df29e..acad315b28 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
@@ -54,7 +54,7 @@ internal fun SwapScreenContent(state: SwapStateHolder, onPermissionWarningClick:
Column {
AppBarWithBackButton(
- text = stringResource(R.string.swapping_swap),
+ text = stringResource(R.string.common_swap),
onBackClick = state.onBackClicked,
iconRes = R.drawable.ic_close_24,
)
@@ -348,7 +348,7 @@ private fun MainButton(state: SwapStateHolder, onPermissionWarningClick: () -> U
else -> {
PrimaryButtonIconEnd(
modifier = Modifier.fillMaxWidth(),
- text = stringResource(id = R.string.swapping_swap),
+ text = stringResource(id = R.string.common_swap),
iconResId = R.drawable.ic_tangem_24,
enabled = state.swapButton.enabled,
showProgress = state.swapButton.loading,
@@ -384,7 +384,7 @@ private val receiveCard = SwapCardData(
coinId = "",
)
-val stateSelectable = SelectableItemsState(
+val stateSelectable = SelectableItemsState(
selectedItem = Item(
0,
TextReference.Str("Balance"),
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSuccessScreen.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSuccessScreen.kt
index d8ad3e646a..2d6f3e52b4 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSuccessScreen.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSuccessScreen.kt
@@ -39,7 +39,7 @@ fun SwapSuccessScreen(state: SwapSuccessStateHolder, onBack: () -> Unit) {
},
topBar = {
AppBarWithBackButton(
- text = stringResource(R.string.swapping_swap),
+ text = stringResource(R.string.common_swap),
onBackClick = onBack,
iconRes = R.drawable.ic_close_24,
)
diff --git a/features/wallet/impl/build.gradle.kts b/features/wallet/impl/build.gradle.kts
index 183e43c174..c639f23ac8 100644
--- a/features/wallet/impl/build.gradle.kts
+++ b/features/wallet/impl/build.gradle.kts
@@ -22,6 +22,8 @@ dependencies {
implementation(deps.compose.ui.tooling)
implementation(deps.compose.shimmer)
implementation(deps.compose.accompanist.systemUiController)
+
+ /** Other libraries */
implementation(deps.kotlin.immutable.collections)
/** DI */
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt
index 04e93bf88f..954467d0fe 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt
@@ -7,6 +7,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
+import com.tangem.core.ui.components.SystemBarsEffect
+import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import com.tangem.features.wallet.navigation.WalletRouter
@@ -38,8 +40,15 @@ internal class WalletFragment : Fragment() {
return ComposeView(inflater.context).apply {
setContent {
- isTransitionGroup = true
- _walletRouter.Initialize()
+ TangemTheme {
+ val systemBarsColor = TangemTheme.colors.background.secondary
+ SystemBarsEffect {
+ setSystemBarsColor(systemBarsColor)
+ }
+
+ isTransitionGroup = true
+ _walletRouter.Initialize()
+ }
}
}
}
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt
index 40817e750e..92c8d8f644 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt
@@ -1,19 +1,23 @@
package com.tangem.feature.wallet.presentation.common
import com.tangem.core.ui.R
-import com.tangem.feature.wallet.presentation.common.state.NetworkGroupState
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState
-import com.tangem.feature.wallet.presentation.common.state.TokenListState
+import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem
+import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensListState
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder
import com.tangem.feature.wallet.presentation.wallet.state.WalletCardState
+import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
import kotlinx.collections.immutable.persistentListOf
+import kotlinx.collections.immutable.toPersistentList
import java.util.UUID
internal object WalletPreviewData {
- val walletCardContent = WalletCardState.Content(
+ val walletTopBarConfig = WalletStateHolder.TopBarConfig(onScanCardClick = {}, onMoreClick = {})
+
+ val walletCardContentState = WalletCardState.Content(
id = UUID.randomUUID().toString(),
title = "Wallet 1",
balance = "8923,05 $",
@@ -22,7 +26,7 @@ internal object WalletPreviewData {
onClick = {},
)
- val walletCardLoading = WalletCardState.Loading(
+ val walletCardLoadingState = WalletCardState.Loading(
id = UUID.randomUUID().toString(),
title = "Wallet 1",
additionalInfo = "3 cards • Seed enabled",
@@ -30,7 +34,7 @@ internal object WalletPreviewData {
onClick = {},
)
- val walletCardHiddenContent = WalletCardState.HiddenContent(
+ val walletCardHiddenContentState = WalletCardState.HiddenContent(
id = UUID.randomUUID().toString(),
title = "Wallet 1",
additionalInfo = "3 cards • Seed enabled",
@@ -38,7 +42,7 @@ internal object WalletPreviewData {
onClick = {},
)
- val walletCardError = WalletCardState.Error(
+ val walletCardErrorState = WalletCardState.Error(
id = UUID.randomUUID().toString(),
title = "Wallet 1",
additionalInfo = "3 cards • Seed enabled",
@@ -46,15 +50,6 @@ internal object WalletPreviewData {
onClick = {},
)
- val walletScreenState = WalletStateHolder(
- onBackClick = {},
- headerConfig = WalletStateHolder.HeaderConfig(
- wallets = persistentListOf(walletCardContent, walletCardLoading, walletCardHiddenContent, walletCardError),
- onScanCardClick = {},
- onMoreClick = {},
- ),
- )
-
val tokenItemVisibleState = TokenItemState.Content(
id = UUID.randomUUID().toString(),
tokenIconUrl = null,
@@ -107,9 +102,46 @@ internal object WalletPreviewData {
val loadingTokenItemState = TokenItemState.Loading(id = UUID.randomUUID().toString())
- val organizeTokensState = OrganizeTokensStateHolder(
- tokens = TokenListState.GroupedByNetwork(
- groups = persistentListOf(),
+ private const val networksSize = 10
+ private const val tokensSize = 3
+ val draggableItems = List(networksSize) { it }
+ .flatMap { index ->
+ val n = index + 1
+
+ val group = DraggableItem.GroupHeader(
+ id = "group_$n",
+ networkName = "$n",
+ )
+
+ val tokens: MutableList = mutableListOf()
+ repeat(times = tokensSize) { i ->
+ val nt = i + 1
+ tokens.add(
+ DraggableItem.Token(
+ tokenItemState = tokenItemDragState.copy(
+ id = "${group.id}_token_$nt",
+ name = "Token $nt",
+ networkIconResId = R.drawable.img_eth_22.takeIf { i != 0 },
+ ),
+ groupId = group.id,
+ ),
+ )
+ }
+
+ buildList {
+ add(group)
+ addAll(tokens)
+ }
+ }
+ .toPersistentList()
+
+ val draggableTokens = draggableItems
+ .filterIsInstance()
+ .toPersistentList()
+
+ val groupedOrganizeTokensState = OrganizeTokensStateHolder(
+ itemsState = OrganizeTokensListState.GroupedByNetwork(
+ items = draggableItems,
),
header = OrganizeTokensStateHolder.HeaderConfig(
onSortByBalanceClick = {},
@@ -121,57 +153,71 @@ internal object WalletPreviewData {
),
)
- private val draggableTokenList = persistentListOf(
- tokenItemDragState.copy(
- id = "token_1",
- name = "Ethereum",
- tokenIconResId = R.drawable.img_eth_22,
- networkIconResId = null,
- fiatAmount = "3 172,14 $",
- ),
- tokenItemDragState.copy(
- id = "token_2",
- networkIconResId = R.drawable.img_eth_22,
- fiatAmount = "803,65 $",
- ),
- tokenItemDragState.copy(
- id = "token_3",
- name = "USDT",
- tokenIconResId = R.drawable.img_arbitrum_22,
- networkIconResId = R.drawable.img_eth_22,
- fiatAmount = "88,01 $",
+ val organizeTokensState = groupedOrganizeTokensState.copy(
+ itemsState = OrganizeTokensListState.Ungrouped(
+ items = draggableTokens,
),
)
- val networkGroup = NetworkGroupState.Content(
- id = UUID.randomUUID().toString(),
- networkName = "Ethereum",
- tokens = persistentListOf(
- tokenItemVisibleState.copy(
- id = "token_1",
- name = "Ethereum",
- tokenIconResId = R.drawable.img_eth_22,
- networkIconResId = null,
- amount = "1,89340821 ETH",
+ val groupedWalletScreenState = WalletStateHolder(
+ onBackClick = {},
+ topBarConfig = walletTopBarConfig,
+ selectedWallet = walletCardContentState,
+ wallets = persistentListOf(
+ walletCardContentState,
+ walletCardLoadingState,
+ walletCardHiddenContentState,
+ walletCardErrorState,
+ ),
+ contentItems = persistentListOf(
+ WalletContentItemState.NetworkGroupTitle("Bitcoin"),
+ WalletContentItemState.Token(
+ tokenItemVisibleState.copy(
+ id = "token_1",
+ name = "Ethereum",
+ tokenIconResId = R.drawable.img_eth_22,
+ networkIconResId = null,
+ amount = "1,89340821 ETH",
+ ),
),
- tokenItemVisibleState.copy(
- id = "token_2",
- networkIconResId = R.drawable.img_eth_22,
- amount = "733,71097 MATIC",
+ WalletContentItemState.Token(
+ tokenItemVisibleState.copy(
+ id = "token_2",
+ name = "Ethereum",
+ tokenIconResId = R.drawable.img_eth_22,
+ networkIconResId = null,
+ amount = "1,89340821 ETH",
+ ),
),
- tokenItemVisibleState.copy(
- id = "token_3",
- name = "USDT",
- tokenIconResId = R.drawable.img_arbitrum_22,
- networkIconResId = R.drawable.img_eth_22,
- amount = "0,25404523 ARB",
+ WalletContentItemState.Token(
+ tokenItemVisibleState.copy(
+ id = "token_3",
+ name = "Ethereum",
+ tokenIconResId = R.drawable.img_eth_22,
+ networkIconResId = null,
+ amount = "1,89340821 ETH",
+ ),
+ ),
+ WalletContentItemState.Token(
+ tokenItemVisibleState.copy(
+ id = "token_4",
+ name = "Ethereum",
+ tokenIconResId = R.drawable.img_eth_22,
+ networkIconResId = null,
+ amount = "1,89340821 ETH",
+ ),
+ ),
+ WalletContentItemState.NetworkGroupTitle("Ethereum"),
+ WalletContentItemState.Token(
+ tokenItemVisibleState.copy(
+ id = "token_5",
+ name = "Ethereum",
+ tokenIconResId = R.drawable.img_eth_22,
+ networkIconResId = null,
+ amount = "1,89340821 ETH",
+ ),
),
),
- )
-
- val draggableNetworkGroup = NetworkGroupState.Draggable(
- id = UUID.randomUUID().toString(),
- networkName = "Ethereum",
- tokens = draggableTokenList,
+ onOrganizeTokensClick = {},
)
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/NetworkGroupItem.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/NetworkGroupItem.kt
index ee2d924e85..82e40737c5 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/NetworkGroupItem.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/NetworkGroupItem.kt
@@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.*
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
@@ -15,65 +14,83 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.impl.R
-import com.tangem.feature.wallet.presentation.common.WalletPreviewData
-import com.tangem.feature.wallet.presentation.common.state.NetworkGroupState
@Composable
-internal fun NetworkGroupItem(state: NetworkGroupState, modifier: Modifier = Modifier) {
+internal fun NetworkGroupItem(networkName: String, modifier: Modifier = Modifier) {
+ InternalNetworkGroupItem(
+ modifier = modifier,
+ networkName = networkName,
+ )
+}
+
+@Composable
+internal fun DraggableNetworkGroupItem(networkName: String, modifier: Modifier = Modifier) {
+ InternalNetworkGroupItem(
+ modifier = modifier,
+ networkName = networkName,
+ endIcon = {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_group_drop_24),
+ tint = TangemTheme.colors.icon.informative,
+ contentDescription = null,
+ )
+ },
+ )
+}
+
+@Composable
+private fun InternalNetworkGroupItem(
+ networkName: String,
+ modifier: Modifier = Modifier,
+ endIcon: @Composable RowScope.() -> Unit = {},
+) {
Column(modifier = modifier) {
Row(
modifier = Modifier
.background(TangemTheme.colors.background.primary)
- .padding(horizontal = TangemTheme.dimens.spacing12)
+ .padding(horizontal = TangemTheme.dimens.spacing14)
.fillMaxWidth()
.heightIn(min = TangemTheme.dimens.size48),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
- text = stringResource(id = R.string.wallet_network_group_title, state.networkName),
+ text = stringResource(id = R.string.wallet_network_group_title, networkName),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
- if (state is NetworkGroupState.Draggable) {
- Icon(
- painter = painterResource(id = R.drawable.ic_group_drop_24),
- tint = TangemTheme.colors.icon.informative,
- contentDescription = null,
- )
- }
- }
- Column {
- state.tokens.forEach { token ->
- key(token.id) {
- TokenItem(state = token)
- }
- }
+ endIcon()
}
}
}
// region Preview
+@Composable
+private fun NetworkGroupItemSample(isDraggable: Boolean) {
+ if (isDraggable) {
+ DraggableNetworkGroupItem(networkName = "Ethereum")
+ } else {
+ NetworkGroupItem(networkName = "Ethereum")
+ }
+}
+
@Preview(showBackground = true, widthDp = 360)
@Composable
-private fun NetworkGroupItemPreview_Light(@PreviewParameter(NetworkGroupProvider::class) group: NetworkGroupState) {
+private fun NetworkGroupItemPreview_Light(@PreviewParameter(NetworkGroupProvider::class) isDraggable: Boolean) {
TangemTheme {
- NetworkGroupItem(group)
+ NetworkGroupItemSample(isDraggable)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
-private fun NetworkGroupItemPreview_Dark(@PreviewParameter(NetworkGroupProvider::class) group: NetworkGroupState) {
+private fun NetworkGroupItemPreview_Dark(@PreviewParameter(NetworkGroupProvider::class) isDraggable: Boolean) {
TangemTheme(isDark = true) {
- NetworkGroupItem(group)
+ NetworkGroupItemSample(isDraggable)
}
}
-private class NetworkGroupProvider : CollectionPreviewParameterProvider(
- collection = listOf(
- WalletPreviewData.networkGroup,
- WalletPreviewData.draggableNetworkGroup,
- ),
+private class NetworkGroupProvider : CollectionPreviewParameterProvider(
+ collection = listOf(true, false),
)
// endregion Preview
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt
index 78c5b5f322..de8daa9cb8 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt
@@ -9,6 +9,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -18,6 +19,7 @@ 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 androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstrainedLayoutReference
import androidx.constraintlayout.compose.ConstraintLayout
@@ -34,6 +36,10 @@ import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState
private const val DOTS = "•••"
+val TOKEN_ITEM_HEIGHT: Dp
+ @Composable
+ @ReadOnlyComposable
+ get() = TangemTheme.dimens.size68
@Composable
internal fun TokenItem(state: TokenItemState, modifier: Modifier = Modifier) {
@@ -76,7 +82,8 @@ internal fun DraggableTokenItem(state: TokenItemState.Draggable, modifier: Modif
hasPending = false,
options = { ref ->
Icon(
- modifier = Modifier.constrainAsOptionsItem(scope = this, ref),
+ modifier = Modifier
+ .constrainAsOptionsItem(scope = this, ref),
painter = painterResource(id = R.drawable.ic_drag_24),
tint = TangemTheme.colors.icon.informative,
contentDescription = null,
@@ -199,7 +206,7 @@ private fun InternalTokenItem(
modifier = Modifier
.fillMaxWidth()
.padding(
- horizontal = TangemTheme.dimens.spacing12,
+ horizontal = TangemTheme.dimens.spacing14,
vertical = TangemTheme.dimens.spacing4,
),
) {
@@ -251,7 +258,7 @@ private fun BaseSurface(
content: @Composable () -> Unit,
) {
Surface(
- modifier = modifier.defaultMinSize(minHeight = TangemTheme.dimens.size68),
+ modifier = modifier.defaultMinSize(minHeight = TOKEN_ITEM_HEIGHT),
color = TangemTheme.colors.background.primary,
onClick = onClick ?: {},
enabled = onClick != null,
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/NetworkGroupState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/NetworkGroupState.kt
deleted file mode 100644
index c34fdd126d..0000000000
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/NetworkGroupState.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.tangem.feature.wallet.presentation.common.state
-
-import androidx.compose.runtime.Immutable
-import kotlinx.collections.immutable.ImmutableList
-
-@Immutable
-internal sealed interface NetworkGroupState {
- val id: String
- val networkName: String
- val tokens: ImmutableList
-
- data class Draggable(
- override val id: String,
- override val networkName: String,
- override val tokens: ImmutableList,
- ) : NetworkGroupState
-
- data class Content(
- override val id: String,
- override val networkName: String,
- override val tokens: ImmutableList,
- ) : NetworkGroupState
-}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenListState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenListState.kt
deleted file mode 100644
index fe3b7fba46..0000000000
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenListState.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.tangem.feature.wallet.presentation.common.state
-
-import androidx.compose.runtime.Immutable
-import kotlinx.collections.immutable.ImmutableList
-
-@Immutable
-internal sealed interface TokenListState {
-
- data class GroupedByNetwork(
- val groups: ImmutableList,
- ) : TokenListState
-
- data class Ungrouped(
- val tokens: ImmutableList,
- ) : TokenListState
-}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt
index f4b5bb65d0..fb6be5831b 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt
@@ -1,89 +1,256 @@
-// TODO: Remove after components implementation
-@file:Suppress("UNUSED_PARAMETER")
-
package com.tangem.feature.wallet.presentation.organizetokens
+import androidx.compose.animation.core.animateDpAsState
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
-import androidx.compose.material3.*
+import androidx.compose.foundation.lazy.*
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.AppBarDefaults
+import androidx.compose.material3.FabPosition
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.shadow
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
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.components.BackgroundActionButton
+import com.tangem.core.ui.components.PrimaryButton
+import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.res.TangemTheme
+import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
-import com.tangem.feature.wallet.presentation.common.state.TokenListState
+import com.tangem.feature.wallet.presentation.common.component.DraggableNetworkGroupItem
+import com.tangem.feature.wallet.presentation.common.component.DraggableTokenItem
@Composable
internal fun OrganizeTokensScreen(state: OrganizeTokensStateHolder, modifier: Modifier = Modifier) {
+ val tokensListState = rememberLazyListState()
+
Scaffold(
modifier = modifier,
topBar = {
- TopBar(state.header)
+ TopBar(state.header, tokensListState)
},
content = { paddingValues ->
TokenList(
- state = state.tokens,
modifier = Modifier.padding(paddingValues),
+ listState = tokensListState,
+ state = state.itemsState,
)
},
floatingActionButtonPosition = FabPosition.Center,
floatingActionButton = {
Actions(state.actions)
},
- contentColor = TangemTheme.colors.background.primary,
+ containerColor = TangemTheme.colors.background.secondary,
)
}
@Composable
-private fun TokenList(state: TokenListState, modifier: Modifier = Modifier) {
- when (state) {
- is TokenListState.GroupedByNetwork -> {
- /* [REDACTED_TODO_COMMENT] */
- }
- is TokenListState.Ungrouped -> {
- /* [REDACTED_TODO_COMMENT] */
+private fun TokenList(listState: LazyListState, state: OrganizeTokensListState, modifier: Modifier = Modifier) {
+ Box(modifier = modifier) {
+ LazyColumn(
+ modifier = Modifier
+ .align(Alignment.TopCenter)
+ .padding(horizontal = TangemTheme.dimens.spacing16),
+ state = listState,
+ contentPadding = PaddingValues(
+ top = TangemTheme.dimens.spacing12,
+ bottom = TangemTheme.dimens.spacing92,
+ ),
+ ) {
+ itemsIndexed(
+ items = state.items,
+ key = { _, item -> item.id },
+ ) { index, item ->
+ DraggableItem(
+ item = item,
+ index = index,
+ lastItemIndex = state.items.lastIndex,
+ )
+ }
}
+
+ BottomGradient(modifier = Modifier.align(Alignment.BottomCenter))
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
-private fun TopBar(config: OrganizeTokensStateHolder.HeaderConfig, modifier: Modifier = Modifier) {
- TopAppBar(
- title = {
+private fun DraggableItem(index: Int, item: DraggableItem, lastItemIndex: Int) {
+ val itemModifier = Modifier
+ .clipFirstAndLastItems(index, lastItemIndex)
+
+ when (item) {
+ is DraggableItem.GroupHeader -> DraggableNetworkGroupItem(
+ modifier = itemModifier,
+ networkName = item.networkName,
+ )
+ is DraggableItem.Token -> DraggableTokenItem(
+ modifier = itemModifier,
+ state = item.tokenItemState,
+ )
+ }
+}
+
+@Composable
+private fun BottomGradient(modifier: Modifier = Modifier) {
+ Box(
+ modifier = modifier
+ .fillMaxWidth()
+ .height(TangemTheme.dimens.size116)
+ .background(
+ brush = Brush.verticalGradient(
+ colors = listOf(
+ Color.Transparent,
+ TangemTheme.colors.background.secondary,
+ ),
+ ),
+ ),
+ )
+}
+
+@Composable
+private fun TopBar(
+ config: OrganizeTokensStateHolder.HeaderConfig,
+ tokensListState: LazyListState,
+ modifier: Modifier = Modifier,
+) {
+ val isElevationEnabled by remember {
+ derivedStateOf {
+ tokensListState.firstVisibleItemScrollOffset > 0
+ }
+ }
+ val elevation by animateDpAsState(
+ targetValue = if (isElevationEnabled) AppBarDefaults.TopAppBarElevation else TangemTheme.dimens.elevation0,
+ label = "top_bar_shadow_elevation",
+ )
+
+ Column(
+ modifier = modifier
+ .shadow(elevation)
+ .background(TangemTheme.colors.background.secondary)
+ .padding(horizontal = TangemTheme.dimens.spacing16)
+ .fillMaxWidth(),
+ ) {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .heightIn(min = TangemTheme.dimens.size56),
+ contentAlignment = Alignment.CenterStart,
+ ) {
Text(
- text = "Organize tokens", // TODO: Move to resources
+ text = stringResource(id = R.string.organize_tokens_title),
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
maxLines = 1,
)
- },
- colors = TopAppBarDefaults.topAppBarColors(
- containerColor = TangemTheme.colors.background.secondary,
- titleContentColor = TangemTheme.colors.text.primary1,
- ),
- )
+ }
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .heightIn(min = TangemTheme.dimens.size56),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
+ ) {
+ BackgroundActionButton(
+ modifier = Modifier.weight(1f),
+ text = stringResource(id = R.string.organize_tokens_sort_by_balance),
+ iconResId = R.drawable.ic_sort_24,
+ onClick = config.onSortByBalanceClick,
+ )
+ BackgroundActionButton(
+ modifier = Modifier.weight(1f),
+ text = stringResource(id = R.string.organize_tokens_group),
+ iconResId = R.drawable.ic_group_24,
+ onClick = config.onGroupByNetworkClick,
+ )
+ }
+ }
}
@Composable
private fun Actions(config: OrganizeTokensStateHolder.ActionsConfig, modifier: Modifier = Modifier) {
- // TODO: Implement list apply and cancel actions
+ Row(
+ modifier = modifier
+ .padding(horizontal = TangemTheme.dimens.spacing16)
+ .fillMaxWidth(),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
+ ) {
+ SecondaryButton(
+ modifier = Modifier.weight(1f),
+ text = stringResource(id = R.string.common_cancel),
+ onClick = config.onCancelClick,
+ )
+ PrimaryButton(
+ modifier = Modifier.weight(1f),
+ text = stringResource(id = R.string.common_apply),
+ onClick = config.onApplyClick,
+ )
+ }
+}
+
+private fun Modifier.clipFirstAndLastItems(index: Int, lastItemIndex: Int): Modifier = composed {
+ when (index) {
+ 0 -> {
+ this
+ .clip(
+ RoundedCornerShape(
+ topStart = TangemTheme.dimens.radius16,
+ topEnd = TangemTheme.dimens.radius16,
+ ),
+ )
+ }
+ lastItemIndex -> {
+ this
+ .clip(
+ RoundedCornerShape(
+ bottomStart = TangemTheme.dimens.radius16,
+ bottomEnd = TangemTheme.dimens.radius16,
+ ),
+ )
+ }
+ else -> this
+ }
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Composable
-private fun OrganizeTokensScreenPreview_Light() {
+private fun OrganizeTokensScreenPreview_Light(
+ @PreviewParameter(OrganizeTokensStateProvider::class) state: OrganizeTokensStateHolder,
+) {
TangemTheme {
- OrganizeTokensScreen(state = WalletPreviewData.organizeTokensState)
+ OrganizeTokensScreen(state)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
-private fun OrganizeTokensScreenPreview_Dark() {
+private fun OrganizeTokensScreenPreview_Dark(
+ @PreviewParameter(OrganizeTokensStateProvider::class) state: OrganizeTokensStateHolder,
+) {
TangemTheme(isDark = true) {
- OrganizeTokensScreen(state = WalletPreviewData.organizeTokensState)
+ OrganizeTokensScreen(state)
}
}
+
+private class OrganizeTokensStateProvider : CollectionPreviewParameterProvider(
+ collection = listOf(
+ WalletPreviewData.organizeTokensState,
+ WalletPreviewData.groupedOrganizeTokensState,
+ ),
+)
// endregion Preview
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt
index b9a8e797cb..0e0a07d2e6 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt
@@ -1,10 +1,13 @@
package com.tangem.feature.wallet.presentation.organizetokens
-import com.tangem.feature.wallet.presentation.common.state.TokenListState
+import androidx.compose.runtime.Immutable
+import com.tangem.feature.wallet.presentation.common.state.TokenItemState
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.toPersistentList
internal data class OrganizeTokensStateHolder(
- val tokens: TokenListState,
val header: HeaderConfig,
+ val itemsState: OrganizeTokensListState,
val actions: ActionsConfig,
) {
@@ -17,4 +20,44 @@ internal data class OrganizeTokensStateHolder(
val onApplyClick: () -> Unit,
val onCancelClick: () -> Unit,
)
+}
+
+@Immutable
+internal sealed class OrganizeTokensListState {
+ abstract val items: ImmutableList
+
+ data class GroupedByNetwork(
+ override val items: ImmutableList,
+ ) : OrganizeTokensListState()
+
+ data class Ungrouped(
+ override val items: ImmutableList,
+ ) : OrganizeTokensListState()
+
+ @Suppress("UNCHECKED_CAST")
+ inline fun updateItems(update: (List) -> List): OrganizeTokensListState {
+ val updatedItems = update(this.items).toPersistentList()
+
+ return when (this) {
+ is GroupedByNetwork -> this.copy(items = updatedItems)
+ is Ungrouped -> this.copy(items = updatedItems as ImmutableList)
+ }
+ }
+}
+
+@Immutable
+internal sealed interface DraggableItem {
+ val id: String
+
+ data class GroupHeader(
+ override val id: String,
+ val networkName: String,
+ ) : DraggableItem
+
+ data class Token(
+ val tokenItemState: TokenItemState.Draggable,
+ val groupId: String,
+ ) : DraggableItem {
+ override val id: String = tokenItemState.id
+ }
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensViewModel.kt
index 16f726eab1..cbdd25e47e 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensViewModel.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensViewModel.kt
@@ -5,11 +5,14 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
+import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder.HeaderConfig
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.collections.immutable.toPersistentList
import javax.inject.Inject
import kotlin.properties.Delegates
+// FIXME: Implemented with preview data
@HiltViewModel
internal class OrganizeTokensViewModel @Inject constructor() : ViewModel() {
@@ -18,5 +21,26 @@ internal class OrganizeTokensViewModel @Inject constructor() : ViewModel() {
var uiState: OrganizeTokensStateHolder by mutableStateOf(getInitialState())
private set
- private fun getInitialState(): OrganizeTokensStateHolder = WalletPreviewData.organizeTokensState
+ private fun getInitialState(): OrganizeTokensStateHolder = WalletPreviewData.organizeTokensState.copy(
+ itemsState = OrganizeTokensListState.Ungrouped(
+ items = WalletPreviewData.draggableTokens,
+ ),
+ header = HeaderConfig(
+ onSortByBalanceClick = { /* no-op */ },
+ onGroupByNetworkClick = this::toggleTokensByNetworkGrouping,
+ ),
+ )
+
+ private fun toggleTokensByNetworkGrouping() {
+ val newListState = when (val itemsState = uiState.itemsState) {
+ is OrganizeTokensListState.GroupedByNetwork -> OrganizeTokensListState.Ungrouped(
+ items = itemsState.items.filterIsInstance().toPersistentList(),
+ )
+ is OrganizeTokensListState.Ungrouped -> OrganizeTokensListState.GroupedByNetwork(
+ items = WalletPreviewData.draggableItems,
+ )
+ }
+
+ uiState = uiState.copy(itemsState = newListState)
+ }
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
index b963f8f7b7..2976a7b8db 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
@@ -10,7 +10,6 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
-import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.presentation.WalletFragment
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensScreen
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensViewModel
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletCardState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletCardState.kt
index 7685a267da..2f000581e2 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletCardState.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletCardState.kt
@@ -1,9 +1,12 @@
package com.tangem.feature.wallet.presentation.wallet.state
import androidx.annotation.DrawableRes
+import androidx.compose.runtime.Immutable
/** Wallet card state */
+@Immutable
internal sealed interface WalletCardState {
+
/** Id */
val id: String
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletContentItemState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletContentItemState.kt
new file mode 100644
index 0000000000..66a426f04a
--- /dev/null
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletContentItemState.kt
@@ -0,0 +1,13 @@
+package com.tangem.feature.wallet.presentation.wallet.state
+
+import com.tangem.feature.wallet.presentation.common.state.TokenItemState
+
+/**
+[REDACTED_AUTHOR]
+ */
+internal sealed interface WalletContentItemState {
+
+ data class NetworkGroupTitle(val networkName: String) : WalletContentItemState
+
+ data class Token(val tokenItemState: TokenItemState) : WalletContentItemState
+}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletStateHolder.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletStateHolder.kt
index 8142667ad3..061647e21b 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletStateHolder.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletStateHolder.kt
@@ -5,26 +5,28 @@ import kotlinx.collections.immutable.ImmutableList
/**
* Wallet state holder
*
- * @property onBackClick lambda be invoked when back button is clicked
- * @property headerConfig header config
+ * @property onBackClick lambda be invoked when back button is clicked
+ * @property topBarConfig top bar config
+ * @property selectedWallet selected wallet
+ * @property wallets list of wallets states
+ * @property contentItems content items
*
[REDACTED_AUTHOR]
*/
internal data class WalletStateHolder(
val onBackClick: () -> Unit,
- val headerConfig: HeaderConfig,
+ val topBarConfig: TopBarConfig,
+ val selectedWallet: WalletCardState,
+ val wallets: ImmutableList,
+ val contentItems: ImmutableList,
+ val onOrganizeTokensClick: () -> Unit,
) {
/**
- * Header config
+ * Top bar config
*
- * @property wallets list of wallets states
* @property onScanCardClick lambda be invoked when scan card button is clicked
* @property onMoreClick lambda be invoked when more button is clicked
*/
- data class HeaderConfig(
- val wallets: ImmutableList,
- val onScanCardClick: () -> Unit,
- val onMoreClick: () -> Unit,
- )
+ data class TopBarConfig(val onScanCardClick: () -> Unit, val onMoreClick: () -> Unit)
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt
index 098d1e1e45..963c6b4a1a 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt
@@ -1,11 +1,32 @@
package com.tangem.feature.wallet.presentation.wallet.ui
import androidx.activity.compose.BackHandler
-import androidx.compose.material.Scaffold
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.itemsIndexed
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.res.stringResource
+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.components.RoundedActionButton
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.feature.wallet.impl.R
+import com.tangem.feature.wallet.presentation.common.WalletPreviewData
+import com.tangem.feature.wallet.presentation.common.component.NetworkGroupItem
+import com.tangem.feature.wallet.presentation.common.component.TokenItem
+import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
-import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletHeader
+import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletCardsList
+import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletTopBar
/**
* Wallet screen
@@ -19,9 +40,109 @@ internal fun WalletScreen(state: WalletStateHolder, modifier: Modifier = Modifie
BackHandler(onBack = state.onBackClick)
Scaffold(
- modifier = modifier,
- topBar = { WalletHeader(config = state.headerConfig) },
- ) {
- // TODO: [REDACTED_TASK_KEY] Design a body with tokens and transactions
+ topBar = { WalletTopBar(config = state.topBarConfig) },
+ containerColor = TangemTheme.colors.background.secondary,
+ ) { scaffoldPaddings ->
+ val lastContentItemIndex = remember(state.contentItems) {
+ state.contentItems.lastIndex
+ }
+
+ LazyColumn(
+ modifier = Modifier
+ .padding(scaffoldPaddings)
+ .fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ item { WalletCardsList(wallets = state.wallets) }
+
+ itemsIndexed(
+ items = state.contentItems,
+ key = { _, item ->
+ when (item) {
+ is WalletContentItemState.NetworkGroupTitle -> item.networkName
+ is WalletContentItemState.Token -> item.tokenItemState.id
+ }
+ },
+ ) { index, item ->
+ val itemModifier = Modifier
+ .padding(horizontal = TangemTheme.dimens.spacing16)
+ .clipFirstAndLastItems(index, lastContentItemIndex)
+
+ when (item) {
+ is WalletContentItemState.NetworkGroupTitle -> {
+ NetworkGroupItem(
+ networkName = item.networkName,
+ modifier = itemModifier,
+ )
+ }
+ is WalletContentItemState.Token -> {
+ TokenItem(
+ state = item.tokenItemState,
+ modifier = itemModifier,
+ )
+ }
+ }
+ }
+
+ item {
+ RoundedActionButton(
+ text = stringResource(id = R.string.organize_tokens_title),
+ iconResId = R.drawable.ic_filter_24,
+ onClick = state.onOrganizeTokensClick,
+ modifier = Modifier.padding(top = TangemTheme.dimens.spacing14),
+ )
+ }
+ }
}
-}
\ No newline at end of file
+}
+
+private fun Modifier.clipFirstAndLastItems(index: Int, lastItemIndex: Int): Modifier = composed {
+ when (index) {
+ 0 -> {
+ this
+ .padding(top = TangemTheme.dimens.spacing14)
+ .clip(
+ RoundedCornerShape(
+ topStart = TangemTheme.dimens.radius16,
+ topEnd = TangemTheme.dimens.radius16,
+ ),
+ )
+ }
+ lastItemIndex -> {
+ this
+ .clip(
+ RoundedCornerShape(
+ bottomStart = TangemTheme.dimens.radius16,
+ bottomEnd = TangemTheme.dimens.radius16,
+ ),
+ )
+ }
+ else -> this
+ }
+}
+
+// region Preview
+@Preview(showBackground = true, widthDp = 360)
+@Composable
+private fun WalletScreenPreview_Light(
+ @PreviewParameter(WalletScreenParameterProvider::class) state: WalletStateHolder,
+) {
+ TangemTheme {
+ WalletScreen(state)
+ }
+}
+
+@Preview(showBackground = true, widthDp = 360)
+@Composable
+private fun WalletScreenPreview_Dark(
+ @PreviewParameter(WalletScreenParameterProvider::class) state: WalletStateHolder,
+) {
+ TangemTheme(isDark = true) {
+ WalletScreen(state)
+ }
+}
+
+private class WalletScreenParameterProvider : CollectionPreviewParameterProvider(
+ collection = listOf(WalletPreviewData.groupedWalletScreenState),
+)
+// endregion Preview
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletCard.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletCard.kt
index 562c954023..d92651ac6f 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletCard.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletCard.kt
@@ -44,7 +44,7 @@ internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
ConstraintLayout(
modifier = Modifier
.fillMaxWidth()
- .padding(horizontal = TangemTheme.dimens.spacing12),
+ .padding(horizontal = TangemTheme.dimens.spacing14),
) {
val (balanceBlock, imageItem) = createRefs()
Column(
@@ -182,10 +182,10 @@ private fun Preview_WalletCard_DarkTheme(@PreviewParameter(WalletCardStateProvid
private class WalletCardStateProvider : CollectionPreviewParameterProvider(
collection = listOf(
- WalletPreviewData.walletCardContent,
- WalletPreviewData.walletCardLoading,
- WalletPreviewData.walletCardHiddenContent,
- WalletPreviewData.walletCardError,
+ WalletPreviewData.walletCardContentState,
+ WalletPreviewData.walletCardLoadingState,
+ WalletPreviewData.walletCardHiddenContentState,
+ WalletPreviewData.walletCardErrorState,
),
)
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletCardsList.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletCardsList.kt
new file mode 100644
index 0000000000..d37d359252
--- /dev/null
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletCardsList.kt
@@ -0,0 +1,78 @@
+package com.tangem.feature.wallet.presentation.wallet.ui.components
+
+import androidx.compose.animation.core.*
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.material3.*
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.feature.wallet.presentation.common.WalletPreviewData
+import com.tangem.feature.wallet.presentation.wallet.state.WalletCardState
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.persistentListOf
+
+/**
+ * Wallets list
+ *
+ * @param wallets list of wallet state
+ *
+[REDACTED_AUTHOR]
+ */
+@OptIn(ExperimentalFoundationApi::class)
+@Composable
+internal fun WalletCardsList(wallets: ImmutableList) {
+ val horizontalCardPadding = TangemTheme.dimens.spacing16
+ val itemWidth = LocalConfiguration.current.screenWidthDp.dp - horizontalCardPadding * 2
+
+ val lazyListState = rememberLazyListState()
+ LazyRow(
+ modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
+ state = lazyListState,
+ contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
+ horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
+ flingBehavior = rememberSnapFlingBehavior(lazyListState = lazyListState),
+ ) {
+ items(items = wallets, key = WalletCardState::id) { state ->
+ WalletCard(state = state, modifier = Modifier.width(itemWidth))
+ }
+ }
+}
+
+@Preview
+@Composable
+private fun Preview_WalletHeader_LightTheme() {
+ TangemTheme(isDark = false) {
+ WalletCardsList(
+ wallets = persistentListOf(
+ WalletPreviewData.walletCardContentState,
+ WalletPreviewData.walletCardLoadingState,
+ WalletPreviewData.walletCardHiddenContentState,
+ WalletPreviewData.walletCardErrorState,
+ ),
+ )
+ }
+}
+
+@Preview
+@Composable
+private fun Preview_WalletHeader_DarkTheme() {
+ TangemTheme(isDark = true) {
+ WalletCardsList(
+ wallets = persistentListOf(
+ WalletPreviewData.walletCardContentState,
+ WalletPreviewData.walletCardLoadingState,
+ WalletPreviewData.walletCardHiddenContentState,
+ WalletPreviewData.walletCardErrorState,
+ ),
+ )
+ }
+}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletHeader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletHeader.kt
deleted file mode 100644
index cb01b48377..0000000000
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletHeader.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-package com.tangem.feature.wallet.presentation.wallet.ui.components
-
-import androidx.compose.animation.core.*
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.LocalOverscrollConfiguration
-import androidx.compose.foundation.background
-import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
-import androidx.compose.foundation.layout.*
-import androidx.compose.foundation.lazy.LazyRow
-import androidx.compose.foundation.lazy.items
-import androidx.compose.foundation.lazy.rememberLazyListState
-import androidx.compose.material3.*
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalConfiguration
-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 androidx.compose.ui.unit.dp
-import com.tangem.core.ui.res.TangemTheme
-import com.tangem.feature.wallet.impl.R
-import com.tangem.feature.wallet.presentation.common.WalletPreviewData
-import com.tangem.feature.wallet.presentation.wallet.state.WalletCardState
-import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
-import kotlinx.collections.immutable.persistentListOf
-
-/**
- * Wallet screen header
- *
- * @param config config
- *
-[REDACTED_AUTHOR]
- */
-@OptIn(ExperimentalFoundationApi::class)
-@Composable
-internal fun WalletHeader(config: WalletStateHolder.HeaderConfig) {
- Column(
- modifier = Modifier
- .background(color = TangemTheme.colors.background.secondary)
- .padding(bottom = TangemTheme.dimens.spacing14),
- ) {
- TopBar(onScanCardClick = config.onScanCardClick, onMoreClick = config.onMoreClick)
-
- CompositionLocalProvider(LocalOverscrollConfiguration provides null) {
- val lazyListState = rememberLazyListState()
- LazyRow(
- state = lazyListState,
- contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
- horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
- flingBehavior = rememberSnapFlingBehavior(lazyListState = lazyListState),
- ) {
- items(items = config.wallets, key = WalletCardState::id) { state ->
- WalletCard(
- state = state,
- modifier = Modifier.width(
- LocalConfiguration.current.screenWidthDp.dp - TangemTheme.dimens.size32,
- ),
- )
- }
- }
- }
- }
-}
-
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-private fun TopBar(onScanCardClick: () -> Unit, onMoreClick: () -> Unit) {
- TopAppBar(
- title = {
- Icon(painter = painterResource(id = R.drawable.img_tangem_logo_90_24), contentDescription = null)
- },
- actions = {
- IconButton(onClick = onScanCardClick) {
- Icon(painter = painterResource(id = R.drawable.ic_tap_card_24), contentDescription = "Scan card")
- }
- IconButton(onClick = onMoreClick) {
- Icon(painter = painterResource(id = R.drawable.ic_more_vertical_24), contentDescription = "More")
- }
- },
- colors = TopAppBarDefaults.topAppBarColors(
- containerColor = TangemTheme.colors.background.secondary,
- titleContentColor = TangemTheme.colors.icon.primary1,
- actionIconContentColor = TangemTheme.colors.icon.primary1,
- ),
- )
-}
-
-@Preview
-@Composable
-private fun Preview_WalletHeader_LightTheme(
- @PreviewParameter(WalletHeaderProvider::class) state: WalletStateHolder.HeaderConfig,
-) {
- TangemTheme(isDark = false) {
- WalletHeader(state)
- }
-}
-
-@Preview
-@Composable
-private fun Preview_WalletHeader_DarkTheme(
- @PreviewParameter(WalletHeaderProvider::class) state: WalletStateHolder.HeaderConfig,
-) {
- TangemTheme(isDark = true) {
- WalletHeader(state)
- }
-}
-
-private class WalletHeaderProvider : CollectionPreviewParameterProvider(
- collection = listOf(
- WalletStateHolder.HeaderConfig(
- wallets = persistentListOf(
- WalletPreviewData.walletCardContent,
- WalletPreviewData.walletCardLoading,
- WalletPreviewData.walletCardHiddenContent,
- WalletPreviewData.walletCardError,
- ),
- onScanCardClick = {},
- onMoreClick = {},
- ),
- ),
-)
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletTopBar.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletTopBar.kt
new file mode 100644
index 0000000000..29b91f97bd
--- /dev/null
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletTopBar.kt
@@ -0,0 +1,55 @@
+package com.tangem.feature.wallet.presentation.wallet.ui.components
+
+import androidx.compose.material3.*
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.tooling.preview.Preview
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.feature.wallet.impl.R
+import com.tangem.feature.wallet.presentation.common.WalletPreviewData
+import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
+
+/**
+ * Wallet screen top bar
+ *
+ * @param config top bar config
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+internal fun WalletTopBar(config: WalletStateHolder.TopBarConfig) {
+ TopAppBar(
+ title = {
+ Icon(painter = painterResource(id = R.drawable.img_tangem_logo_90_24), contentDescription = null)
+ },
+ actions = {
+ IconButton(onClick = config.onScanCardClick) {
+ Icon(painter = painterResource(id = R.drawable.ic_tap_card_24), contentDescription = "Scan card")
+ }
+ IconButton(onClick = config.onMoreClick) {
+ Icon(painter = painterResource(id = R.drawable.ic_more_vertical_24), contentDescription = "More")
+ }
+ },
+ colors = TopAppBarDefaults.topAppBarColors(
+ containerColor = TangemTheme.colors.background.secondary,
+ titleContentColor = TangemTheme.colors.icon.primary1,
+ actionIconContentColor = TangemTheme.colors.icon.primary1,
+ ),
+ scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
+ )
+}
+
+@Preview
+@Composable
+private fun Preview_WalletTopBar_LightTheme() {
+ TangemTheme(isDark = false) {
+ WalletTopBar(config = WalletPreviewData.walletTopBarConfig)
+ }
+}
+
+@Preview
+@Composable
+private fun Preview_WalletTopBar_DarkTheme() {
+ TangemTheme(isDark = true) {
+ WalletTopBar(config = WalletPreviewData.walletTopBarConfig)
+ }
+}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt
index a565bb8c91..9cb70bd530 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt
@@ -27,9 +27,9 @@ internal class WalletViewModel @Inject constructor() : ViewModel() {
private set
// TODO: [REDACTED_TASK_KEY] Use production data instead of WalletPreviewData
- private fun getInitialState(): WalletStateHolder = WalletPreviewData.walletScreenState.copy(
+ private fun getInitialState(): WalletStateHolder = WalletPreviewData.groupedWalletScreenState.copy(
onBackClick = { router.popBackStack() },
- headerConfig = WalletPreviewData.walletScreenState.headerConfig.copy(
+ topBarConfig = WalletPreviewData.groupedWalletScreenState.topBarConfig.copy(
onScanCardClick = { router.openOrganizeTokensScreen() },
),
)
diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml
index 8d89456b8c..269eb8f262 100644
--- a/gradle/dependencies.toml
+++ b/gradle/dependencies.toml
@@ -77,9 +77,9 @@ walletConnectWeb3 = "1.8.0"
# endregion Other libraries
# region Tangem
-tangemBlockchainSdk = "release-app_4.7-245"
+tangemBlockchainSdk = "develop-247"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
-tangemCardSdk = "release-app_4.7-268"
+tangemCardSdk = "develop-266"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds
# endregion Tangem