diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 7ad7dd2099..8c1d366c83 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -84,6 +84,7 @@
Копировать
Скопировать адрес
Создать
+ Свое
Удалить
Отключено
Готово
@@ -95,7 +96,6 @@
Обозреватель
Комиссия
Сетевые комиссии – это плата пользователя за обработку и подтверждение транзакций. Размер комиссии зависит от нагрузки на сеть, объема транзакции и приоритета исполнения. %s
- Свое
Быстро
По рынку
Медленно
@@ -302,6 +302,7 @@
- %1$d из %2$d кошельков
- %1$d из %2$d кошельков
+ Удалить
например Bitcoin
Ваш портфель был обновлен
Выбранный токен не доступен в кошельке на данный момент. Но не переживайте, вы можете выразить свой интерес проголосовав за его добавление.
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 752c42de5a..38c7f41345 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -67,6 +67,7 @@
Not enough ADA
Accept
Access denied
+ All
Allow
Apply
Approval
@@ -84,6 +85,7 @@
Copy
Copy address
Create
+ Custom
Delete
Disabled
Done
@@ -95,7 +97,6 @@
Explorer
Fee
Network fees are charges users pay to process and confirm transactions. The fee amount can be affected by network congestion, transaction size, and execution priority. %s
- Custom
Fast
Market
Slow
@@ -304,6 +305,7 @@
- %1$d of %2$d wallet
- %1$d of %2$d wallets
+ Remove
e.g. BTC I trust, hodl I must
Your portfolio has been updated
The selected token is currently unavailable for actions within the crypto wallet. But worry not, you can express your interest by upvoting it.
@@ -562,9 +564,11 @@
On stake
Reward claiming
Reward schedule
+ Rewards to claim: %s
Staking %s
Unbonding Period
Warmup period
+ Native staking
Staking allow you to earn %1s. Your staking rewards arrive every ~%2s days.
Earn staking rewards
Rewards
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/buttons/segmentedbutton/SegmentedButton.kt b/core/ui/src/main/java/com/tangem/core/ui/components/buttons/segmentedbutton/SegmentedButton.kt
index 0bfeb822a6..1101935641 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/buttons/segmentedbutton/SegmentedButton.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/buttons/segmentedbutton/SegmentedButton.kt
@@ -8,10 +8,7 @@ import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.*
@@ -21,8 +18,9 @@ import androidx.compose.ui.graphics.Color
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.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.res.TangemThemePreview
+import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
@@ -42,7 +40,7 @@ import kotlinx.collections.immutable.persistentListOf
*/
@Composable
inline fun SegmentedButtons(
- config: PersistentList,
+ config: ImmutableList,
crossinline onClick: (T) -> Unit,
modifier: Modifier = Modifier,
color: Color = TangemTheme.colors.background.tertiary,
@@ -51,7 +49,7 @@ inline fun SegmentedButtons(
showIndication: Boolean = true,
initialSelectedItem: T? = null,
isEnabled: Boolean = true,
- crossinline buttonContent: @Composable (T) -> Unit,
+ crossinline buttonContent: @Composable BoxScope.(T) -> Unit,
) {
if (config.isEmpty() || config.size == 1) return
@@ -97,7 +95,7 @@ inline fun SegmentedButtons(
onClick(config[index])
},
) {
- buttonContent.invoke(config[index])
+ buttonContent.invoke(this, config[index])
}
}
}
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/rows/SelectorRowItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/rows/SelectorRowItem.kt
index c1e06e7270..5eb6b5f287 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/rows/SelectorRowItem.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/rows/SelectorRowItem.kt
@@ -25,6 +25,7 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
+import com.tangem.utils.Strings
@Composable
fun SelectorRowItem(
@@ -127,7 +128,7 @@ private fun RowScope.SelectorValueContent(
)
if (postDot != null) {
Text(
- text = "•",
+ text = Strings.DOT,
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.primary1,
textAlign = TextAlign.Center,
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 cc51084e66..2ad32a8f6f 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
@@ -102,9 +102,11 @@ data class TangemDimens internal constructor(
val spacing2: Dp = 2.dp,
val spacing3: Dp = 3.dp,
val spacing4: Dp = 4.dp,
+ val spacing5: Dp = 5.dp,
val spacing6: Dp = 6.dp,
val spacing8: Dp = 8.dp,
val spacing10: Dp = 10.dp,
+ val spacing11: Dp = 11.dp,
val spacing12: Dp = 12.dp,
val spacing14: Dp = 14.dp,
val spacing15: Dp = 15.dp,
diff --git a/core/utils/src/main/java/com/tangem/utils/Strings.kt b/core/utils/src/main/java/com/tangem/utils/Strings.kt
index 59adbdab5b..f6cc72a41a 100644
--- a/core/utils/src/main/java/com/tangem/utils/Strings.kt
+++ b/core/utils/src/main/java/com/tangem/utils/Strings.kt
@@ -3,4 +3,5 @@ package com.tangem.utils
object Strings {
const val STARS = "\u2217\u2217\u2217"
+ const val DOT = "•"
}
\ No newline at end of file
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt
index f403cf423b..096fbe1d8b 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt
@@ -63,7 +63,7 @@ internal fun SendSpeedSelector(
onSelect = { clickIntents.onFeeSelectorClick(FeeType.Fast) },
)
SendSpeedSelectorItem(
- titleRes = R.string.common_fee_selector_option_custom,
+ titleRes = R.string.common_custom,
iconRes = R.drawable.ic_edit_24,
feeType = FeeType.Custom,
state = state,
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/FeeBlock.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/FeeBlock.kt
index 6873ed2b63..11c4f4ebab 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/FeeBlock.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/FeeBlock.kt
@@ -53,7 +53,7 @@ internal fun FeeBlock(feeState: SendStates.FeeState, isClickDisabled: Boolean, o
FeeType.Slow -> R.string.common_fee_selector_option_slow to R.drawable.ic_tortoise_24
FeeType.Market -> R.string.common_fee_selector_option_market to R.drawable.ic_bird_24
FeeType.Fast -> R.string.common_fee_selector_option_fast to R.drawable.ic_hare_24
- FeeType.Custom -> R.string.common_fee_selector_option_custom to R.drawable.ic_edit_24
+ FeeType.Custom -> R.string.common_custom to R.drawable.ic_edit_24
}
} else {
R.string.common_fee_selector_option_market to R.drawable.ic_bird_24
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/TokenDetailsPreviewData.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/TokenDetailsPreviewData.kt
index f99dbb1cd3..79b16936c9 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/TokenDetailsPreviewData.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/TokenDetailsPreviewData.kt
@@ -9,7 +9,9 @@ import com.tangem.core.ui.components.transactions.state.TransactionState
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.core.ui.event.consumedEvent
import com.tangem.core.ui.extensions.TextReference
+import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
+import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton
@@ -18,6 +20,7 @@ import com.tangem.features.tokendetails.impl.R
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
+@Suppress("LargeClass")
internal object TokenDetailsPreviewData {
val tokenDetailsTopAppBarConfig = TokenDetailsTopAppBarConfig(
@@ -100,17 +103,47 @@ internal object TokenDetailsPreviewData {
TokenDetailsActionButton.Swap(dimContent = false, onClick = {}),
)
- val balanceLoading = TokenDetailsBalanceBlockState.Loading(actionButtons = actionButtons)
+ private val balanceSegmentedButtonConfig = persistentListOf(
+ TokenBalanceSegmentedButtonConfig(
+ title = resourceReference(R.string.common_all),
+ type = BalanceType.ALL,
+ ),
+ TokenBalanceSegmentedButtonConfig(
+ title = resourceReference(R.string.staking_details_available),
+ type = BalanceType.AVAILABLE,
+ ),
+ )
+
+ val balanceLoading = TokenDetailsBalanceBlockState.Loading(
+ actionButtons = actionButtons,
+ balanceSegmentedButtonConfig = balanceSegmentedButtonConfig,
+ selectedBalanceType = BalanceType.ALL,
+ )
val balanceContent = TokenDetailsBalanceBlockState.Content(
actionButtons = actionButtons,
fiatBalance = "91,50$",
cryptoBalance = "966,96 XLM",
+ isStakingEnabled = true,
+ balanceSegmentedButtonConfig = balanceSegmentedButtonConfig,
+ selectedBalanceType = BalanceType.ALL,
+ onBalanceSelect = {},
+ )
+ val balanceError = TokenDetailsBalanceBlockState.Error(
+ actionButtons = actionButtons,
+ balanceSegmentedButtonConfig = balanceSegmentedButtonConfig,
+ selectedBalanceType = BalanceType.ALL,
)
- val balanceError = TokenDetailsBalanceBlockState.Error(actionButtons = actionButtons)
private val marketPriceLoading = MarketPriceBlockState.Loading(currencySymbol = "USDT")
- private val stakingLoading = StakingBlockState.Loading(iconState = iconState)
+ private val stakingLoading = StakingBlocksState(
+ stakingAvailable = StakingAvailable.Loading(iconState),
+ stakingBalance = StakingBalance.Content(
+ cryptoAmount = stringReference("5 SOL"),
+ fiatAmount = stringReference("456.34 $"),
+ rewardAmount = resourceReference(R.string.staking_details_no_rewards_to_claim, wrappedList("0.43 $")),
+ ),
+ )
private val pullToRefreshConfig = TokenDetailsPullToRefreshConfig(
isRefreshing = false,
@@ -246,7 +279,7 @@ internal object TokenDetailsPreviewData {
tokenInfoBlockState = tokenInfoBlockState,
tokenBalanceBlockState = balanceLoading,
marketPriceBlockState = marketPriceLoading,
- stakingBlockState = stakingLoading,
+ stakingBlocksState = stakingLoading,
notifications = persistentListOf(),
txHistoryState = TxHistoryState.Content(
contentItems = MutableStateFlow(
@@ -278,12 +311,19 @@ internal object TokenDetailsPreviewData {
type = PriceChangeType.UP,
),
),
- stakingBlockState = StakingBlockState.Content(
- interestRate = "7.38",
- periodInDays = 4,
- tokenSymbol = "XLM",
- iconState = iconState,
- onStakeClicked = {},
+ stakingBlocksState = StakingBlocksState(
+ stakingAvailable = StakingAvailable.Content(
+ interestRate = "7.38",
+ periodInDays = 4,
+ tokenSymbol = "XLM",
+ iconState = iconState,
+ onStakeClicked = {},
+ ),
+ stakingBalance = StakingBalance.Content(
+ cryptoAmount = stringReference("5 SOL"),
+ fiatAmount = stringReference("456.34 $"),
+ rewardAmount = resourceReference(R.string.staking_details_rewards_to_claim, wrappedList("0.43 $")),
+ ),
),
notifications = persistentListOf(),
txHistoryState = TxHistoryState.NotSupported(
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockState.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockState.kt
index 76d9483c9b..6b5802a796 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockState.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockState.kt
@@ -1,15 +1,20 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.state
import androidx.compose.runtime.Immutable
+import com.tangem.core.ui.extensions.TextReference
+
+internal data class StakingBlocksState(
+ val stakingAvailable: StakingAvailable,
+ val stakingBalance: StakingBalance,
+)
@Immutable
-internal sealed interface StakingBlockState {
-
+internal sealed interface StakingAvailable {
val iconState: IconState
- data class Error(override val iconState: IconState) : StakingBlockState
+ data class Error(override val iconState: IconState) : StakingAvailable
- data class Loading(override val iconState: IconState) : StakingBlockState
+ data class Loading(override val iconState: IconState) : StakingAvailable
data class Content(
override val iconState: IconState,
@@ -17,5 +22,16 @@ internal sealed interface StakingBlockState {
val periodInDays: Int,
val tokenSymbol: String,
val onStakeClicked: () -> Unit,
- ) : StakingBlockState
+ ) : StakingAvailable
+}
+
+@Immutable
+sealed class StakingBalance {
+ data object Empty : StakingBalance()
+
+ data class Content(
+ val cryptoAmount: TextReference,
+ val fiatAmount: TextReference,
+ val rewardAmount: TextReference,
+ ) : StakingBalance()
}
\ No newline at end of file
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenBalanceSegmentedButtonConfig.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenBalanceSegmentedButtonConfig.kt
new file mode 100644
index 0000000000..d741d3e609
--- /dev/null
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenBalanceSegmentedButtonConfig.kt
@@ -0,0 +1,13 @@
+package com.tangem.feature.tokendetails.presentation.tokendetails.state
+
+import com.tangem.core.ui.extensions.TextReference
+
+data class TokenBalanceSegmentedButtonConfig(
+ val title: TextReference,
+ val type: BalanceType,
+)
+
+enum class BalanceType {
+ ALL,
+ AVAILABLE,
+}
\ No newline at end of file
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsBalanceBlockState.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsBalanceBlockState.kt
index 2f066dae01..21ee681241 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsBalanceBlockState.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsBalanceBlockState.kt
@@ -6,19 +6,29 @@ import kotlinx.collections.immutable.ImmutableList
internal sealed class TokenDetailsBalanceBlockState {
abstract val actionButtons: ImmutableList
+ abstract val balanceSegmentedButtonConfig: ImmutableList
+ abstract val selectedBalanceType: BalanceType
data class Loading(
override val actionButtons: ImmutableList,
+ override val balanceSegmentedButtonConfig: ImmutableList,
+ override val selectedBalanceType: BalanceType,
) : TokenDetailsBalanceBlockState()
data class Content(
override val actionButtons: ImmutableList,
+ override val balanceSegmentedButtonConfig: ImmutableList,
+ override val selectedBalanceType: BalanceType,
val fiatBalance: String,
val cryptoBalance: String,
+ val isStakingEnabled: Boolean,
+ val onBalanceSelect: (TokenBalanceSegmentedButtonConfig) -> Unit,
) : TokenDetailsBalanceBlockState()
data class Error(
override val actionButtons: ImmutableList,
+ override val balanceSegmentedButtonConfig: ImmutableList,
+ override val selectedBalanceType: BalanceType,
) : TokenDetailsBalanceBlockState()
fun copyActionButtons(buttons: ImmutableList): TokenDetailsBalanceBlockState {
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsState.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsState.kt
index d1ec291d51..b9594669da 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsState.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsState.kt
@@ -17,7 +17,7 @@ internal data class TokenDetailsState(
val tokenInfoBlockState: TokenInfoBlockState,
val tokenBalanceBlockState: TokenDetailsBalanceBlockState,
val marketPriceBlockState: MarketPriceBlockState,
- val stakingBlockState: StakingBlockState,
+ val stakingBlocksState: StakingBlocksState,
val notifications: ImmutableList,
val pendingTxs: PersistentList,
val swapTxs: PersistentList,
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt
index 63d735d3ad..87e2d83683 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt
@@ -10,6 +10,7 @@ import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.BalanceType
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification
@@ -23,6 +24,7 @@ import kotlinx.collections.immutable.toPersistentList
internal class TokenDetailsLoadedBalanceConverter(
private val currentStateProvider: Provider,
private val appCurrencyProvider: Provider,
+ private val isStakingEnabled: Boolean,
private val symbol: String,
private val decimals: Int,
private val clickIntents: TokenDetailsClickIntents,
@@ -39,7 +41,11 @@ internal class TokenDetailsLoadedBalanceConverter(
private fun convertError(): TokenDetailsState {
val state = currentStateProvider()
return state.copy(
- tokenBalanceBlockState = TokenDetailsBalanceBlockState.Error(state.tokenBalanceBlockState.actionButtons),
+ tokenBalanceBlockState = TokenDetailsBalanceBlockState.Error(
+ actionButtons = state.tokenBalanceBlockState.actionButtons,
+ balanceSegmentedButtonConfig = state.tokenBalanceBlockState.balanceSegmentedButtonConfig,
+ selectedBalanceType = state.tokenBalanceBlockState.selectedBalanceType,
+ ),
marketPriceBlockState = MarketPriceBlockState.Error(state.marketPriceBlockState.currencySymbol),
notifications = persistentListOf(TokenDetailsNotification.NetworksUnreachable),
)
@@ -74,12 +80,24 @@ internal class TokenDetailsLoadedBalanceConverter(
actionButtons = currentState.actionButtons,
fiatBalance = formatFiatAmount(status.value, appCurrencyProvider()),
cryptoBalance = formatCryptoAmount(status),
+ isStakingEnabled = isStakingEnabled,
+ balanceSegmentedButtonConfig = currentState.balanceSegmentedButtonConfig,
+ onBalanceSelect = clickIntents::onBalanceSelect,
+ selectedBalanceType = currentState.selectedBalanceType,
+ )
+ is CryptoCurrencyStatus.Loading -> TokenDetailsBalanceBlockState.Loading(
+ actionButtons = currentState.actionButtons,
+ balanceSegmentedButtonConfig = currentState.balanceSegmentedButtonConfig,
+ selectedBalanceType = BalanceType.ALL,
)
- is CryptoCurrencyStatus.Loading -> TokenDetailsBalanceBlockState.Loading(currentState.actionButtons)
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
- -> TokenDetailsBalanceBlockState.Error(currentState.actionButtons)
+ -> TokenDetailsBalanceBlockState.Error(
+ actionButtons = currentState.actionButtons,
+ balanceSegmentedButtonConfig = currentState.balanceSegmentedButtonConfig,
+ selectedBalanceType = BalanceType.ALL,
+ )
}
}
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt
index 9cc42f3c2d..3268e37904 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt
@@ -48,9 +48,16 @@ internal class TokenDetailsSkeletonStateConverter(
)
},
),
- tokenBalanceBlockState = TokenDetailsBalanceBlockState.Loading(actionButtons = createButtons()),
+ tokenBalanceBlockState = TokenDetailsBalanceBlockState.Loading(
+ actionButtons = createButtons(),
+ balanceSegmentedButtonConfig = createBalanceSegmentedButtonConfig(),
+ selectedBalanceType = BalanceType.ALL,
+ ),
marketPriceBlockState = MarketPriceBlockState.Loading(value.symbol),
- stakingBlockState = StakingBlockState.Loading(iconState = iconState),
+ stakingBlocksState = StakingBlocksState(
+ stakingAvailable = StakingAvailable.Loading(iconState),
+ stakingBalance = StakingBalance.Empty,
+ ),
notifications = persistentListOf(),
pendingTxs = persistentListOf(),
swapTxs = persistentListOf(),
@@ -99,6 +106,19 @@ internal class TokenDetailsSkeletonStateConverter(
)
}
+ private fun createBalanceSegmentedButtonConfig(): ImmutableList {
+ return persistentListOf(
+ TokenBalanceSegmentedButtonConfig(
+ title = resourceReference(R.string.common_all),
+ type = BalanceType.ALL,
+ ),
+ TokenBalanceSegmentedButtonConfig(
+ title = resourceReference(R.string.staking_details_available),
+ type = BalanceType.AVAILABLE,
+ ),
+ )
+ }
+
private fun createPullToRefresh(): TokenDetailsPullToRefreshConfig = TokenDetailsPullToRefreshConfig(
isRefreshing = false,
onRefresh = clickIntents::onRefreshSwipe,
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt
index 9f8de13d25..54210912e8 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt
@@ -24,9 +24,7 @@ import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryListError
import com.tangem.domain.txhistory.models.TxHistoryStateError
-import com.tangem.feature.tokendetails.presentation.tokendetails.state.SwapTransactionsState
-import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsAppBarMenuConfig
-import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsDialogConfig
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadedTxHistoryConverter
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter
@@ -46,6 +44,7 @@ internal class TokenDetailsStateFactory(
private val appCurrencyProvider: Provider,
private val clickIntents: TokenDetailsClickIntents,
private val featureToggles: TokenDetailsFeatureToggles,
+ private val isStakingEnabled: Boolean,
symbol: String,
decimals: Int,
) {
@@ -65,6 +64,7 @@ internal class TokenDetailsStateFactory(
TokenDetailsLoadedBalanceConverter(
currentStateProvider = currentStateProvider,
appCurrencyProvider = appCurrencyProvider,
+ isStakingEnabled = isStakingEnabled,
symbol = symbol,
decimals = decimals,
clickIntents = clickIntents,
@@ -218,7 +218,7 @@ internal class TokenDetailsStateFactory(
fun getStateWithStaking(stakingEither: Either): TokenDetailsState {
return currentStateProvider().copy(
- stakingBlockState = stakingStateConverter.convert(stakingEither),
+ stakingBlocksState = stakingStateConverter.convert(stakingEither),
)
}
@@ -348,6 +348,17 @@ internal class TokenDetailsStateFactory(
}
}
+ fun getStateWithUpdatedBalanceSegmentedButtonConfig(
+ buttonConfig: TokenBalanceSegmentedButtonConfig,
+ ): TokenDetailsState {
+ return with(currentStateProvider()) {
+ val updatedState = (tokenBalanceBlockState as? TokenDetailsBalanceBlockState.Content)
+ ?.copy(selectedBalanceType = buttonConfig.type)
+ ?: tokenBalanceBlockState
+ copy(tokenBalanceBlockState = updatedState)
+ }
+ }
+
private fun TokenDetailsAppBarMenuConfig.updateMenu(
cardTypesResolver: CardTypesResolver,
isBitcoin: Boolean,
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt
index 0bdf52927f..29fe830039 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt
@@ -3,7 +3,9 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory
import arrow.core.Either
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.staking.model.StakingEntryInfo
-import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockState
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingAvailable
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBalance
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlocksState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents
import com.tangem.utils.Provider
@@ -12,25 +14,31 @@ import com.tangem.utils.converter.Converter
internal class TokenStakingStateConverter(
private val clickIntents: TokenDetailsClickIntents,
private val currentStateProvider: Provider,
-) : Converter, StakingBlockState> {
+) : Converter, StakingBlocksState> {
- override fun convert(value: Either): StakingBlockState {
+ override fun convert(value: Either): StakingBlocksState {
value.fold(
ifLeft = {
- return StakingBlockState.Error(
- iconState = currentStateProvider().tokenInfoBlockState.iconState,
+ return StakingBlocksState(
+ stakingAvailable = StakingAvailable.Error(
+ iconState = currentStateProvider().tokenInfoBlockState.iconState,
+ ),
+ stakingBalance = StakingBalance.Empty,
)
},
ifRight = {
- return StakingBlockState.Content(
- interestRate = BigDecimalFormatter.formatPercent(
- percent = it.interestRate,
- useAbsoluteValue = true,
+ return StakingBlocksState(
+ stakingAvailable = StakingAvailable.Content(
+ interestRate = BigDecimalFormatter.formatPercent(
+ percent = it.interestRate,
+ useAbsoluteValue = true,
+ ),
+ periodInDays = it.periodInDays,
+ tokenSymbol = it.tokenSymbol,
+ iconState = currentStateProvider().tokenInfoBlockState.iconState,
+ onStakeClicked = clickIntents::onStakeBannerClick,
),
- periodInDays = it.periodInDays,
- tokenSymbol = it.tokenSymbol,
- iconState = currentStateProvider().tokenInfoBlockState.iconState,
- onStakeClicked = clickIntents::onStakeBannerClick,
+ stakingBalance = StakingBalance.Empty,
)
},
)
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt
index e4574897ac..f076f05240 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt
@@ -41,10 +41,10 @@ import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData
-import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockState
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingAvailable
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBalance
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification
-import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.*
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.TokenDetailsBalanceBlock
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.TokenDetailsDialogs
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.TokenDetailsTopAppBar
@@ -52,6 +52,8 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.T
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.exchange.ExchangeStatusBottomSheet
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.exchange.ExchangeStatusBottomSheetConfig
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.exchange.swapTransactionsItems
+import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.staking.StakingBalanceBlock
+import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.staking.TokenStakingBlock
// TODO: Split to blocks [REDACTED_JIRA]
@Suppress("LongMethod")
@@ -140,10 +142,27 @@ internal fun TokenDetailsScreen(state: TokenDetailsState) {
if (state.isStakingBlockShown) {
item(
- key = StakingBlockState::class.java,
- contentType = StakingBlockState::class.java,
- content = { TokenStakingBlock(modifier = itemModifier, state = state.stakingBlockState) },
+ key = StakingAvailable::class.java,
+ contentType = StakingAvailable::class.java,
+ content = {
+ TokenStakingBlock(
+ modifier = itemModifier,
+ state = state.stakingBlocksState.stakingAvailable,
+ )
+ },
)
+ if (state.stakingBlocksState.stakingBalance is StakingBalance.Content) {
+ item(
+ key = StakingBalance::class.java,
+ contentType = StakingBalance::class.java,
+ content = {
+ StakingBalanceBlock(
+ state = state.stakingBlocksState.stakingBalance,
+ modifier = itemModifier,
+ )
+ },
+ )
+ }
}
swapTransactionsItems(
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/TokenDetailsBalanceBlock.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/TokenDetailsBalanceBlock.kt
index 06d871b579..081fab085e 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/TokenDetailsBalanceBlock.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/TokenDetailsBalanceBlock.kt
@@ -13,6 +13,8 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.buttons.HorizontalActionChips
+import com.tangem.core.ui.components.buttons.segmentedbutton.SegmentedButtons
+import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.BigDecimalFormatter
@@ -35,20 +37,23 @@ internal fun TokenDetailsBalanceBlock(
color = TangemTheme.colors.background.primary,
) {
Column {
- Box(
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
- .padding(top = TangemTheme.dimens.spacing12)
.padding(horizontal = TangemTheme.dimens.spacing12)
.fillMaxWidth()
.heightIn(min = TangemTheme.dimens.spacing24),
- contentAlignment = Alignment.CenterStart,
) {
Text(
text = stringResource(id = R.string.common_balance_title),
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.subtitle2,
maxLines = 1,
+ modifier = Modifier
+ .weight(1f)
+ .padding(top = TangemTheme.dimens.spacing12),
)
+ BalanceButtons(state)
}
FiatBalance(
state = state,
@@ -130,6 +135,35 @@ private fun CryptoBalance(
}
}
+@Composable
+private fun BalanceButtons(state: TokenDetailsBalanceBlockState) {
+ if (state !is TokenDetailsBalanceBlockState.Content) return
+
+ SegmentedButtons(
+ config = state.balanceSegmentedButtonConfig,
+ onClick = state.onBalanceSelect,
+ showIndication = false,
+ modifier = Modifier
+ .padding(top = TangemTheme.dimens.spacing11)
+ .width(IntrinsicSize.Min),
+ ) { config ->
+ Text(
+ text = config.title.resolveReference(),
+ color = TangemTheme.colors.text.primary1,
+ style = TangemTheme.typography.caption1,
+ maxLines = 1,
+ modifier = Modifier
+ .padding(
+ start = TangemTheme.dimens.spacing5,
+ end = TangemTheme.dimens.spacing5,
+ top = TangemTheme.dimens.spacing3,
+ bottom = TangemTheme.dimens.spacing3,
+ )
+ .align(Alignment.Center),
+ )
+ }
+}
+
@Preview(widthDp = 328, heightDp = 152)
@Preview(widthDp = 328, heightDp = 152, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingBalanceBlock.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingBalanceBlock.kt
new file mode 100644
index 0000000000..4a2929a40d
--- /dev/null
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingBalanceBlock.kt
@@ -0,0 +1,98 @@
+package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.staking
+
+import android.content.res.Configuration
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.*
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.res.painterResource
+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.PreviewParameterProvider
+import com.tangem.core.ui.extensions.resolveReference
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.res.TangemThemePreview
+import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBalance
+import com.tangem.features.tokendetails.impl.R
+import com.tangem.utils.Strings
+
+@Composable
+fun StakingBalanceBlock(state: StakingBalance.Content, modifier: Modifier = Modifier) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = modifier
+ .fillMaxWidth()
+ .clip(TangemTheme.shapes.roundedCornersXMedium)
+ .background(TangemTheme.colors.background.action)
+ .padding(TangemTheme.dimens.spacing12),
+ ) {
+ Column(
+ verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
+ modifier = Modifier.weight(1f),
+ ) {
+ Text(
+ text = stringResource(R.string.staking_native),
+ style = TangemTheme.typography.subtitle2,
+ color = TangemTheme.colors.text.tertiary,
+ modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing2),
+ )
+ Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
+ Text(
+ text = state.fiatAmount.resolveReference(),
+ style = TangemTheme.typography.body2,
+ color = TangemTheme.colors.text.primary1,
+ )
+ Text(
+ text = Strings.DOT,
+ style = TangemTheme.typography.body2,
+ color = TangemTheme.colors.text.primary1,
+ )
+ Text(
+ text = state.cryptoAmount.resolveReference(),
+ style = TangemTheme.typography.body2,
+ color = TangemTheme.colors.text.tertiary,
+ )
+ }
+ Text(
+ text = state.rewardAmount.resolveReference(),
+ style = TangemTheme.typography.caption2,
+ color = TangemTheme.colors.text.tertiary,
+ )
+ }
+ Icon(
+ painter = painterResource(id = R.drawable.ic_chevron_right_24),
+ contentDescription = null,
+ tint = TangemTheme.colors.icon.informative,
+ )
+ }
+}
+
+// region Preview
+@Preview(showBackground = true, widthDp = 360)
+@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun StakingBalanceBlock_Preview(
+ @PreviewParameter(StakingBalanceBlockPreviewProvider::class) data: StakingBalance,
+) {
+ TangemThemePreview {
+ StakingBalanceBlock(
+ state = data as StakingBalance.Content,
+ modifier = Modifier.padding(TangemTheme.dimens.spacing16),
+ )
+ }
+}
+
+private class StakingBalanceBlockPreviewProvider : PreviewParameterProvider {
+ override val values: Sequence
+ get() = sequenceOf(
+ TokenDetailsPreviewData.tokenDetailsState_1.stakingBlocksState.stakingBalance,
+ TokenDetailsPreviewData.tokenDetailsState_2.stakingBlocksState.stakingBalance,
+ )
+}
+// endregion
\ No newline at end of file
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/TokenStakingBlock.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlock.kt
similarity index 86%
rename from features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/TokenStakingBlock.kt
rename to features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlock.kt
index d888903a28..e9f66e62ab 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/TokenStakingBlock.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlock.kt
@@ -1,11 +1,12 @@
-package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components
+package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.staking
import android.content.res.Configuration
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
-import androidx.compose.material.Text
-import androidx.compose.runtime.*
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -14,14 +15,17 @@ 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.*
-import com.tangem.core.ui.res.TangemThemePreview
+import com.tangem.core.ui.components.RectangleShimmer
+import com.tangem.core.ui.components.SecondaryButton
+import com.tangem.core.ui.components.SpacerW8
import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.GRAY_SCALE_ALPHA
import com.tangem.core.ui.utils.GrayscaleColorFilter
import com.tangem.core.ui.utils.NORMAL_ALPHA
import com.tangem.feature.tokendetails.presentation.tokendetails.state.IconState
-import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockState
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingAvailable
+import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.CurrencyIcon
import com.tangem.features.tokendetails.impl.R
/**
@@ -31,7 +35,7 @@ import com.tangem.features.tokendetails.impl.R
* @param modifier modifier
*/
@Composable
-internal fun TokenStakingBlock(state: StakingBlockState, modifier: Modifier = Modifier) {
+internal fun TokenStakingBlock(state: StakingAvailable, modifier: Modifier = Modifier) {
Column(
modifier = modifier
.background(
@@ -49,7 +53,7 @@ internal fun TokenStakingBlock(state: StakingBlockState, modifier: Modifier = Mo
}
@Composable
-private fun Content(state: StakingBlockState, modifier: Modifier = Modifier) {
+private fun Content(state: StakingAvailable, modifier: Modifier = Modifier) {
AnimatedContent(
modifier = modifier.heightIn(min = TangemTheme.dimens.size60),
targetState = state,
@@ -57,24 +61,24 @@ private fun Content(state: StakingBlockState, modifier: Modifier = Modifier) {
label = "Update the content",
) { stakingBlockState ->
when (stakingBlockState) {
- is StakingBlockState.Content -> {
+ is StakingAvailable.Content -> {
StakingContent(
stakingBlockState = stakingBlockState,
iconState = stakingBlockState.iconState,
)
}
- is StakingBlockState.Loading -> {
+ is StakingAvailable.Loading -> {
StakingLoading(
iconState = stakingBlockState.iconState,
)
}
- is StakingBlockState.Error -> Row {} // TODO staking
+ is StakingAvailable.Error -> Row {} // TODO staking
}
}
}
@Composable
-private fun StakingContent(stakingBlockState: StakingBlockState.Content, iconState: IconState) {
+private fun StakingContent(stakingBlockState: StakingAvailable.Content, iconState: IconState) {
Column {
Row {
val (alpha, colorFilter) = remember(iconState.isGrayscale) {
@@ -177,24 +181,24 @@ private fun StakingLoading(iconState: IconState) {
@Composable
private fun Preview_TokenStakingBlock(
@PreviewParameter(StakingBlockStateProvider::class)
- state: StakingBlockState,
+ state: StakingAvailable,
) {
TangemThemePreview {
TokenStakingBlock(state = state)
}
}
-private class StakingBlockStateProvider : CollectionPreviewParameterProvider(
+private class StakingBlockStateProvider : CollectionPreviewParameterProvider(
collection = listOf(
- StakingBlockState.Content(
+ StakingAvailable.Content(
iconState = iconState,
interestRate = "10",
periodInDays = 4,
tokenSymbol = "SOL",
onStakeClicked = {},
),
- StakingBlockState.Loading(iconState = iconState),
- StakingBlockState.Error(iconState = iconState),
+ StakingAvailable.Loading(iconState = iconState),
+ StakingAvailable.Error(iconState = iconState),
),
)
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt
index 51b5adda0c..9332738ab0 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt
@@ -4,6 +4,7 @@ import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenBalanceSegmentedButtonConfig
@Suppress("TooManyFunctions")
interface TokenDetailsClickIntents {
@@ -59,4 +60,6 @@ interface TokenDetailsClickIntents {
fun onAssociateClick()
fun onStakeBannerClick()
+
+ fun onBalanceSelect(config: TokenBalanceSegmentedButtonConfig)
}
\ No newline at end of file
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
index 09a908e65f..333fdc48e6 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
@@ -63,6 +63,7 @@ import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRout
import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenDetailsCurrencyStatusAnalyticsSender
import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenDetailsNotificationsAnalyticsSender
import com.tangem.feature.tokendetails.presentation.tokendetails.state.SwapTransactionsState
+import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenBalanceSegmentedButtonConfig
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsStateFactory
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.exchange.ExchangeStatusBottomSheetConfig
@@ -125,12 +126,12 @@ internal class TokenDetailsViewModel @Inject constructor(
) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents {
private val userWalletId: UserWalletId = savedStateHandle.get(AppRoute.CurrencyDetails.USER_WALLET_ID_KEY)
- ?.let { it.unbundle(UserWalletId.serializer()) }
+ ?.unbundle(UserWalletId.serializer())
?: error("This screen can't open without `UserWalletId`")
private val cryptoCurrency: CryptoCurrency =
savedStateHandle.get(AppRoute.CurrencyDetails.CRYPTO_CURRENCY_KEY)
- ?.let { it.unbundle(CryptoCurrency.serializer()) }
+ ?.unbundle(CryptoCurrency.serializer())
?: error("This screen can't open without `CryptoCurrency`")
private val userWallet: UserWallet
@@ -154,6 +155,7 @@ internal class TokenDetailsViewModel @Inject constructor(
symbol = cryptoCurrency.symbol,
decimals = cryptoCurrency.decimals,
featureToggles = tokenDetailsFeatureToggles,
+ isStakingEnabled = stakingFeatureToggles.isStakingEnabled,
)
private val exchangeStatusFactory by lazy(mode = LazyThreadSafetyMode.NONE) {
@@ -787,6 +789,10 @@ internal class TokenDetailsViewModel @Inject constructor(
}
}
+ override fun onBalanceSelect(config: TokenBalanceSegmentedButtonConfig) {
+ uiState = stateFactory.getStateWithUpdatedBalanceSegmentedButtonConfig(config)
+ }
+
private fun handleUnavailabilityReason(unavailabilityReason: ScenarioUnavailabilityReason): Boolean {
if (unavailabilityReason == ScenarioUnavailabilityReason.None) return false
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VisaTxHistoryItemStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VisaTxHistoryItemStateConverter.kt
index 5c1b0a20c5..819d0d20d1 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VisaTxHistoryItemStateConverter.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VisaTxHistoryItemStateConverter.kt
@@ -9,6 +9,7 @@ import com.tangem.domain.visa.model.VisaCurrency
import com.tangem.domain.visa.model.VisaTxHistoryItem
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.VisaWalletIntents
+import com.tangem.utils.Strings
import com.tangem.utils.converter.Converter
import org.joda.time.DateTimeZone
@@ -20,7 +21,7 @@ internal class VisaTxHistoryItemStateConverter(
override fun convert(value: VisaTxHistoryItem): TransactionState {
val localDate = value.date.withZone(DateTimeZone.getDefault())
val time = DateTimeFormatters.formatDate(localDate, DateTimeFormatters.timeFormatter)
- val subtitle = "$time • ${value.status.capitalize()}"
+ val subtitle = "$time ${Strings.DOT} ${value.status.capitalize()}"
return TransactionState.Content(
txHash = value.id,