From cb9e07b46deecdcf19b77199cd253cc22e1e089c Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Sep 2024 19:15:51 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../list/RoundedListWithDividers.kt | 10 +- .../SetInitialDataStateTransformer.kt | 1 + .../viewmodel/StakingViewModel.kt | 135 +++++++++--------- 3 files changed, 78 insertions(+), 68 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/list/RoundedListWithDividers.kt b/core/ui/src/main/java/com/tangem/core/ui/components/list/RoundedListWithDividers.kt index 87640bcc2a..afa890cb01 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/list/RoundedListWithDividers.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/list/RoundedListWithDividers.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.R import com.tangem.core.ui.components.rows.CornersToRound @@ -64,6 +65,11 @@ fun LazyListScope.roundedListWithDividersItems( endText = row.endText.orMaskWithStars(hideEndText && row.isEndTextHideable).resolveReference(), cornersToRound = getCornersToRound(index, rows.size), iconClick = row.iconClick, + endTextColor = if (row.isEndTextHighlighted) { + TangemTheme.colors.text.accent + } else { + TangemTheme.colors.text.tertiary + }, showDivider = index < rows.lastIndex, ) } @@ -81,6 +87,7 @@ private fun InitialInfoContentRow( endText: String, cornersToRound: CornersToRound, showDivider: Boolean, + endTextColor: Color = TangemTheme.colors.text.tertiary, iconClick: (() -> Unit)? = null, ) { Box { @@ -89,7 +96,7 @@ private fun InitialInfoContentRow( startTextColor = TangemTheme.colors.text.primary1, startTextStyle = TangemTheme.typography.body2, endText = endText, - endTextColor = TangemTheme.colors.text.tertiary, + endTextColor = endTextColor, endTextStyle = TangemTheme.typography.body2, cornersToRound = cornersToRound, iconResId = R.drawable.ic_information_24, @@ -126,6 +133,7 @@ data class RoundedListWithDividersItemData( val id: Int, val startText: TextReference, val endText: TextReference, + val isEndTextHighlighted: Boolean = false, val iconClick: (() -> Unit)? = null, val isEndTextHideable: Boolean = false, ) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt index 58d6743dbd..c2a2c681a5 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt @@ -118,6 +118,7 @@ internal class SetInitialDataStateTransformer( startText = TextReference.Res(R.string.staking_details_annual_percentage_rate), endText = getAprRange(validators), iconClick = { clickIntents.onInfoClick(InfoType.ANNUAL_PERCENTAGE_RATE) }, + isEndTextHighlighted = true, ) } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt index e23576a2b7..cebace0c6e 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt @@ -66,6 +66,7 @@ import com.tangem.utils.coroutines.* import com.tangem.utils.extensions.isSingleItem import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber @@ -101,6 +102,7 @@ internal class StakingViewModel @Inject constructor( private val stakingFeeTransactionLoader: StakingFeeTransactionLoader.Factory, private val stakingBalanceUpdater: StakingBalanceUpdater.Factory, private val analyticsEventHandler: AnalyticsEventHandler, + @DelayedWork private val coroutineScope: CoroutineScope, savedStateHandle: SavedStateHandle, ) : ViewModel(), DefaultLifecycleObserver, StakingClickIntents { @@ -174,7 +176,8 @@ internal class StakingViewModel @Inject constructor( private val transactionsInProgress: CopyOnWriteArrayList = CopyOnWriteArrayList() private var approvalJobHolder: JobHolder = JobHolder() - private var updateBalancesJobHolder: JobHolder = JobHolder() + private var feeJobHolder: JobHolder = JobHolder() + private var sendTransactionJobHolder = JobHolder() init { subscribeOnSelectedAppCurrency() @@ -184,8 +187,9 @@ internal class StakingViewModel @Inject constructor( override fun onCleared() { super.onCleared() - updateBalancesJobHolder.cancel() approvalJobHolder.cancel() + feeJobHolder.cancel() + sendTransactionJobHolder.cancel() } override fun onBackClick() { @@ -258,7 +262,7 @@ internal class StakingViewModel @Inject constructor( updateNotifications() }, ) - } + }.saveIn(feeJobHolder) } private fun handleOnNextConfirmationClick() { @@ -287,7 +291,7 @@ internal class StakingViewModel @Inject constructor( stateController.update(SetConfirmationStateResetAssentTransformer) }, ) - } + }.saveIn(sendTransactionJobHolder) } } @@ -313,12 +317,11 @@ internal class StakingViewModel @Inject constructor( override fun onRefreshSwipe(isRefreshing: Boolean) { stateController.update(SetInitialLoadingStateTransformer(isRefreshing)) - viewModelScope.launch { + coroutineScope.launch { balanceUpdater.instantUpdate() - }.saveIn(updateBalancesJobHolder) - .invokeOnCompletion { - stateController.update(SetInitialLoadingStateTransformer(false)) - } + }.invokeOnCompletion { + stateController.update(SetInitialLoadingStateTransformer(false)) + } } override fun onInitialInfoBannerClick() { @@ -393,7 +396,7 @@ internal class StakingViewModel @Inject constructor( cryptoCurrencyStatus.currency.network.id.value, activeStake.pendingActions, ) - val isMultiplePendingActions = activeStake.pendingActions.isSingleItem().not() + val isMultiplePendingActions = activeStake.pendingActions.size > 1 if (isMultiplePendingActions && !isAllWithdrawActions) { stateController.update( ShowActionSelectorBottomSheetTransformer( @@ -701,65 +704,63 @@ internal class StakingViewModel @Inject constructor( } private fun subscribeOnCurrencyStatusUpdates() { - viewModelScope.launch { - getUserWalletUseCase(userWalletId).fold( - ifRight = { wallet -> - userWallet = wallet - }, - ifLeft = { - Timber.e(it.toString()) - stakingEventFactory.createGenericErrorAlert(it.toString()) - stateController.update(SetConfirmationStateResetAssentTransformer) - }, - ) - getCurrencyStatusUpdatesUseCase(userWalletId, cryptoCurrencyId, false) - .conflate() - .distinctUntilChanged() - .filter { value.currentStep == StakingStep.InitialInfo } - .onEach { maybeStatus -> - maybeStatus.fold( - ifRight = { status -> - if (!isInitialInfoAnalyticSent) { - isInitialInfoAnalyticSent = true - val balances = status.value.yieldBalance as? YieldBalance.Data - analyticsEventHandler.send( - StakingAnalyticsEvents.StakingInfoScreenOpened( - validatorsCount = balances?.getValidatorsCount() ?: 0, - token = status.currency.symbol, - ), - ) - } - - feeCryptoCurrencyStatus = - getFeePaidCryptoCurrencyStatusSyncUseCase(userWalletId, status).getOrNull() - cryptoCurrencyStatus = status - val isAnyTokenStaked = isAnyTokenStakedUseCase(userWalletId).getOrNull() ?: false - - setupApprovalNeeded() - checkIfSubtractAvailable() - - 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 }, + getUserWalletUseCase(userWalletId).fold( + ifRight = { wallet -> + userWallet = wallet + }, + ifLeft = { + Timber.e(it.toString()) + stakingEventFactory.createGenericErrorAlert(it.toString()) + stateController.update(SetConfirmationStateResetAssentTransformer) + }, + ) + getCurrencyStatusUpdatesUseCase(userWalletId, cryptoCurrencyId, false) + .conflate() + .distinctUntilChanged() + .filter { value.currentStep == StakingStep.InitialInfo } + .onEach { maybeStatus -> + maybeStatus.fold( + ifRight = { status -> + if (!isInitialInfoAnalyticSent) { + isInitialInfoAnalyticSent = true + val balances = status.value.yieldBalance as? YieldBalance.Data + analyticsEventHandler.send( + StakingAnalyticsEvents.StakingInfoScreenOpened( + validatorsCount = balances?.getValidatorsCount() ?: 0, + token = status.currency.symbol, ), ) - }, - ifLeft = { error -> - Timber.e(error.toString()) - stakingEventFactory.createGenericErrorAlert(error.toString()) - stateController.update(SetConfirmationStateResetAssentTransformer) - }, - ) - } - .flowOn(dispatchers.main) - .launchIn(viewModelScope) - } + } + + feeCryptoCurrencyStatus = + getFeePaidCryptoCurrencyStatusSyncUseCase(userWalletId, status).getOrNull() + cryptoCurrencyStatus = status + val isAnyTokenStaked = isAnyTokenStakedUseCase(userWalletId).getOrNull() ?: false + + setupApprovalNeeded() + checkIfSubtractAvailable() + + 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) + }, + ) + } + .flowOn(dispatchers.main) + .launchIn(viewModelScope) } private fun subscribeOnBalanceHiding() {