Updated on 2026-08-14
This commit is contained in:
parent
67016b4755
commit
57eb2359a7
19 changed files with 291 additions and 125 deletions
|
|
@ -21,6 +21,7 @@ data class Address(
|
|||
val binanceBeaconAddress: String? = null,
|
||||
|
||||
// solana-specific
|
||||
@Deprecated("Legacy in StakeKit, isn't used in Solana")
|
||||
@Json(name = "stakeAccounts")
|
||||
val stakeAccounts: List<String>? = null,
|
||||
@Json(name = "lidoStakeAccounts")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
package com.tangem.core.ui.components.list
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.rows.CornersToRound
|
||||
import com.tangem.core.ui.components.rows.RoundableCornersRow
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
fun RoundedListWithDividers(rows: List<RoundedListWithDividersItemData>, modifier: Modifier = Modifier) {
|
||||
LazyColumn(modifier = modifier) {
|
||||
itemsIndexed(
|
||||
items = rows,
|
||||
key = { _, item -> item.id },
|
||||
) { index, row ->
|
||||
InitialInfoContentRow(
|
||||
startText = row.startText.resolveReference(),
|
||||
endText = row.endText.resolveReference(),
|
||||
cornersToRound = getCornersToRound(index, rows.size),
|
||||
iconClick = row.iconClick,
|
||||
)
|
||||
if (index < rows.lastIndex) {
|
||||
RoundedListDivider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun InitialInfoContentRow(
|
||||
startText: String,
|
||||
endText: String,
|
||||
cornersToRound: CornersToRound,
|
||||
iconClick: (() -> Unit)? = null,
|
||||
) {
|
||||
RoundableCornersRow(
|
||||
startText = startText,
|
||||
startTextColor = TangemTheme.colors.text.primary1,
|
||||
startTextStyle = TangemTheme.typography.body2,
|
||||
endText = endText,
|
||||
endTextColor = TangemTheme.colors.text.tertiary,
|
||||
endTextStyle = TangemTheme.typography.body2,
|
||||
cornersToRound = cornersToRound,
|
||||
iconResId = R.drawable.ic_information_24,
|
||||
iconClick = iconClick,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RoundedListDivider() {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(TangemTheme.dimens.size0_5),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(TangemTheme.dimens.size16)
|
||||
.height(TangemTheme.dimens.size0_5)
|
||||
.background(TangemTheme.colors.background.primary),
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.height(TangemTheme.dimens.size0_5)
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCornersToRound(currentIndex: Int, listSize: Int): CornersToRound {
|
||||
return when (currentIndex) {
|
||||
0 -> CornersToRound.TOP_2
|
||||
listSize - 1 -> CornersToRound.BOTTOM_2
|
||||
else -> CornersToRound.ZERO
|
||||
}
|
||||
}
|
||||
|
||||
data class RoundedListWithDividersItemData(
|
||||
val id: Int,
|
||||
val startText: TextReference,
|
||||
val endText: TextReference,
|
||||
val iconClick: (() -> Unit)? = null,
|
||||
)
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_StakingInfoBottomSheet() {
|
||||
TangemThemePreview {
|
||||
RoundedListWithDividers(
|
||||
rows = persistentListOf(
|
||||
RoundedListWithDividersItemData(
|
||||
id = 1,
|
||||
startText = TextReference.Str("Key 1"),
|
||||
endText = TextReference.Str("Value 1"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = 2,
|
||||
startText = TextReference.Str("Key 2"),
|
||||
endText = TextReference.Str("Value 2"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = 3,
|
||||
startText = TextReference.Str("Key 3"),
|
||||
endText = TextReference.Str("Value 3"),
|
||||
iconClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
5
core/ui/src/main/res/drawable/ic_staking_24.xml
Normal file
5
core/ui/src/main/res/drawable/ic_staking_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="20" android:viewportWidth="20" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M10,15.45L16.142,10.667L17.5,11.725L10,17.558L2.5,11.725L3.85,10.675L10,15.45ZM10,13.333L2.5,7.5L10,1.667L17.5,7.5L10,13.333ZM10,3.775L5.217,7.5L10,11.225L14.783,7.5L10,3.775Z"/>
|
||||
|
||||
</vector>
|
||||
|
|
@ -124,9 +124,9 @@ internal class DefaultStakingRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getEntryInfo(integrationId: String): StakingEntryInfo {
|
||||
override suspend fun getEntryInfo(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): StakingEntryInfo {
|
||||
return withContext(dispatchers.io) {
|
||||
val yield = stakeKitApi.getSingleYield(integrationId).getOrThrow()
|
||||
val yield = getYield(cryptoCurrencyId, symbol)
|
||||
|
||||
StakingEntryInfo(
|
||||
interestRate = yield.apy,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.domain.staking.model.StakingEntryInfo
|
|||
import com.tangem.domain.staking.model.stakekit.StakingError
|
||||
import com.tangem.domain.staking.repositories.StakingErrorResolver
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
||||
/**
|
||||
* Use case for getting entry info about staking on token screen.
|
||||
|
|
@ -14,9 +15,17 @@ class GetStakingEntryInfoUseCase(
|
|||
private val stakingErrorResolver: StakingErrorResolver,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(integrationId: String): Either<StakingError, StakingEntryInfo> {
|
||||
suspend operator fun invoke(
|
||||
cryptoCurrencyId: CryptoCurrency.ID,
|
||||
symbol: String,
|
||||
): Either<StakingError, StakingEntryInfo> {
|
||||
return Either
|
||||
.catch { stakingRepository.getEntryInfo(integrationId) }
|
||||
.catch {
|
||||
stakingRepository.getEntryInfo(
|
||||
cryptoCurrencyId = cryptoCurrencyId,
|
||||
symbol = symbol,
|
||||
)
|
||||
}
|
||||
.mapLeft { stakingErrorResolver.resolve(it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ interface StakingRepository {
|
|||
|
||||
suspend fun fetchEnabledYields(refresh: Boolean)
|
||||
|
||||
suspend fun getEntryInfo(integrationId: String): StakingEntryInfo
|
||||
suspend fun getEntryInfo(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): StakingEntryInfo
|
||||
|
||||
suspend fun getYield(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): Yield
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,12 @@ class MockStakingRepository : StakingRepository {
|
|||
/* no-op */
|
||||
}
|
||||
|
||||
override suspend fun getEntryInfo(integrationId: String): StakingEntryInfo = StakingEntryInfo(
|
||||
interestRate = 1.toBigDecimal(),
|
||||
periodInDays = 2,
|
||||
tokenSymbol = "SOL",
|
||||
)
|
||||
override suspend fun getEntryInfo(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): StakingEntryInfo =
|
||||
StakingEntryInfo(
|
||||
interestRate = 1.toBigDecimal(),
|
||||
periodInDays = 2,
|
||||
tokenSymbol = "SOL",
|
||||
)
|
||||
|
||||
override suspend fun getYield(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): Yield = Yield(
|
||||
id = "1",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.staking.impl.presentation.state
|
|||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.list.RoundedListWithDividersItemData
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||
|
|
@ -47,6 +48,14 @@ internal sealed class StakingStates {
|
|||
sealed class InitialInfoState : StakingStates() {
|
||||
data class Data(
|
||||
override val isPrimaryButtonEnabled: Boolean,
|
||||
val infoItems: ImmutableList<RoundedListWithDividersItemData>,
|
||||
val aprRange: TextReference,
|
||||
val onInfoClick: (InfoType) -> Unit,
|
||||
val yieldBalance: InnerYieldBalanceState,
|
||||
val isStakeMoreAvailable: Boolean,
|
||||
) : InitialInfoState()
|
||||
|
||||
data class InitialInfoItems(
|
||||
val available: String,
|
||||
val onStake: String,
|
||||
val aprRange: TextReference,
|
||||
|
|
@ -55,10 +64,7 @@ internal sealed class StakingStates {
|
|||
val rewardClaiming: String,
|
||||
val warmupPeriod: String,
|
||||
val rewardSchedule: String,
|
||||
val onInfoClick: (InfoType) -> Unit,
|
||||
val yieldBalance: InnerYieldBalanceState,
|
||||
val isStakeMoreAvailable: Boolean,
|
||||
) : InitialInfoState()
|
||||
)
|
||||
|
||||
data class Empty(
|
||||
override val isPrimaryButtonEnabled: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -1,21 +1,59 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.previewdata
|
||||
|
||||
import com.tangem.core.ui.components.list.RoundedListWithDividersItemData
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.*
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal object InitialStakingStatePreview {
|
||||
val defaultState = StakingStates.InitialInfoState.Data(
|
||||
isPrimaryButtonEnabled = true,
|
||||
available = "15 SOL",
|
||||
onStake = "0 SOL",
|
||||
aprRange = stringReference("2.54-5.12%"),
|
||||
unbondingPeriod = "3d",
|
||||
minimumRequirement = "12 SOL",
|
||||
rewardClaiming = "Auto",
|
||||
warmupPeriod = "Days",
|
||||
rewardSchedule = "Block",
|
||||
infoItems = persistentListOf(
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_available,
|
||||
startText = TextReference.Res(R.string.staking_details_available),
|
||||
endText = TextReference.Str("15 SOL"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_apy,
|
||||
startText = TextReference.Res(R.string.staking_details_apy),
|
||||
endText = TextReference.Str("2.54-5.12%"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_on_stake,
|
||||
startText = TextReference.Res(R.string.staking_details_on_stake),
|
||||
endText = TextReference.Str("0 SOL"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_unbonding_period,
|
||||
startText = TextReference.Res(R.string.staking_details_unbonding_period),
|
||||
endText = TextReference.Str("3d"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_minimum_requirement,
|
||||
startText = TextReference.Res(R.string.staking_details_minimum_requirement),
|
||||
endText = TextReference.Str("12 SOL"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_reward_claiming,
|
||||
startText = TextReference.Res(R.string.staking_details_reward_claiming),
|
||||
endText = TextReference.Str("Auto"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_warmup_period,
|
||||
startText = TextReference.Res(R.string.staking_details_warmup_period),
|
||||
endText = TextReference.Str("Days"),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_reward_schedule,
|
||||
startText = TextReference.Res(R.string.staking_details_reward_schedule),
|
||||
endText = TextReference.Str("Block"),
|
||||
),
|
||||
),
|
||||
onInfoClick = {},
|
||||
yieldBalance = InnerYieldBalanceState.Empty,
|
||||
isStakeMoreAvailable = true,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import com.tangem.utils.Provider
|
|||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class SetConfirmationStateAssentTransformer(
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.features.staking.impl.presentation.state.*
|
|||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class SetConfirmationStateLoadingTransformer(
|
||||
private val yield: Yield,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.common.extensions.remove
|
|||
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.list.RoundedListWithDividersItemData
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
|
|
@ -26,6 +27,8 @@ import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickInten
|
|||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class SetInitialDataStateTransformer(
|
||||
|
|
@ -70,33 +73,87 @@ internal class SetInitialDataStateTransformer(
|
|||
}
|
||||
|
||||
private fun createInitialInfoState(): StakingStates.InitialInfoState.Data {
|
||||
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance
|
||||
|
||||
return StakingStates.InitialInfoState.Data(
|
||||
isPrimaryButtonEnabled = true,
|
||||
available = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = cryptoCurrencyStatus.value.amount,
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
|
||||
decimals = cryptoCurrencyStatus.currency.decimals,
|
||||
),
|
||||
onStake = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = (yieldBalance as? YieldBalance.Data)?.getTotalStakingBalance().orZero(),
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
|
||||
decimals = cryptoCurrencyStatus.currency.decimals,
|
||||
),
|
||||
aprRange = getAprRange(),
|
||||
unbondingPeriod = yield.metadata.cooldownPeriod.days.toString(),
|
||||
minimumRequirement = yield.metadata.minimumStake.toString(),
|
||||
rewardClaiming = yield.metadata.rewardClaiming,
|
||||
warmupPeriod = yield.metadata.warmupPeriod.days.toString(),
|
||||
rewardSchedule = yield.metadata.rewardSchedule,
|
||||
infoItems = getInfoItems(),
|
||||
onInfoClick = clickIntents::onInfoClick,
|
||||
yieldBalance = yieldBalancesConverter.convert(Unit),
|
||||
isStakeMoreAvailable = isStakeMoreAvailable,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getInfoItems(): PersistentList<RoundedListWithDividersItemData> {
|
||||
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance
|
||||
|
||||
return persistentListOf(
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_available,
|
||||
startText = TextReference.Res(R.string.staking_details_available),
|
||||
endText = TextReference.Str(
|
||||
value = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = cryptoCurrencyStatus.value.amount,
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
|
||||
decimals = cryptoCurrencyStatus.currency.decimals,
|
||||
),
|
||||
),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_apy,
|
||||
startText = TextReference.Res(R.string.staking_details_apy),
|
||||
endText = getAprRange(),
|
||||
iconClick = { clickIntents.onInfoClick(InfoType.APY) },
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_on_stake,
|
||||
startText = TextReference.Res(R.string.staking_details_on_stake),
|
||||
endText = TextReference.Str(
|
||||
value = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = (yieldBalance as? YieldBalance.Data)?.getTotalStakingBalance().orZero(),
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
|
||||
decimals = cryptoCurrencyStatus.currency.decimals,
|
||||
),
|
||||
),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_unbonding_period,
|
||||
startText = TextReference.Res(R.string.staking_details_unbonding_period),
|
||||
endText = TextReference.Str(yield.metadata.cooldownPeriod.days.toString()),
|
||||
iconClick = { clickIntents.onInfoClick(InfoType.UNBOUNDING_PERIOD) },
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_minimum_requirement,
|
||||
startText = TextReference.Res(R.string.staking_details_minimum_requirement),
|
||||
endText = TextReference.Str(
|
||||
value = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = yield.args.enter.args[KEY_AMOUNT]?.minimum?.toBigDecimal(),
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
|
||||
decimals = cryptoCurrencyStatus.currency.decimals,
|
||||
),
|
||||
),
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_reward_claiming,
|
||||
startText = TextReference.Res(R.string.staking_details_reward_claiming),
|
||||
endText = TextReference.Str(yield.metadata.rewardClaiming),
|
||||
iconClick = { clickIntents.onInfoClick(InfoType.REWARD_CLAIMING) },
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_warmup_period,
|
||||
startText = TextReference.Res(R.string.staking_details_warmup_period),
|
||||
endText = TextReference.Str(yield.metadata.warmupPeriod.days.toString()),
|
||||
iconClick = { clickIntents.onInfoClick(InfoType.WARMUP_PERIOD) },
|
||||
),
|
||||
RoundedListWithDividersItemData(
|
||||
id = R.string.staking_details_reward_schedule,
|
||||
startText = TextReference.Res(R.string.staking_details_reward_schedule),
|
||||
endText = TextReference.Str(yield.metadata.rewardSchedule),
|
||||
iconClick = { clickIntents.onInfoClick(InfoType.REWARD_SCHEDULE) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createInitialAmountState(): AmountState {
|
||||
return amountStateConverter.convert("")
|
||||
}
|
||||
|
|
@ -134,5 +191,6 @@ internal class SetInitialDataStateTransformer(
|
|||
|
||||
companion object {
|
||||
private val EQUALITY_THRESHOLD = BigDecimal(1E-10)
|
||||
private const val KEY_AMOUNT = "amount"
|
||||
}
|
||||
}
|
||||
|
|
@ -7,9 +7,7 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
|
|
@ -27,8 +25,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
|||
import com.tangem.core.ui.components.containers.FooterContainer
|
||||
import com.tangem.core.ui.components.inputrow.InputRowDefault
|
||||
import com.tangem.core.ui.components.inputrow.InputRowImageInfo
|
||||
import com.tangem.core.ui.components.rows.CornersToRound
|
||||
import com.tangem.core.ui.components.rows.RoundableCornersRow
|
||||
import com.tangem.core.ui.components.list.RoundedListWithDividers
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -37,7 +34,6 @@ import com.tangem.features.staking.impl.R
|
|||
import com.tangem.features.staking.impl.presentation.state.*
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.InitialStakingStatePreview
|
||||
import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||
import com.tangem.utils.StringsSigns.DOT
|
||||
import com.tangem.utils.StringsSigns.PLUS
|
||||
|
|
@ -55,13 +51,12 @@ internal fun StakingInitialInfoContent(state: StakingStates.InitialInfoState, cl
|
|||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
),
|
||||
) {
|
||||
AnimatedVisibility(state.yieldBalance == InnerYieldBalanceState.Empty) {
|
||||
MetricsBlock(state)
|
||||
}
|
||||
StakingDetailsRows(state)
|
||||
RoundedListWithDividers(state.infoItems)
|
||||
AnimatedContent(targetState = state.yieldBalance, label = "Rewards block visibility animation") {
|
||||
if (it is InnerYieldBalanceState.Data) {
|
||||
StakingRewardBlock(
|
||||
|
|
@ -142,57 +137,6 @@ private fun MetricsBlock(state: StakingStates.InitialInfoState.Data) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun StakingDetailsRows(state: StakingStates.InitialInfoState.Data) {
|
||||
Column {
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_available),
|
||||
endText = state.available,
|
||||
cornersToRound = CornersToRound.TOP_2,
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_on_stake),
|
||||
endText = state.onStake,
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_apy),
|
||||
endText = state.aprRange.resolveReference(),
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
iconClick = { state.onInfoClick(InfoType.APY) },
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_unbonding_period),
|
||||
endText = state.unbondingPeriod,
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
iconClick = { state.onInfoClick(InfoType.UNBOUNDING_PERIOD) },
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_minimum_requirement),
|
||||
endText = state.minimumRequirement,
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_reward_claiming),
|
||||
endText = state.rewardClaiming,
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
iconClick = { state.onInfoClick(InfoType.REWARD_CLAIMING) },
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_warmup_period),
|
||||
endText = state.warmupPeriod,
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
iconClick = { state.onInfoClick(InfoType.WARMUP_PERIOD) },
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_reward_schedule),
|
||||
endText = state.rewardSchedule,
|
||||
cornersToRound = CornersToRound.BOTTOM_2,
|
||||
iconClick = { state.onInfoClick(InfoType.REWARD_SCHEDULE) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun StakingRewardBlock(
|
||||
rewardCrypto: String,
|
||||
|
|
@ -295,25 +239,7 @@ private fun ActiveStakingBlock(groups: List<BalanceGroupedState>, onClick: (Bala
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun InitialInfoContentRow(
|
||||
startText: String,
|
||||
endText: String,
|
||||
cornersToRound: CornersToRound,
|
||||
iconClick: (() -> Unit)? = null,
|
||||
) {
|
||||
RoundableCornersRow(
|
||||
startText = startText,
|
||||
startTextColor = TangemTheme.colors.text.primary1,
|
||||
startTextStyle = TangemTheme.typography.body2,
|
||||
endText = endText,
|
||||
endTextColor = TangemTheme.colors.text.tertiary,
|
||||
endTextStyle = TangemTheme.typography.body2,
|
||||
cornersToRound = cornersToRound,
|
||||
iconResId = R.drawable.ic_information_24,
|
||||
iconClick = iconClick,
|
||||
)
|
||||
}
|
||||
// region preview
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
|
|
|
|||
|
|
@ -1866,7 +1866,6 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private const val INCREASE_GAS_LIMIT_BY = 112 // 12%
|
||||
private const val INCREASE_GAS_LIMIT_FOR_SEND = 105 // 5%
|
||||
private const val INFINITY_SYMBOL = "∞"
|
||||
|
|
|
|||
|
|
@ -847,7 +847,6 @@ internal class SwapViewModel @Inject constructor(
|
|||
onAmountChanged(newAmount.formatToUIRepresentation())
|
||||
}
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private fun onAmountSelected(selected: Boolean) {
|
||||
if (selected) {
|
||||
analyticsEventHandler.send(SwapEvents.SendTokenBalanceClicked)
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ internal sealed class TokenDetailsActionButton(val config: ActionButtonConfig) {
|
|||
data class Stake(val dimContent: Boolean, override val onClick: () -> Unit) : TokenDetailsActionButton(
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(id = R.string.common_stake),
|
||||
iconResId = R.drawable.ic_arrow_down_24, // TODO staking
|
||||
iconResId = R.drawable.ic_staking_24,
|
||||
onClick = onClick,
|
||||
dimContent = dimContent,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -393,7 +393,10 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
|
||||
internalUiState.value = stateFactory.getStateWithUpdatedStakingAvailability(stakingAvailability)
|
||||
if (stakingAvailability is StakingAvailability.Available) {
|
||||
val stakingInfo = getStakingEntryInfoUseCase(stakingAvailability.integrationId)
|
||||
val stakingInfo = getStakingEntryInfoUseCase(
|
||||
cryptoCurrencyId = cryptoCurrency.id,
|
||||
symbol = cryptoCurrency.symbol,
|
||||
)
|
||||
internalUiState.value = stateFactory.getStateWithStaking(stakingInfo)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ internal sealed class WalletManageButton(val config: ActionButtonConfig) {
|
|||
) : WalletManageButton(
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(id = R.string.common_stake),
|
||||
iconResId = R.drawable.ic_arrow_down_24, // TODO staking
|
||||
iconResId = R.drawable.ic_staking_24,
|
||||
onClick = onClick,
|
||||
dimContent = dimContent,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ internal class MultiWalletCurrencyActionsConverter(
|
|||
}
|
||||
is TokenActionsState.ActionState.Stake -> {
|
||||
title = resourceReference(R.string.common_stake)
|
||||
icon = R.drawable.ic_arrow_down_24 // TODO staking replace icon
|
||||
icon = R.drawable.ic_staking_24
|
||||
action = { clickIntents.onStakeClick(cryptoCurrencyStatus) }
|
||||
}
|
||||
is TokenActionsState.ActionState.Sell -> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue