Updated on 2026-08-14
This commit is contained in:
parent
db9990920e
commit
4dc4053869
12 changed files with 231 additions and 127 deletions
|
|
@ -20,6 +20,7 @@ import androidx.compose.ui.text.TextStyle
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -95,8 +96,7 @@ enum class CornersToRound {
|
|||
|
||||
@Suppress("TopLevelComposableFunctions")
|
||||
@Composable
|
||||
fun getShape(): RoundedCornerShape {
|
||||
val radius = TangemTheme.dimens.radius12
|
||||
fun getShape(radius: Dp = TangemTheme.dimens.radius12): RoundedCornerShape {
|
||||
return when (this) {
|
||||
ALL_4 -> RoundedCornerShape(radius)
|
||||
TOP_2 -> RoundedCornerShape(topStart = radius, topEnd = radius)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import javax.inject.Singleton
|
|||
|
||||
@Singleton
|
||||
internal class StakingStateController @Inject constructor(
|
||||
private val urlOpener: UrlOpener,
|
||||
urlOpener: UrlOpener,
|
||||
) {
|
||||
|
||||
val value: StakingUiState get() = uiState.value
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ 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.core.ui.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType
|
||||
|
|
@ -62,6 +63,7 @@ internal sealed class StakingStates {
|
|||
val aprRange: TextReference,
|
||||
val onInfoClick: (InfoType) -> Unit,
|
||||
val yieldBalance: InnerYieldBalanceState,
|
||||
val pullToRefreshConfig: PullToRefreshConfig,
|
||||
) : InitialInfoState()
|
||||
|
||||
data class Empty(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ 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.core.ui.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.domain.staking.model.stakekit.BalanceType
|
||||
import com.tangem.domain.staking.model.stakekit.RewardBlockType
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
|
|
@ -57,6 +58,7 @@ internal object InitialStakingStatePreview {
|
|||
),
|
||||
onInfoClick = {},
|
||||
yieldBalance = InnerYieldBalanceState.Empty,
|
||||
pullToRefreshConfig = PullToRefreshConfig(isRefreshing = false, onRefresh = {}),
|
||||
)
|
||||
|
||||
val stateWithYield = defaultState.copy(
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ internal object StakingClickIntentsStub : StakingClickIntents {
|
|||
|
||||
override fun onPrevClick() {}
|
||||
|
||||
override fun onRefreshSwipe(isRefreshing: Boolean) {}
|
||||
|
||||
override fun onInitialInfoBannerClick() {}
|
||||
|
||||
override fun onInfoClick(infoType: InfoType) {}
|
||||
|
|
@ -59,7 +61,8 @@ internal object StakingClickIntentsStub : StakingClickIntents {
|
|||
reduceAmountBy: BigDecimal,
|
||||
reduceAmountByDiff: BigDecimal,
|
||||
notification: Class<out NotificationUM>,
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onAmountReduceToClick(reduceAmountTo: BigDecimal, notification: Class<out NotificationUM>) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ 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.*
|
||||
import com.tangem.core.ui.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.core.serialization.SerializedBigDecimal
|
||||
|
|
@ -14,10 +15,6 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.*
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.features.staking.impl.presentation.state.TransactionDoneState
|
||||
import com.tangem.features.staking.impl.presentation.state.ValidatorState
|
||||
import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType
|
||||
import com.tangem.features.staking.impl.presentation.state.converters.RewardsValidatorStateConverter
|
||||
import com.tangem.features.staking.impl.presentation.state.converters.YieldBalancesConverter
|
||||
|
|
@ -88,6 +85,10 @@ internal class SetInitialDataStateTransformer(
|
|||
infoItems = getInfoItems(),
|
||||
onInfoClick = clickIntents::onInfoClick,
|
||||
yieldBalance = yieldBalance,
|
||||
pullToRefreshConfig = PullToRefreshConfig(
|
||||
onRefresh = { clickIntents.onRefreshSwipe(it.value) },
|
||||
isRefreshing = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class SetInitialLoadingStateTransformer(
|
||||
private val isRefreshing: Boolean,
|
||||
) : Transformer<StakingUiState> {
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val initialState = prevState.initialInfoState as? StakingStates.InitialInfoState.Data
|
||||
return prevState.copy(
|
||||
initialInfoState = initialState?.copy(
|
||||
pullToRefreshConfig = prevState.initialInfoState.pullToRefreshConfig.copy(
|
||||
isRefreshing = isRefreshing,
|
||||
),
|
||||
) ?: prevState.initialInfoState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,11 +8,16 @@ import androidx.compose.foundation.clickable
|
|||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.pullRefresh
|
||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -35,7 +40,9 @@ import com.tangem.core.ui.components.SpacerH12
|
|||
import com.tangem.core.ui.components.inputrow.InputRowDefault
|
||||
import com.tangem.core.ui.components.inputrow.InputRowImageInfo
|
||||
import com.tangem.core.ui.components.list.roundedListWithDividersItems
|
||||
import com.tangem.core.ui.components.rows.CornersToRound
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -52,14 +59,13 @@ import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickInten
|
|||
import com.tangem.utils.StringsSigns.DOT
|
||||
import com.tangem.utils.StringsSigns.PLUS
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
private const val BANNER_BLOCK_KEY = "BannerBlock"
|
||||
private const val STAKING_REWARD_BLOCK_KEY = "StakingRewardBlock"
|
||||
private const val ACTIVE_STAKING_BLOCK_KEY = "ActiveStakingBlock"
|
||||
private const val STAKE_PRIMARY_BUTTON_KEY = "StakePrimaryButton"
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
internal fun StakingInitialInfoContent(
|
||||
state: StakingStates.InitialInfoState,
|
||||
|
|
@ -69,60 +75,116 @@ internal fun StakingInitialInfoContent(
|
|||
) {
|
||||
if (state !is StakingStates.InitialInfoState.Data) return
|
||||
|
||||
LazyColumn(
|
||||
verticalArrangement = alignLastToBottom(),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
if (state.showBanner) {
|
||||
item(key = BANNER_BLOCK_KEY) {
|
||||
Column(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
) {
|
||||
BannerBlock(onClick = clickIntents::onInitialInfoBannerClick)
|
||||
SpacerH12()
|
||||
val pullRefreshState = rememberPullRefreshState(
|
||||
refreshing = state.pullToRefreshConfig.isRefreshing,
|
||||
onRefresh = { state.pullToRefreshConfig.onRefresh(PullToRefreshConfig.ShowRefreshState()) },
|
||||
)
|
||||
Box(modifier = Modifier.pullRefresh(pullRefreshState)) {
|
||||
LazyColumn(
|
||||
verticalArrangement = alignLastToBottom(),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
if (state.showBanner) {
|
||||
item(key = BANNER_BLOCK_KEY) {
|
||||
Column(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
) {
|
||||
BannerBlock(onClick = clickIntents::onInitialInfoBannerClick)
|
||||
SpacerH12()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.roundedListWithDividersItems(
|
||||
rows = state.infoItems,
|
||||
footerContent = { SpacerH12() },
|
||||
hideEndText = isBalanceHidden,
|
||||
)
|
||||
|
||||
if (state.yieldBalance is InnerYieldBalanceState.Data) {
|
||||
item(key = STAKING_REWARD_BLOCK_KEY) {
|
||||
Column(modifier = Modifier.animateItemPlacement()) {
|
||||
StakingRewardBlock(
|
||||
rewardCrypto = state.yieldBalance.rewardsCrypto,
|
||||
rewardFiat = state.yieldBalance.rewardsFiat,
|
||||
rewardBlockType = state.yieldBalance.rewardBlockType,
|
||||
onRewardsClick = clickIntents::openRewardsValidators,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
SpacerH12()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activeStakingBlock(
|
||||
state = state,
|
||||
clickIntents = clickIntents,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
|
||||
item(STAKE_PRIMARY_BUTTON_KEY) {
|
||||
SpacerH12()
|
||||
StakeButtonBlock(buttonState)
|
||||
}
|
||||
}
|
||||
|
||||
this.roundedListWithDividersItems(
|
||||
rows = state.infoItems,
|
||||
footerContent = { SpacerH12() },
|
||||
hideEndText = isBalanceHidden,
|
||||
PullRefreshIndicator(
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
refreshing = state.pullToRefreshConfig.isRefreshing,
|
||||
state = pullRefreshState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (state.yieldBalance is InnerYieldBalanceState.Data) {
|
||||
item(key = STAKING_REWARD_BLOCK_KEY) {
|
||||
Column(modifier = Modifier.animateItemPlacement()) {
|
||||
StakingRewardBlock(
|
||||
rewardCrypto = state.yieldBalance.rewardsCrypto,
|
||||
rewardFiat = state.yieldBalance.rewardsFiat,
|
||||
rewardBlockType = state.yieldBalance.rewardBlockType,
|
||||
onRewardsClick = clickIntents::openRewardsValidators,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
SpacerH12()
|
||||
}
|
||||
}
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
private fun LazyListScope.activeStakingBlock(
|
||||
state: StakingStates.InitialInfoState.Data,
|
||||
clickIntents: StakingClickIntents,
|
||||
isBalanceHidden: Boolean,
|
||||
) {
|
||||
if (state.yieldBalance is InnerYieldBalanceState.Data) {
|
||||
item(ACTIVE_STAKING_BLOCK_KEY) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.staking_your_stakes),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(CornersToRound.TOP_2.getShape())
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing4,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if (state.yieldBalance is InnerYieldBalanceState.Data) {
|
||||
item(key = ACTIVE_STAKING_BLOCK_KEY) {
|
||||
Column(modifier = Modifier.animateItemPlacement()) {
|
||||
ActiveStakingBlock(
|
||||
balances = state.yieldBalance.balance,
|
||||
onClick = clickIntents::onActiveStake,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
SpacerH12()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item(STAKE_PRIMARY_BUTTON_KEY) {
|
||||
StakeButtonBlock(buttonState)
|
||||
items(
|
||||
items = state.yieldBalance.balance,
|
||||
key = {
|
||||
// Staked balance does not have unique identifier.
|
||||
// Balance type and group id is used to identify item.
|
||||
it.id + it.type
|
||||
},
|
||||
) { balance ->
|
||||
ActiveStakingBlock(
|
||||
balance = balance,
|
||||
onClick = clickIntents::onActiveStake,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier
|
||||
.animateItemPlacement()
|
||||
.then(
|
||||
if (state.yieldBalance.balance.last() == balance) {
|
||||
Modifier.clip(CornersToRound.BOTTOM_2.getShape())
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -205,49 +267,29 @@ private fun StakingRewardBlock(
|
|||
|
||||
@Composable
|
||||
private fun ActiveStakingBlock(
|
||||
balances: ImmutableList<BalanceState>,
|
||||
balance: BalanceState,
|
||||
onClick: (BalanceState) -> Unit,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.staking_your_stakes),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.padding(
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing4,
|
||||
val (icon, iconTint) = balance.type.getIcon()
|
||||
InputRowImageInfo(
|
||||
subtitle = balance.title,
|
||||
caption = balance.subtitle ?: balance.getAprText(),
|
||||
infoTitle = balance.fiatAmount.orMaskWithStars(isBalanceHidden),
|
||||
infoSubtitle = balance.cryptoAmount.orMaskWithStars(isBalanceHidden),
|
||||
imageUrl = balance.getImage(),
|
||||
iconRes = icon,
|
||||
iconTint = iconTint,
|
||||
modifier = modifier
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = balance.isClickable,
|
||||
onClick = { onClick(balance) },
|
||||
),
|
||||
)
|
||||
balances.forEach { balance ->
|
||||
key(balance.id) {
|
||||
val (icon, iconTint) = balance.type.getIcon()
|
||||
InputRowImageInfo(
|
||||
subtitle = balance.title,
|
||||
caption = balance.subtitle ?: balance.getAprText(),
|
||||
isGrayscaleImage = !balance.isClickable,
|
||||
infoTitle = balance.fiatAmount.orMaskWithStars(isBalanceHidden),
|
||||
infoSubtitle = balance.cryptoAmount.orMaskWithStars(isBalanceHidden),
|
||||
imageUrl = balance.getImage(),
|
||||
iconRes = icon,
|
||||
iconTint = iconTint,
|
||||
modifier = Modifier.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = balance.isClickable,
|
||||
onClick = { onClick(balance) },
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ internal interface StakingClickIntents : AmountScreenClickIntents {
|
|||
|
||||
fun onPrevClick()
|
||||
|
||||
fun onRefreshSwipe(isRefreshing: Boolean)
|
||||
|
||||
fun onInitialInfoBannerClick()
|
||||
|
||||
fun onInfoClick(infoType: InfoType)
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
private val stateController: StakingStateController,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
|
|
@ -149,6 +149,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
private val transactionsInProgress: CopyOnWriteArrayList<StakingTransaction> = CopyOnWriteArrayList()
|
||||
|
||||
private var approvalJobHolder: JobHolder = JobHolder()
|
||||
private var updateBalancesJobHolder: JobHolder = JobHolder()
|
||||
|
||||
init {
|
||||
subscribeOnSelectedAppCurrency()
|
||||
|
|
@ -156,6 +157,12 @@ internal class StakingViewModel @Inject constructor(
|
|||
subscribeOnCurrencyStatusUpdates()
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
updateBalancesJobHolder.cancel()
|
||||
approvalJobHolder.cancel()
|
||||
}
|
||||
|
||||
override fun onBackClick() {
|
||||
stakingStateRouter.onBackClick()
|
||||
}
|
||||
|
|
@ -173,7 +180,10 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
stakingStateRouter.onNextClick()
|
||||
when {
|
||||
isInitState() -> stateController.update(SetConfirmationStateLoadingTransformer(yield, appCurrency))
|
||||
isInitState() -> {
|
||||
stateController.update(SetConfirmationStateLoadingTransformer(yield, appCurrency))
|
||||
onRefreshSwipe(isRefreshing = false)
|
||||
}
|
||||
isAssentState() -> getFee(pendingAction)
|
||||
}
|
||||
}
|
||||
|
|
@ -364,6 +374,19 @@ internal class StakingViewModel @Inject constructor(
|
|||
stakingStateRouter.onPrevClick()
|
||||
}
|
||||
|
||||
override fun onRefreshSwipe(isRefreshing: Boolean) {
|
||||
stateController.update(SetInitialLoadingStateTransformer(isRefreshing))
|
||||
viewModelScope.launch {
|
||||
val balancesUpdate = async { updateStakeBalance() }
|
||||
val networkUpdate = async { updateNetworkStatuses(0) }
|
||||
|
||||
awaitAll(balancesUpdate, networkUpdate)
|
||||
}.saveIn(updateBalancesJobHolder)
|
||||
.invokeOnCompletion {
|
||||
stateController.update(SetInitialLoadingStateTransformer(false))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInitialInfoBannerClick() {
|
||||
innerRouter.openUrl(WHAT_IS_STAKING_ARTICLE_URL)
|
||||
}
|
||||
|
|
@ -711,33 +734,42 @@ internal class StakingViewModel @Inject constructor(
|
|||
stateController.update(SetConfirmationStateResetAssentTransformer)
|
||||
},
|
||||
)
|
||||
getCryptoCurrencyStatusSyncUseCase(userWalletId, cryptoCurrencyId).fold(
|
||||
ifRight = {
|
||||
feeCryptoCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase(userWalletId, it).getOrNull()
|
||||
val isAnyTokenStaked = isAnyTokenStakedUseCase(userWalletId).getOrNull() ?: false
|
||||
cryptoCurrencyStatus = it
|
||||
getCurrencyStatusUpdatesUseCase(userWalletId, cryptoCurrencyId, false)
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
.filter { value.currentStep == StakingStep.InitialInfo }
|
||||
.onEach { maybeStatus ->
|
||||
maybeStatus.fold(
|
||||
ifRight = { status ->
|
||||
feeCryptoCurrencyStatus =
|
||||
getFeePaidCryptoCurrencyStatusSyncUseCase(userWalletId, status).getOrNull()
|
||||
cryptoCurrencyStatus = status
|
||||
val isAnyTokenStaked = isAnyTokenStakedUseCase(userWalletId).getOrNull() ?: false
|
||||
|
||||
setupApprovalNeeded()
|
||||
checkIfSubtractAvailable()
|
||||
setupApprovalNeeded()
|
||||
checkIfSubtractAvailable()
|
||||
|
||||
stateController.update(
|
||||
transformer = SetInitialDataStateTransformer(
|
||||
clickIntents = this@StakingViewModel,
|
||||
yield = yield,
|
||||
isApprovalNeeded = stakingApproval is StakingApproval.Needed,
|
||||
isAnyTokenStaked = isAnyTokenStaked,
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
userWalletProvider = Provider { userWallet },
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
),
|
||||
stateController.update(
|
||||
transformer = SetInitialDataStateTransformer(
|
||||
clickIntents = this@StakingViewModel,
|
||||
yield = yield,
|
||||
isAnyTokenStaked = isAnyTokenStaked,
|
||||
isApprovalNeeded = stakingApproval is StakingApproval.Needed,
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
userWalletProvider = Provider { userWallet },
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
),
|
||||
)
|
||||
},
|
||||
ifLeft = { error ->
|
||||
Timber.e(error.toString())
|
||||
stakingEventFactory.createGenericErrorAlert(error.toString())
|
||||
stateController.update(SetConfirmationStateResetAssentTransformer)
|
||||
},
|
||||
)
|
||||
},
|
||||
ifLeft = {
|
||||
Timber.e(it.toString())
|
||||
stakingEventFactory.createGenericErrorAlert(it.toString())
|
||||
stateController.update(SetConfirmationStateResetAssentTransformer)
|
||||
},
|
||||
)
|
||||
}
|
||||
.flowOn(dispatchers.main)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -850,11 +882,11 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun updateNetworkStatuses() {
|
||||
private suspend fun updateNetworkStatuses(delay: Long = BALANCE_UPDATE_DELAY) {
|
||||
updateDelayedNetworkStatusUseCase(
|
||||
userWalletId = userWalletId,
|
||||
network = cryptoCurrencyStatus.currency.network,
|
||||
delayMillis = BALANCE_UPDATE_DELAY,
|
||||
delayMillis = delay,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,6 @@ internal class TokenDetailsSkeletonStateConverter(
|
|||
|
||||
private fun createPullToRefresh(): PullToRefreshConfig = PullToRefreshConfig(
|
||||
isRefreshing = false,
|
||||
onRefresh = { clickIntents.onRefreshSwipe(it.value) } ,
|
||||
onRefresh = { clickIntents.onRefreshSwipe(it.value) },
|
||||
)
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ internal fun TokenDetailsScreen(state: TokenDetailsState, tokenMarketBlockCompon
|
|||
) { scaffoldPaddings ->
|
||||
val pullRefreshState = rememberPullRefreshState(
|
||||
refreshing = state.pullToRefreshConfig.isRefreshing,
|
||||
onRefresh = { state.pullToRefreshConfig.onRefresh(PullToRefreshConfig.ShowRefreshState()) } ,
|
||||
onRefresh = { state.pullToRefreshConfig.onRefresh(PullToRefreshConfig.ShowRefreshState()) },
|
||||
)
|
||||
|
||||
val txHistoryItems = if (state.txHistoryState is TxHistoryState.Content) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue