Updated on 2026-08-14
This commit is contained in:
parent
dce35fc26b
commit
430eced63a
10 changed files with 126 additions and 80 deletions
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.child.wallet.model.intents
|
|||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.domain.exchange.RampStateManager
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
|
|
@ -18,6 +19,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletContentFetcher
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.unwrap
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetRefreshStateTransformer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -46,6 +48,7 @@ internal class WalletClickIntents @Inject constructor(
|
|||
private val tangemPayIntents: TangemPayClickIntentsImplementor,
|
||||
private val yieldSupplyApyUpdateUseCase: YieldSupplyApyUpdateUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
) : BaseWalletClickIntents(),
|
||||
WalletCardClickIntents by walletCardClickIntentsImplementor,
|
||||
WalletWarningsClickIntents by warningsClickIntentsImplementer,
|
||||
|
|
@ -108,6 +111,13 @@ internal class WalletClickIntents @Inject constructor(
|
|||
|
||||
fun onTransferClick(userWalletId: UserWalletId) {
|
||||
analyticsEventHandler.send(MainScreenAnalyticsEvent.ButtonTransfer())
|
||||
|
||||
val selectedWallet = stateController.getSelectedWalletUM() as? WalletUM.Content
|
||||
if (selectedWallet?.areActionsAvailable == false) {
|
||||
uiMessageSender.send(WalletAlertUM.unavailableOperation())
|
||||
return
|
||||
}
|
||||
|
||||
router.openTransfer(userWalletId)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.core.ui.ds.button.TangemButtonUM
|
|||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
||||
/**
|
||||
|
|
@ -26,7 +27,16 @@ internal sealed class WalletActionButtons(
|
|||
val buttonUM: TangemButtonUM
|
||||
get() = TangemButtonUM(
|
||||
text = text,
|
||||
tangemIconUM = TangemIconUM.Icon(iconRes = iconRes),
|
||||
tangemIconUM = TangemIconUM.Icon(
|
||||
iconRes = iconRes,
|
||||
tintReference = {
|
||||
if (isEnabled) {
|
||||
TangemTheme.colors2.graphic.neutral.primary
|
||||
} else {
|
||||
TangemTheme.colors2.graphic.neutral.quaternary
|
||||
}
|
||||
},
|
||||
),
|
||||
type = TangemButtonType.Secondary,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
onClick = onClick,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ internal sealed interface WalletUM {
|
|||
override val type: WalletType,
|
||||
override val tangemPayMainUM: TangemPayMainUM,
|
||||
override val virtualAccountMainUM: VirtualAccountMainUM,
|
||||
val areActionsAvailable: Boolean = false,
|
||||
) : WalletUM
|
||||
|
||||
data class Locked(
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.disableButtons
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.mutate
|
||||
|
||||
|
|
@ -36,15 +34,9 @@ internal class SetRefreshStateTransformer(
|
|||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return when (walletUM) {
|
||||
is WalletUM.Content -> {
|
||||
val tokensListUM = walletUM.tokensListUM.toUpdatedState()
|
||||
walletUM.copy(
|
||||
pullToRefreshConfig = walletUM.pullToRefreshConfig.toUpdatedState(isRefreshing),
|
||||
tokensListUM = tokensListUM,
|
||||
buttons = if (tokensListUM is WalletTokensListUM.Empty) {
|
||||
walletUM.disableButtons()
|
||||
} else {
|
||||
walletUM.enableButtons()
|
||||
},
|
||||
tokensListUM = walletUM.tokensListUM.toUpdatedState(),
|
||||
)
|
||||
}
|
||||
is WalletUM.Locked -> walletUM
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.tokens.error.TokenListError
|
|||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.createWalletActionButtons
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.disableButtons
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -64,7 +65,14 @@ internal class SetTokenListErrorTransformer(
|
|||
clickIntents.onAssetsDiscoveryManageClick(walletUM.walletsBalanceUM.id)
|
||||
},
|
||||
),
|
||||
buttons = walletUM.disableButtons(),
|
||||
areActionsAvailable = false,
|
||||
buttons = createWalletActionButtons(
|
||||
userWallet = selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
isAddFundsEnabled = false,
|
||||
isSwapEnabled = false,
|
||||
isTransferEnabled = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletUM.Locked -> {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
|
||||
import com.tangem.common.ui.tokens.TokenConverterParams
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -9,7 +11,7 @@ import com.tangem.domain.staking.model.StakingAvailability
|
|||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.disableButtons
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.createWalletActionButtons
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM
|
||||
|
|
@ -68,16 +70,21 @@ internal class SetTokenListTransformer(
|
|||
return when (walletUM) {
|
||||
is WalletUM.Content -> {
|
||||
val tokensListUM = toLoadedState()
|
||||
val isTokensEmpty = tokensListUM is WalletTokensListUM.Empty
|
||||
val areActionsAvailable = getTotalFiatBalance().areActionsAvailable()
|
||||
walletUM.copy(
|
||||
walletsBalanceUM = walletUM.walletsBalanceUM.toLoadedState2(),
|
||||
tangemPayMainUM = walletUM.tangemPayMainUM.toLoadedState(),
|
||||
virtualAccountMainUM = walletUM.virtualAccountMainUM.toLoadedVirtualState(),
|
||||
tokensListUM = tokensListUM,
|
||||
buttons = if (tokensListUM is WalletTokensListUM.Empty) {
|
||||
walletUM.disableButtons()
|
||||
} else {
|
||||
walletUM.enableButtons()
|
||||
},
|
||||
areActionsAvailable = areActionsAvailable,
|
||||
buttons = createWalletActionButtons(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
isAddFundsEnabled = !isTokensEmpty,
|
||||
isSwapEnabled = !isTokensEmpty && areActionsAvailable,
|
||||
isTransferEnabled = !isTokensEmpty,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletUM.Locked -> {
|
||||
|
|
@ -87,6 +94,14 @@ internal class SetTokenListTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getTotalFiatBalance(): TotalFiatBalance = when (params) {
|
||||
is TokenConverterParams.Account -> params.accountList.totalFiatBalance
|
||||
is TokenConverterParams.Wallet -> params.tokenList.totalFiatBalance
|
||||
}
|
||||
|
||||
private fun TotalFiatBalance.areActionsAvailable(): Boolean =
|
||||
(this as? TotalFiatBalance.Loaded)?.source != StatusSource.ONLY_CACHE
|
||||
|
||||
private fun WalletCardState.toLoadedState(): WalletCardState {
|
||||
val fiatBalance = when (params) {
|
||||
is TokenConverterParams.Account -> params.accountList.totalFiatBalance
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.utils
|
||||
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletManageButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
|
|
@ -17,27 +13,6 @@ internal fun WalletState.MultiCurrency.Content.disableButtons(): PersistentList<
|
|||
return changeAvailability(enabled = false)
|
||||
}
|
||||
|
||||
internal fun WalletUM.Content.enableButtons(): PersistentList<TangemButtonUM> {
|
||||
return buttons.map { it.withEnabled(isEnabled = true) }.toPersistentList()
|
||||
}
|
||||
|
||||
internal fun WalletUM.Content.disableButtons(): PersistentList<TangemButtonUM> {
|
||||
return buttons.map { it.withEnabled(isEnabled = false) }.toPersistentList()
|
||||
}
|
||||
|
||||
private fun TangemButtonUM.withEnabled(isEnabled: Boolean): TangemButtonUM {
|
||||
val refreshedIcon = (tangemIconUM as? TangemIconUM.Icon)?.copy(
|
||||
tint = {
|
||||
if (isEnabled) {
|
||||
TangemTheme.colors2.graphic.neutral.primary
|
||||
} else {
|
||||
TangemTheme.colors2.graphic.neutral.quaternary
|
||||
}
|
||||
},
|
||||
) ?: tangemIconUM
|
||||
return copy(isEnabled = isEnabled, tangemIconUM = refreshedIcon)
|
||||
}
|
||||
|
||||
private fun WalletState.MultiCurrency.Content.changeAvailability(enabled: Boolean): PersistentList<WalletManageButton> {
|
||||
return buttons
|
||||
.map { action ->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.utils
|
||||
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletActionButtons
|
||||
import com.tangem.utils.extensions.addIf
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal fun createWalletActionButtons(
|
||||
userWallet: UserWallet,
|
||||
clickIntents: WalletClickIntents,
|
||||
isAddFundsEnabled: Boolean,
|
||||
isSwapEnabled: Boolean,
|
||||
isTransferEnabled: Boolean,
|
||||
): PersistentList<TangemButtonUM> {
|
||||
val isSingleWalletWithToken = userWallet is UserWallet.Cold &&
|
||||
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
|
||||
return buildList {
|
||||
add(
|
||||
WalletActionButtons.AddFunds(
|
||||
isEnabled = isAddFundsEnabled,
|
||||
onClick = { clickIntents.onAddFundsClick(userWalletId = userWallet.walletId) },
|
||||
).buttonUM,
|
||||
)
|
||||
addIf(
|
||||
condition = !userWallet.isSingleWallet() && !isSingleWalletWithToken,
|
||||
element = WalletActionButtons.Swap(
|
||||
isEnabled = isSwapEnabled,
|
||||
onClick = { clickIntents.onMultiWalletSwapClick(userWalletId = userWallet.walletId) },
|
||||
).buttonUM,
|
||||
)
|
||||
add(
|
||||
WalletActionButtons.Transfer(
|
||||
isEnabled = isTransferEnabled,
|
||||
onClick = { clickIntents.onTransferClick(userWalletId = userWallet.walletId) },
|
||||
).buttonUM,
|
||||
)
|
||||
}.toPersistentList()
|
||||
}
|
||||
|
|
@ -18,11 +18,9 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.features.virtualaccount.main.entity.VirtualAccountMainUM
|
||||
import com.tangem.utils.extensions.addIf
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
/**
|
||||
|
|
@ -174,33 +172,13 @@ internal class WalletLoadingStateFactory(
|
|||
}
|
||||
|
||||
private fun createWalletActions(userWallet: UserWallet): PersistentList<TangemButtonUM> {
|
||||
val isSingleWalletWithToken =
|
||||
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
return buildList {
|
||||
add(
|
||||
WalletActionButtons.AddFunds(
|
||||
isEnabled = false,
|
||||
onClick = { clickIntents.onAddFundsClick(userWalletId = userWallet.walletId) },
|
||||
).buttonUM,
|
||||
return createWalletActionButtons(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
isAddFundsEnabled = false,
|
||||
isSwapEnabled = false,
|
||||
isTransferEnabled = false,
|
||||
)
|
||||
addIf(
|
||||
condition = !userWallet.isSingleWallet() && !isSingleWalletWithToken,
|
||||
element = WalletActionButtons.Swap(
|
||||
isEnabled = false,
|
||||
onClick = {
|
||||
clickIntents.onMultiWalletSwapClick(userWalletId = userWallet.walletId)
|
||||
},
|
||||
).buttonUM,
|
||||
)
|
||||
add(
|
||||
WalletActionButtons.Transfer(
|
||||
isEnabled = false,
|
||||
onClick = {
|
||||
clickIntents.onTransferClick(userWalletId = userWallet.walletId)
|
||||
},
|
||||
).buttonUM,
|
||||
)
|
||||
}.toPersistentList()
|
||||
}
|
||||
|
||||
private fun createDimmedButtons(): PersistentList<WalletManageButton> {
|
||||
|
|
|
|||
|
|
@ -44,19 +44,33 @@ class SetTokenListTransformerTest {
|
|||
val result = transformer.transform(walletUM(buttonEnabled = true)) as WalletUM.Content
|
||||
|
||||
assertThat(result.tokensListUM).isInstanceOf(WalletTokensListUM.Empty::class.java)
|
||||
assertThat(result.buttons).hasSize(1)
|
||||
assertThat(result.buttons.single().isEnabled).isFalse()
|
||||
assertThat(result.buttons.map { it.isEnabled }).containsExactly(false, false, false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN non-empty account list WHEN transform THEN tokens not Empty and buttons enabled`() {
|
||||
val transformer = createTransformer(accountList = nonEmptyAccountList())
|
||||
fun `GIVEN actual balance WHEN transform THEN tokens not Empty and all buttons enabled`() {
|
||||
val transformer = createTransformer(
|
||||
accountList = nonEmptyAccountList(TotalFiatBalance.Loaded(BigDecimal.ZERO, StatusSource.ACTUAL)),
|
||||
)
|
||||
|
||||
val result = transformer.transform(walletUM(buttonEnabled = false)) as WalletUM.Content
|
||||
|
||||
assertThat(result.tokensListUM).isNotInstanceOf(WalletTokensListUM.Empty::class.java)
|
||||
assertThat(result.buttons).hasSize(1)
|
||||
assertThat(result.buttons.single().isEnabled).isTrue()
|
||||
assertThat(result.areActionsAvailable).isTrue()
|
||||
assertThat(result.buttons.map { it.isEnabled }).containsExactly(true, true, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN only cached balance WHEN transform THEN Swap disabled while AddFunds and Transfer enabled`() {
|
||||
val transformer = createTransformer(
|
||||
accountList = nonEmptyAccountList(TotalFiatBalance.Loaded(BigDecimal.ZERO, StatusSource.ONLY_CACHE)),
|
||||
)
|
||||
|
||||
val result = transformer.transform(walletUM(buttonEnabled = false)) as WalletUM.Content
|
||||
|
||||
assertThat(result.areActionsAvailable).isFalse()
|
||||
// buttons order: AddFunds, Swap, Transfer
|
||||
assertThat(result.buttons.map { it.isEnabled }).containsExactly(true, false, true)
|
||||
}
|
||||
|
||||
private fun createTransformer(accountList: AccountStatusList): SetTokenListTransformer {
|
||||
|
|
@ -88,11 +102,11 @@ class SetTokenListTransformerTest {
|
|||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
|
||||
private fun nonEmptyAccountList(): AccountStatusList {
|
||||
private fun nonEmptyAccountList(totalFiatBalance: TotalFiatBalance): AccountStatusList {
|
||||
val token = createToken()
|
||||
val tokenList = TokenList.Ungrouped(
|
||||
currencies = listOf(createLoadedStatus(token)),
|
||||
totalFiatBalance = TotalFiatBalance.Loaded(BigDecimal.ZERO, StatusSource.ACTUAL),
|
||||
totalFiatBalance = totalFiatBalance,
|
||||
sortedBy = TokensSortType.NONE,
|
||||
)
|
||||
return AccountStatusList(
|
||||
|
|
@ -100,7 +114,7 @@ class SetTokenListTransformerTest {
|
|||
accountStatuses = listOf(mainCryptoPortfolioStatus(tokenList = tokenList)),
|
||||
totalAccounts = 1,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
totalFiatBalance = totalFiatBalance,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue