Updated on 2026-08-14
This commit is contained in:
parent
60258b3096
commit
fa948bd91a
28 changed files with 651 additions and 83 deletions
|
|
@ -30,4 +30,7 @@ dependencies {
|
|||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(deps.tangem.blockchain) {
|
||||
exclude(module = "joda-time")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package com.tangem.common.ui.amountScreen.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
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.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.core.ui.components.ResizableText
|
||||
import com.tangem.core.ui.components.currency.tokenicon.TokenIcon
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
|
||||
@Composable
|
||||
fun AmountBlock(amountState: AmountState, isClickDisabled: Boolean, isEditingDisabled: Boolean, onClick: () -> Unit) {
|
||||
if (amountState !is AmountState.Data) return
|
||||
val amount = amountState.amountTextField
|
||||
|
||||
val cryptoAmount = BigDecimalFormatter.formatWithSymbol(amount.value, amount.cryptoAmount.currencySymbol)
|
||||
val fiatAmount = BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = amount.fiatAmount.value,
|
||||
fiatCurrencySymbol = amount.fiatAmount.currencySymbol,
|
||||
fiatCurrencyCode = amountState.appCurrencyCode,
|
||||
)
|
||||
val backgroundColor = if (isEditingDisabled) {
|
||||
TangemTheme.colors.button.disabled
|
||||
} else {
|
||||
TangemTheme.colors.background.action
|
||||
}
|
||||
|
||||
val (firstAmount, secondAmount) = if (amount.isFiatValue) {
|
||||
fiatAmount to cryptoAmount
|
||||
} else {
|
||||
cryptoAmount to fiatAmount
|
||||
}
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(backgroundColor)
|
||||
.clickable(enabled = !isClickDisabled && !isEditingDisabled, onClick = onClick)
|
||||
.padding(TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
TokenIcon(state = amountState.tokenIconState)
|
||||
ResizableText(
|
||||
text = firstAmount,
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = TangemTheme.dimens.spacing24),
|
||||
)
|
||||
Text(
|
||||
text = secondAmount,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = TangemTheme.dimens.spacing8),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun AmountBlockPreview(@PreviewParameter(AmountBlockPreviewProvider::class) value: AmountState) {
|
||||
TangemThemePreview {
|
||||
AmountBlock(
|
||||
amountState = value,
|
||||
isClickDisabled = false,
|
||||
isEditingDisabled = false,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class AmountBlockPreviewProvider : PreviewParameterProvider<AmountState> {
|
||||
override val values: Sequence<AmountState>
|
||||
get() = sequenceOf(
|
||||
AmountStatePreviewData.amountState,
|
||||
)
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.features.send.impl.presentation.utils
|
||||
package com.tangem.common.ui.amountScreen.utils
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
|
@ -11,7 +11,7 @@ import java.math.BigDecimal
|
|||
|
||||
private const val CRYPTO_FEE_DECIMALS = 6
|
||||
|
||||
internal fun getCryptoReference(amount: Amount?, isFeeApproximate: Boolean): TextReference? {
|
||||
fun getCryptoReference(amount: Amount?, isFeeApproximate: Boolean): TextReference? {
|
||||
if (amount == null) return null
|
||||
return combinedReference(
|
||||
if (isFeeApproximate) stringReference("${BigDecimalFormatter.CAN_BE_LOWER_SIGN} ") else TextReference.EMPTY,
|
||||
|
|
@ -25,13 +25,13 @@ internal fun getCryptoReference(amount: Amount?, isFeeApproximate: Boolean): Tex
|
|||
)
|
||||
}
|
||||
|
||||
internal fun getFiatReference(value: BigDecimal?, rate: BigDecimal?, appCurrency: AppCurrency): TextReference? {
|
||||
fun getFiatReference(value: BigDecimal?, rate: BigDecimal?, appCurrency: AppCurrency): TextReference? {
|
||||
if (value == null || rate == null) return null
|
||||
val formattedFiat = getFiatString(value = value, rate = rate, appCurrency = appCurrency)
|
||||
return stringReference(formattedFiat)
|
||||
}
|
||||
|
||||
internal fun getFiatString(value: BigDecimal?, rate: BigDecimal?, appCurrency: AppCurrency): String {
|
||||
fun getFiatString(value: BigDecimal?, rate: BigDecimal?, appCurrency: AppCurrency): String {
|
||||
if (value == null || rate == null) return EMPTY_BALANCE_SIGN
|
||||
val feeValue = value.multiply(rate)
|
||||
return BigDecimalFormatter.formatFiatAmount(
|
||||
|
|
@ -543,6 +543,7 @@
|
|||
<string name="send_transaction_success">Транзакция успешно подписана и отправлена в блокчейн. Баланс будет обновлен через некоторое время</string>
|
||||
<string name="send_validation_invalid_address">Неверный адрес</string>
|
||||
<string name="sent_transaction_sent_title">Транзакция отправлена</string>
|
||||
<string name="settings_card_settings_footer">Подготовьтесь к сканированию карты, которую вы хотите настроить.</string>
|
||||
<string name="settings_forget_wallet">Забыть кошелек</string>
|
||||
<string name="settings_forget_wallet_footer">Это приведет к удалению кошелька из приложения. Сам кошелек можно добавить снова.</string>
|
||||
<string name="settings_wallet_name_title">Имя</string>
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@
|
|||
<string name="common_origin_card">Primary Card</string>
|
||||
<string name="common_passphrase">Passphrase</string>
|
||||
<string name="common_paste">Paste</string>
|
||||
<string name="common_percent_range" formatted="false">%1$s-%2$s</string>
|
||||
<string name="common_range">%1$s-%2$s</string>
|
||||
<string name="common_read_more">Read more</string>
|
||||
<string name="common_receive">Receive</string>
|
||||
<string name="common_reject">Reject</string>
|
||||
|
|
@ -310,7 +310,12 @@
|
|||
<string name="manage_tokens_unavailable_vote">Upvote</string>
|
||||
<string name="manage_tokens_wallet_selector_title">Choose wallet</string>
|
||||
<string name="manage_tokens_wallet_support_only_one_network_title">The wallet doesn\'t support more than one network</string>
|
||||
<string name="markets_add_to_my_portfolio_description">To start buying, exchanging or receiving this asset, add this token to at least 1 network</string>
|
||||
<string name="markets_add_to_my_portfolio_unavailable_description">This asset is not available</string>
|
||||
<string name="markets_add_to_portfolio_button">Add to portfolio</string>
|
||||
<string name="markets_common_my_portfolio">My portfolio</string>
|
||||
<string name="markets_common_title">Market</string>
|
||||
<string name="markets_select_wallet">Select wallet</string>
|
||||
<string name="markets_sort_by_title">Sort By</string>
|
||||
<string name="onboarding_access_code_feature_1_description">You have to set up a single access code to protect all your cards</string>
|
||||
<string name="onboarding_access_code_feature_1_title">Protect</string>
|
||||
|
|
@ -541,6 +546,7 @@
|
|||
<string name="send_validation_invalid_address">Invalid address</string>
|
||||
<string name="send_wallet_balance_format">%1$s (%2$s)</string>
|
||||
<string name="sent_transaction_sent_title">Transaction sent</string>
|
||||
<string name="settings_card_settings_footer">Prepare to scan card you want to setup.</string>
|
||||
<string name="settings_forget_wallet">Forget wallet</string>
|
||||
<string name="settings_forget_wallet_footer">This will remove the wallet from the application. The wallet itself can be added again.</string>
|
||||
<string name="settings_wallet_name_title">Name</string>
|
||||
|
|
@ -559,7 +565,10 @@
|
|||
<string name="staking_details_title">Staking %s</string>
|
||||
<string name="staking_details_unbonding_period">Unbonding Period</string>
|
||||
<string name="staking_details_warmup_period">Warmup period</string>
|
||||
<string name="staking_notification_earn_rewards_text" formatted="false">Staking allow you to earn %1s. Your staking rewards arrive every ~%2s days.</string>
|
||||
<string name="staking_notification_earn_rewards_title">Earn staking rewards</string>
|
||||
<string name="staking_rewards">Rewards</string>
|
||||
<string name="staking_validator">Validator</string>
|
||||
<string name="story_awe_description">Store your crypto assets secure while keeping private keys contained in your card</string>
|
||||
<string name="story_awe_title">Revolutionary Hardware Wallet</string>
|
||||
<string name="story_backup_description">Up to 3 physical cards to one wallet</string>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.blockchain.common.transaction.Fee
|
|||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.blockchainsdk.utils.minimalAmount
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatString
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.extensions.networkIconResId
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
|
|
@ -25,7 +26,6 @@ import com.tangem.features.send.impl.presentation.analytics.SendAnalyticEvents
|
|||
import com.tangem.features.send.impl.presentation.state.*
|
||||
import com.tangem.features.send.impl.presentation.state.fee.*
|
||||
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
|
||||
import com.tangem.features.send.impl.presentation.utils.getFiatString
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isTezos
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
|
|
@ -14,7 +15,6 @@ import com.tangem.features.send.impl.R
|
|||
import com.tangem.features.send.impl.presentation.state.StateRouter
|
||||
import com.tangem.features.send.impl.presentation.state.fee.checkExceedBalance
|
||||
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
|
||||
import com.tangem.features.send.impl.presentation.utils.getFiatReference
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isBitcoin
|
||||
import com.tangem.utils.Provider
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
|
|
@ -14,7 +15,6 @@ import com.tangem.features.send.impl.R
|
|||
import com.tangem.features.send.impl.presentation.state.StateRouter
|
||||
import com.tangem.features.send.impl.presentation.state.fee.checkExceedBalance
|
||||
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
|
||||
import com.tangem.features.send.impl.presentation.utils.getFiatReference
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
|
||||
import com.tangem.utils.Provider
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import androidx.compose.ui.platform.LocalHapticFeedback
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.tangem.common.ui.amountScreen.utils.getCryptoReference
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatString
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.Keyboard
|
||||
import com.tangem.core.ui.components.SecondaryButtonIconStart
|
||||
|
|
@ -32,12 +34,9 @@ import com.tangem.core.ui.components.keyboardAsState
|
|||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.tokens.model.Amount
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiCurrentScreen
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiState
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiStateType
|
||||
import com.tangem.features.send.impl.presentation.utils.getFiatString
|
||||
import com.tangem.features.send.impl.presentation.utils.getCryptoReference
|
||||
|
||||
@Composable
|
||||
internal fun SendNavigationButtons(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.common.ui.amountScreen.utils.getCryptoReference
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.rows.SelectorRowItem
|
||||
|
|
@ -20,8 +22,6 @@ import com.tangem.core.ui.utils.parseToBigDecimal
|
|||
import com.tangem.features.send.impl.presentation.state.SendStates
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeType
|
||||
import com.tangem.features.send.impl.presentation.utils.getCryptoReference
|
||||
import com.tangem.features.send.impl.presentation.utils.getFiatReference
|
||||
|
||||
@Composable
|
||||
internal fun SendSpeedSelectorItem(
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ 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.common.ui.amountScreen.utils.getCryptoReference
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.rows.SelectorRowItem
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -24,8 +26,6 @@ import com.tangem.features.send.impl.presentation.state.SendStates
|
|||
import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeType
|
||||
import com.tangem.features.send.impl.presentation.state.previewdata.FeeStatePreviewData
|
||||
import com.tangem.features.send.impl.presentation.utils.getCryptoReference
|
||||
import com.tangem.features.send.impl.presentation.utils.getFiatReference
|
||||
|
||||
@Composable
|
||||
internal fun FeeBlock(feeState: SendStates.FeeState, isClickDisabled: Boolean, onClick: () -> Unit) {
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ dependencies {
|
|||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.transaction)
|
||||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.features.staking.impl.presentation.state
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
|
||||
@Immutable
|
||||
internal sealed class InnerFeeState {
|
||||
|
||||
data class Content(
|
||||
val fees: TransactionFee,
|
||||
) : InnerFeeState()
|
||||
|
||||
data object Loading : InnerFeeState()
|
||||
|
||||
data object Error : InnerFeeState()
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.features.staking.impl.presentation.state
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.domain.staking.model.Yield
|
||||
|
||||
@Immutable
|
||||
internal sealed class InnerValidatorState {
|
||||
|
||||
data class Content(
|
||||
val chosenValidator: Yield.Validator,
|
||||
) : InnerValidatorState()
|
||||
|
||||
data object Loading : InnerValidatorState()
|
||||
|
||||
data object Error : InnerValidatorState()
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.features.staking.impl.presentation.state
|
||||
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.features.staking.impl.R
|
||||
|
||||
internal sealed class StakingNotification(val config: NotificationConfig) {
|
||||
|
||||
sealed class Error(
|
||||
title: TextReference,
|
||||
subtitle: TextReference,
|
||||
iconResId: Int = R.drawable.ic_alert_24,
|
||||
buttonState: NotificationConfig.ButtonsState? = null,
|
||||
onCloseClick: (() -> Unit)? = null,
|
||||
) : StakingNotification(
|
||||
config = NotificationConfig(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
iconResId = iconResId,
|
||||
buttonsState = buttonState,
|
||||
onCloseClick = onCloseClick,
|
||||
),
|
||||
) {
|
||||
// TODO staking
|
||||
}
|
||||
|
||||
sealed class Warning(
|
||||
title: TextReference,
|
||||
subtitle: TextReference,
|
||||
buttonsState: NotificationConfig.ButtonsState? = null,
|
||||
onCloseClick: (() -> Unit)? = null,
|
||||
) : StakingNotification(
|
||||
config = NotificationConfig(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
buttonsState = buttonsState,
|
||||
onCloseClick = onCloseClick,
|
||||
),
|
||||
) {
|
||||
data class EarnRewards(
|
||||
val currencyName: String,
|
||||
val days: Int,
|
||||
) : Warning(
|
||||
title = resourceReference(R.string.staking_notification_earn_rewards_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.staking_notification_earn_rewards_text,
|
||||
wrappedList(currencyName, days),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -39,7 +39,6 @@ internal class StakingStateController @Inject constructor() {
|
|||
currentStep = StakingStep.InitialInfo,
|
||||
initialInfoState = StakingStates.InitialInfoState.Empty(),
|
||||
amountState = AmountState.Empty(),
|
||||
validatorState = StakingStates.ValidatorState.Empty(),
|
||||
confirmStakingState = StakingStates.ConfirmStakingState.Empty(),
|
||||
isBalanceHidden = false,
|
||||
event = consumedEvent(),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.features.staking.impl.presentation.state
|
||||
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import kotlinx.coroutines.flow.update
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
internal class StakingStateRouter(
|
||||
|
|
@ -22,7 +21,7 @@ internal class StakingStateRouter(
|
|||
isSuccess -> popBackStack()
|
||||
else -> when (type) {
|
||||
StakingStep.Amount -> showInitial()
|
||||
StakingStep.ValidatorAndFee -> showAmount()
|
||||
StakingStep.Confirm -> showAmount()
|
||||
else -> popBackStack()
|
||||
}
|
||||
}
|
||||
|
|
@ -31,9 +30,9 @@ internal class StakingStateRouter(
|
|||
fun onNextClick() {
|
||||
when (stateController.uiState.value.currentStep) {
|
||||
StakingStep.InitialInfo -> showAmount()
|
||||
StakingStep.Amount -> showValidator()
|
||||
StakingStep.ValidatorAndFee -> showConfirm()
|
||||
StakingStep.Confirm -> onBackClick()
|
||||
StakingStep.Amount -> showConfirm()
|
||||
StakingStep.Confirm -> showSuccess()
|
||||
StakingStep.Success -> onBackClick()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,13 +51,13 @@ internal class StakingStateRouter(
|
|||
stateController.update { it.copy(currentStep = StakingStep.Amount) }
|
||||
}
|
||||
|
||||
fun showValidator() {
|
||||
stateController.update { it.copy(currentStep = StakingStep.ValidatorAndFee) }
|
||||
}
|
||||
|
||||
fun showConfirm() {
|
||||
stateController.update { it.copy(currentStep = StakingStep.Confirm) }
|
||||
}
|
||||
|
||||
fun showSuccess() {
|
||||
stateController.update { it.copy(currentStep = StakingStep.Success) }
|
||||
}
|
||||
|
||||
private fun getInitialState() = StakingStep.InitialInfo
|
||||
}
|
||||
|
|
@ -1,10 +1,15 @@
|
|||
package com.tangem.features.staking.impl.presentation.state
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.Yield
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Ui states of the staking screen
|
||||
|
|
@ -16,7 +21,6 @@ internal data class StakingUiState(
|
|||
val currentStep: StakingStep,
|
||||
val initialInfoState: StakingStates.InitialInfoState,
|
||||
val amountState: AmountState,
|
||||
val validatorState: StakingStates.ValidatorState,
|
||||
val confirmStakingState: StakingStates.ConfirmStakingState,
|
||||
val isBalanceHidden: Boolean,
|
||||
val event: StateEvent<StakingEvent>,
|
||||
|
|
@ -25,12 +29,10 @@ internal data class StakingUiState(
|
|||
fun copyWrapped(
|
||||
initialInfoState: StakingStates.InitialInfoState = this.initialInfoState,
|
||||
amountState: AmountState = this.amountState,
|
||||
validatorState: StakingStates.ValidatorState = this.validatorState,
|
||||
confirmStakingState: StakingStates.ConfirmStakingState = this.confirmStakingState,
|
||||
): StakingUiState = copy(
|
||||
initialInfoState = initialInfoState,
|
||||
amountState = amountState,
|
||||
validatorState = validatorState,
|
||||
confirmStakingState = confirmStakingState,
|
||||
)
|
||||
}
|
||||
|
|
@ -58,32 +60,14 @@ internal sealed class StakingStates {
|
|||
) : InitialInfoState()
|
||||
}
|
||||
|
||||
/** Validator state */
|
||||
sealed class ValidatorState : StakingStates() {
|
||||
data class Data(
|
||||
override val isPrimaryButtonEnabled: Boolean,
|
||||
) : ValidatorState()
|
||||
|
||||
data class Empty(
|
||||
override val isPrimaryButtonEnabled: Boolean = false,
|
||||
) : ValidatorState()
|
||||
}
|
||||
|
||||
/** Fee state */
|
||||
sealed class FeeState : StakingStates() {
|
||||
data class Data(
|
||||
override val isPrimaryButtonEnabled: Boolean,
|
||||
) : FeeState()
|
||||
|
||||
data class Empty(
|
||||
override val isPrimaryButtonEnabled: Boolean = false,
|
||||
) : FeeState()
|
||||
}
|
||||
|
||||
/** Confirm state */
|
||||
sealed class ConfirmStakingState : StakingStates() {
|
||||
data class Data(
|
||||
override val isPrimaryButtonEnabled: Boolean,
|
||||
val feeState: FeeState,
|
||||
val validatorState: ValidatorState,
|
||||
val notifications: ImmutableList<StakingNotification>,
|
||||
val footerText: String,
|
||||
val isSuccess: Boolean,
|
||||
val isStaking: Boolean,
|
||||
) : ConfirmStakingState()
|
||||
|
|
@ -92,11 +76,25 @@ internal sealed class StakingStates {
|
|||
override val isPrimaryButtonEnabled: Boolean = false,
|
||||
) : ConfirmStakingState()
|
||||
}
|
||||
|
||||
data class FeeState(
|
||||
val innerFeeState: InnerFeeState,
|
||||
val fee: Fee?,
|
||||
val rate: BigDecimal?,
|
||||
val isFeeConvertibleToFiat: Boolean,
|
||||
val appCurrency: AppCurrency,
|
||||
val isFeeApproximate: Boolean,
|
||||
)
|
||||
|
||||
data class ValidatorState(
|
||||
val validatorState: InnerValidatorState,
|
||||
val availableValidators: List<Yield.Validator>,
|
||||
)
|
||||
}
|
||||
|
||||
enum class StakingStep {
|
||||
InitialInfo,
|
||||
Amount,
|
||||
ValidatorAndFee,
|
||||
Confirm,
|
||||
Success,
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.previewdata
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType.Coin
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.Yield
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerFeeState
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerValidatorState
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingNotification
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal object ConfirmStakingStatePreviewData {
|
||||
|
||||
private val validatorList = listOf(
|
||||
Yield.Validator(
|
||||
address = "0xa6e768fef2d1af36c0cfdb276422e7881a83e951",
|
||||
status = "active",
|
||||
name = "Luganodes",
|
||||
image = "https://assets.stakek.it/validators/luganodes.png",
|
||||
apr = BigDecimal("0.054823398040640445"),
|
||||
commission = 0.1,
|
||||
stakedBalance = "355544384.45009977",
|
||||
website = "https://luganodes.com/",
|
||||
votingPower = 0.09778360195377911,
|
||||
preferred = true,
|
||||
),
|
||||
Yield.Validator(
|
||||
address = "0x35b1ca0f398905cf752e6fe122b51c88022fca32",
|
||||
status = "active",
|
||||
name = "InfStones",
|
||||
image = "https://assets.stakek.it/validators/infstones.png",
|
||||
apr = BigDecimal("0.057786472172836965"),
|
||||
commission = 0.05,
|
||||
stakedBalance = "12495684.05643019",
|
||||
website = "https://infstones.com/",
|
||||
votingPower = 0.0034366257754399774,
|
||||
preferred = true,
|
||||
),
|
||||
Yield.Validator(
|
||||
address = "0xd14a87025109013b0a2354a775cb335f926af65a",
|
||||
status = "active",
|
||||
name = "Kiln",
|
||||
image = "https://assets.stakek.it/validators/kiln.png",
|
||||
apr = BigDecimal("0.057786472172836965"),
|
||||
commission = 0.05,
|
||||
stakedBalance = "85400369.96393165",
|
||||
website = "https://infstones.com/",
|
||||
votingPower = 0.023487238579718264,
|
||||
preferred = true,
|
||||
),
|
||||
)
|
||||
|
||||
private val fee = Fee.Common(
|
||||
amount = Amount(
|
||||
currencySymbol = "MATIC",
|
||||
value = BigDecimal(0.159806),
|
||||
decimals = 18,
|
||||
type = Coin,
|
||||
),
|
||||
)
|
||||
|
||||
val confirmStakingState = StakingStates.ConfirmStakingState.Data(
|
||||
isPrimaryButtonEnabled = true,
|
||||
feeState = StakingStates.FeeState(
|
||||
innerFeeState = InnerFeeState.Content(TransactionFee.Single(fee)),
|
||||
fee = fee,
|
||||
rate = BigDecimal.ONE,
|
||||
appCurrency = AppCurrency.Default,
|
||||
isFeeApproximate = false,
|
||||
isFeeConvertibleToFiat = true,
|
||||
),
|
||||
validatorState = StakingStates.ValidatorState(
|
||||
validatorState = InnerValidatorState.Content(
|
||||
chosenValidator = validatorList[0],
|
||||
),
|
||||
availableValidators = validatorList,
|
||||
),
|
||||
footerText = "You stake \$715.11 and will be receiving ~\$35 monthly",
|
||||
notifications = persistentListOf(
|
||||
StakingNotification.Warning.EarnRewards(
|
||||
currencyName = "Solana",
|
||||
days = 2,
|
||||
),
|
||||
),
|
||||
isStaking = false,
|
||||
isSuccess = false,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.Yield
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmStakingStatePreviewData
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class SetConfirmStateDataStateTransformer(
|
||||
private val yield: Yield,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
private val isFeeApproximateUseCase: IsFeeApproximateUseCase,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
// TODO staking fill with real data
|
||||
return prevState.copy(
|
||||
confirmStakingState = ConfirmStakingStatePreviewData.confirmStakingState,
|
||||
)
|
||||
}
|
||||
|
||||
private fun isFeeApproximate(fee: Fee): Boolean {
|
||||
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
|
||||
return isFeeApproximateUseCase(
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
amountType = fee.amount.type,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ internal class SetInitialDataStateTransformer(
|
|||
if (maxApr - minApr < EQUALITY_THRESHOLD) {
|
||||
return stringReference("$formattedMinApr%")
|
||||
}
|
||||
return resourceReference(R.string.common_percent_range, wrappedList(formattedMinApr, formattedMaxApr))
|
||||
return resourceReference(R.string.common_range, wrappedList(formattedMinApr, formattedMaxApr))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
package com.tangem.features.staking.impl.presentation.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountBlock
|
||||
import com.tangem.core.ui.components.SpacerHMax
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmStakingStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.NotificationsBlock
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.StakingFeeBlock
|
||||
|
||||
@Composable
|
||||
internal fun StakingConfirmContent(amountState: AmountState, state: StakingStates.ConfirmStakingState) {
|
||||
if (state !is StakingStates.ConfirmStakingState.Data) return
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.tertiary)
|
||||
.padding(TangemTheme.dimens.spacing16)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
AmountBlock(
|
||||
amountState = amountState,
|
||||
isClickDisabled = true,
|
||||
isEditingDisabled = true,
|
||||
onClick = {},
|
||||
)
|
||||
StakingFeeBlock(feeState = state.feeState)
|
||||
NotificationsBlock(notifications = state.notifications)
|
||||
SpacerHMax()
|
||||
FooterText(text = state.footerText)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FooterText(text: String) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = text,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(widthDp = 360, showBackground = true)
|
||||
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview_StakingConfirmContent() {
|
||||
TangemThemePreview {
|
||||
Column(Modifier.background(TangemTheme.colors.background.primary)) {
|
||||
StakingConfirmContent(
|
||||
amountState = AmountStatePreviewData.amountState,
|
||||
state = ConfirmStakingStatePreviewData.confirmStakingState,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,8 +51,8 @@ private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier
|
|||
val isSuccess = (confirmState as? StakingStates.ConfirmStakingState.Data)?.isSuccess ?: false
|
||||
val isStaking = (confirmState as? StakingStates.ConfirmStakingState.Data)?.isStaking ?: false
|
||||
|
||||
val isButtonsVisible = uiState.currentStep != StakingStep.Confirm
|
||||
val isStakingState = uiState.currentStep == StakingStep.Confirm && !isSuccess && !isStaking
|
||||
val isButtonsVisible = uiState.currentStep != StakingStep.Success
|
||||
val isStakingState = uiState.currentStep == StakingStep.Success && !isSuccess && !isStaking
|
||||
|
||||
val (buttonTextId, buttonClick) = getButtonData(
|
||||
currentState = uiState,
|
||||
|
|
@ -103,8 +103,8 @@ private fun getButtonData(currentState: StakingUiState): Pair<Int, () -> Unit> {
|
|||
return when (currentState.currentStep) {
|
||||
StakingStep.InitialInfo,
|
||||
StakingStep.Amount,
|
||||
StakingStep.ValidatorAndFee,
|
||||
StakingStep.Confirm,
|
||||
StakingStep.Success,
|
||||
-> R.string.common_next to { currentState.clickIntents.onNextClick() }
|
||||
}
|
||||
}
|
||||
|
|
@ -113,7 +113,7 @@ private fun isButtonEnabled(uiState: StakingUiState): Boolean {
|
|||
return when (uiState.currentStep) {
|
||||
StakingStep.InitialInfo -> uiState.initialInfoState.isPrimaryButtonEnabled
|
||||
StakingStep.Amount -> uiState.amountState.isPrimaryButtonEnabled
|
||||
StakingStep.ValidatorAndFee -> uiState.validatorState.isPrimaryButtonEnabled
|
||||
StakingStep.Confirm -> uiState.confirmStakingState.isPrimaryButtonEnabled
|
||||
StakingStep.Success -> true
|
||||
}
|
||||
}
|
||||
|
|
@ -52,13 +52,13 @@ private fun SendAppBar(uiState: StakingUiState) {
|
|||
val titleRes = when (uiState.currentStep) {
|
||||
StakingStep.InitialInfo -> stringResource(id = R.string.common_stake)
|
||||
StakingStep.Amount -> stringResource(id = R.string.send_amount_label)
|
||||
StakingStep.ValidatorAndFee -> stringResource(id = R.string.common_stake)
|
||||
StakingStep.Confirm -> ""
|
||||
StakingStep.Confirm -> stringResource(id = R.string.common_stake)
|
||||
StakingStep.Success -> ""
|
||||
}
|
||||
val backIcon = when (uiState.currentStep) {
|
||||
StakingStep.Amount,
|
||||
StakingStep.ValidatorAndFee,
|
||||
StakingStep.Confirm,
|
||||
StakingStep.Success,
|
||||
-> {
|
||||
R.drawable.ic_close_24
|
||||
}
|
||||
|
|
@ -127,8 +127,9 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M
|
|||
isBalanceHiding = uiState.isBalanceHidden,
|
||||
clickIntents = uiState.clickIntents,
|
||||
)
|
||||
StakingStep.ValidatorAndFee -> StakingValidatorAndFeeContent(
|
||||
state = uiState.validatorState,
|
||||
StakingStep.Confirm -> StakingConfirmContent(
|
||||
amountState = uiState.amountState,
|
||||
state = uiState.confirmStakingState,
|
||||
)
|
||||
else -> TODO()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
package com.tangem.features.staking.impl.presentation.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
|
||||
@Composable
|
||||
internal fun StakingValidatorAndFeeContent(state: StakingStates.ValidatorState) {
|
||||
if (state !is StakingStates.ValidatorState.Data) return
|
||||
|
||||
// TODO staking
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.features.staking.impl.presentation.ui.block
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingNotification
|
||||
|
||||
@Composable
|
||||
internal fun NotificationsBlock(notifications: List<StakingNotification>) {
|
||||
notifications.forEach {
|
||||
Notification(config = it.config, iconTint = TangemTheme.colors.icon.accent)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
package com.tangem.features.staking.impl.presentation.ui.block
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
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.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.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.rows.SelectorRowItem
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.utils.getCryptoReference
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerFeeState
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Composable
|
||||
internal fun StakingFeeBlock(feeState: StakingStates.FeeState) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.common_network_fee_title),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing8),
|
||||
) {
|
||||
val feeAmount = feeState.fee?.amount
|
||||
val (title, icon) = R.string.common_fee_selector_option_market to R.drawable.ic_bird_24
|
||||
SelectorRowItem(
|
||||
titleRes = title,
|
||||
iconRes = icon,
|
||||
preDot = getCryptoReference(feeAmount, feeState.isFeeApproximate),
|
||||
postDot = if (feeState.isFeeConvertibleToFiat) {
|
||||
getFiatReference(feeAmount?.value, feeState.rate, feeState.appCurrency)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = feeAmount?.currencySymbol?.length,
|
||||
isSelected = true,
|
||||
showDivider = false,
|
||||
showSelectedAppearance = false,
|
||||
paddingValues = PaddingValues(),
|
||||
)
|
||||
FeeLoading(feeState.innerFeeState)
|
||||
FeeError(feeState.innerFeeState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.FeeLoading(feeSelectorState: InnerFeeState) {
|
||||
AnimatedContent(
|
||||
targetState = feeSelectorState,
|
||||
label = "Fee Loading State Change",
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
) {
|
||||
if (it == InnerFeeState.Loading) {
|
||||
RectangleShimmer(
|
||||
radius = TangemTheme.dimens.radius3,
|
||||
modifier = Modifier.size(
|
||||
height = TangemTheme.dimens.size12,
|
||||
width = TangemTheme.dimens.size90,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.FeeError(feeSelectorState: InnerFeeState) {
|
||||
AnimatedContent(
|
||||
targetState = feeSelectorState,
|
||||
label = "Fee Error State Change",
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
) {
|
||||
if (it == InnerFeeState.Error) {
|
||||
Text(
|
||||
text = BigDecimalFormatter.EMPTY_BALANCE_SIGN,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.body2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun FeeBlockPreview(@PreviewParameter(FeeBlockPreviewProvider::class) value: StakingStates.FeeState) {
|
||||
TangemThemePreview {
|
||||
StakingFeeBlock(
|
||||
feeState = value,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class FeeBlockPreviewProvider : PreviewParameterProvider<StakingStates.FeeState> {
|
||||
|
||||
override val values: Sequence<StakingStates.FeeState>
|
||||
get() = sequenceOf(
|
||||
feeState,
|
||||
)
|
||||
|
||||
private val fee = Fee.Common(
|
||||
amount = Amount(
|
||||
currencySymbol = "MATIC",
|
||||
value = BigDecimal(0.159806),
|
||||
decimals = 18,
|
||||
type = AmountType.Coin,
|
||||
),
|
||||
)
|
||||
|
||||
private val feeState = StakingStates.FeeState(
|
||||
innerFeeState = InnerFeeState.Content(TransactionFee.Single(normal = fee)),
|
||||
fee = fee,
|
||||
rate = BigDecimal.ONE,
|
||||
appCurrency = AppCurrency.Default,
|
||||
isFeeApproximate = false,
|
||||
isFeeConvertibleToFiat = true,
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
|
@ -15,14 +15,17 @@ import com.tangem.domain.staking.model.Yield
|
|||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.staking.impl.navigation.InnerStakingRouter
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStateController
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStateRouter
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStep
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.HideBalanceStateTransformer
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.SetConfirmStateDataStateTransformer
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.SetInitialDataStateTransformer
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.amount.AmountChangeStateTransformer
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.amount.AmountCurrencyChangeStateTransformer
|
||||
|
|
@ -45,6 +48,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val isFeeApproximateUseCase: IsFeeApproximateUseCase,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(), DefaultLifecycleObserver, StakingClickIntents {
|
||||
|
||||
|
|
@ -72,9 +76,10 @@ internal class StakingViewModel @Inject constructor(
|
|||
|
||||
private var innerRouter: InnerStakingRouter by Delegates.notNull()
|
||||
private var userWallet: UserWallet by Delegates.notNull()
|
||||
private val selectedAppCurrencyFlow: StateFlow<AppCurrency> = createSelectedAppCurrencyFlow()
|
||||
private var appCurrency: AppCurrency by Delegates.notNull()
|
||||
|
||||
init {
|
||||
subscribeOnSelectedAppCurrency()
|
||||
subscribeOnBalanceHiding()
|
||||
subscribeOnCurrencyStatusUpdates()
|
||||
}
|
||||
|
|
@ -85,6 +90,27 @@ internal class StakingViewModel @Inject constructor(
|
|||
|
||||
override fun onNextClick() {
|
||||
stakingStateRouter.onNextClick()
|
||||
when (value.currentStep) {
|
||||
StakingStep.Confirm -> {
|
||||
stateController.update(
|
||||
SetConfirmStateDataStateTransformer(
|
||||
yield = yield,
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
isFeeApproximateUseCase = isFeeApproximateUseCase,
|
||||
),
|
||||
)
|
||||
}
|
||||
StakingStep.InitialInfo -> {
|
||||
// TODO staking
|
||||
}
|
||||
StakingStep.Amount -> {
|
||||
// TODO staking
|
||||
}
|
||||
StakingStep.Success -> {
|
||||
// TODO staking
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPrevClick() {
|
||||
|
|
@ -131,7 +157,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
yield = yield,
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
userWalletProvider = Provider { userWallet },
|
||||
appCurrencyProvider = Provider { selectedAppCurrencyFlow.value },
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
@ -153,18 +179,14 @@ internal class StakingViewModel @Inject constructor(
|
|||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
private fun createSelectedAppCurrencyFlow(): StateFlow<AppCurrency> {
|
||||
return getSelectedAppCurrencyUseCase()
|
||||
private fun subscribeOnSelectedAppCurrency() {
|
||||
getSelectedAppCurrencyUseCase()
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
.map { maybeAppCurrency ->
|
||||
maybeAppCurrency.getOrElse { AppCurrency.Default }
|
||||
.onEach { maybeAppCurrency ->
|
||||
appCurrency = maybeAppCurrency.getOrElse { AppCurrency.Default }
|
||||
}
|
||||
.flowOn(dispatchers.main)
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = AppCurrency.Default,
|
||||
)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue