Updated on 2026-08-14

This commit is contained in:
Tangem 2024-11-06 19:46:17 +04:00
parent 3d5a28e435
commit 75e794abdf
12 changed files with 171 additions and 58 deletions

View file

@ -119,6 +119,7 @@ internal object WalletScreenPreviewData {
onRefresh = {},
),
walletCardState = miltiUnreachableCard,
buttons = persistentListOf(buyButton),
warnings = persistentListOf(
WalletNotification.Warning.SomeNetworksUnreachable,
),

View file

@ -24,6 +24,7 @@ internal sealed interface WalletState : WalletStateHolder {
data class Content(
override val pullToRefreshConfig: PullToRefreshConfig,
override val walletCardState: WalletCardState,
override val buttons: PersistentList<WalletManageButton>,
override val warnings: ImmutableList<WalletNotification>,
override val bottomSheetConfig: TangemBottomSheetConfig?,
override val tokensListState: WalletTokensListState,
@ -31,13 +32,15 @@ internal sealed interface WalletState : WalletStateHolder {
data class Locked(
override val walletCardState: WalletCardState,
override val buttons: PersistentList<WalletManageButton>,
override val bottomSheetConfig: TangemBottomSheetConfig?,
val onUnlockNotificationClick: () -> Unit,
) : MultiCurrency(),
WalletStateHolder by LockedWalletStateHolder(
walletCardState,
bottomSheetConfig,
onUnlockNotificationClick,
walletCardState = walletCardState,
buttons = buttons,
bottomSheetConfig = bottomSheetConfig,
onUnlockNotificationClick = onUnlockNotificationClick,
) {
override val tokensListState = WalletTokensListState.ContentState.Locked
@ -46,7 +49,6 @@ internal sealed interface WalletState : WalletStateHolder {
sealed class SingleCurrency : WalletState, TxHistoryStateHolder {
abstract val buttons: PersistentList<WalletManageButton>
abstract val marketPriceBlockState: MarketPriceBlockState?
data class Content(
@ -68,9 +70,10 @@ internal sealed interface WalletState : WalletStateHolder {
) : SingleCurrency(),
TxHistoryStateHolder by LockedTxHistoryStateHolder(onExploreClick),
WalletStateHolder by LockedWalletStateHolder(
walletCardState,
bottomSheetConfig,
onUnlockNotificationClick,
walletCardState = walletCardState,
buttons = buttons,
bottomSheetConfig = bottomSheetConfig,
onUnlockNotificationClick = onUnlockNotificationClick,
) {
override val marketPriceBlockState: MarketPriceBlockState? = null
@ -84,6 +87,7 @@ internal sealed interface WalletState : WalletStateHolder {
data class Content(
override val pullToRefreshConfig: PullToRefreshConfig,
override val walletCardState: WalletCardState,
override val buttons: PersistentList<WalletManageButton>,
override val warnings: ImmutableList<WalletNotification>,
override val bottomSheetConfig: TangemBottomSheetConfig?,
override val balancesAndLimitBlockState: BalancesAndLimitsBlockState,
@ -93,15 +97,17 @@ internal sealed interface WalletState : WalletStateHolder {
data class Locked(
override val walletCardState: WalletCardState,
val onUnlockNotificationClick: () -> Unit,
override val buttons: PersistentList<WalletManageButton>,
override val bottomSheetConfig: TangemBottomSheetConfig?,
val onUnlockNotificationClick: () -> Unit,
val onExploreClick: () -> Unit,
) : Visa(),
TxHistoryStateHolder by LockedTxHistoryStateHolder(onExploreClick),
WalletStateHolder by LockedWalletStateHolder(
walletCardState,
bottomSheetConfig,
onUnlockNotificationClick,
walletCardState = walletCardState,
buttons = buttons,
bottomSheetConfig = bottomSheetConfig,
onUnlockNotificationClick = onUnlockNotificationClick,
) {
override val balancesAndLimitBlockState: BalancesAndLimitsBlockState? = null

View file

@ -3,20 +3,24 @@ package com.tangem.feature.wallet.presentation.wallet.state.model.holder
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.pullToRefresh.PullToRefreshConfig
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletManageButton
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
internal interface WalletStateHolder {
val pullToRefreshConfig: PullToRefreshConfig
val walletCardState: WalletCardState
val buttons: PersistentList<WalletManageButton>
val warnings: ImmutableList<WalletNotification>
val bottomSheetConfig: TangemBottomSheetConfig?
}
internal class LockedWalletStateHolder(
override val walletCardState: WalletCardState,
override val buttons: PersistentList<WalletManageButton>,
override val bottomSheetConfig: TangemBottomSheetConfig?,
onUnlockNotificationClick: () -> Unit,
) : WalletStateHolder {

View file

@ -5,18 +5,21 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import kotlinx.collections.immutable.toImmutableList
internal class AddWalletTransformer(
private val userWallet: UserWallet,
private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver,
private val walletFeatureToggles: WalletFeatureToggles,
) : WalletScreenStateTransformer {
private val walletLoadingStateFactory by lazy {
WalletLoadingStateFactory(
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
walletFeatureToggles = walletFeatureToggles,
)
}

View file

@ -7,6 +7,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.*
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
import com.tangem.feature.wallet.presentation.wallet.state.utils.createStateByWalletType
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@ -16,10 +17,15 @@ internal class InitializeWalletsTransformer(
private val wallets: List<UserWallet>,
private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver,
private val walletFeatureToggles: WalletFeatureToggles,
) : WalletScreenStateTransformer {
private val walletLoadingStateFactory by lazy {
WalletLoadingStateFactory(clickIntents = clickIntents, walletImageResolver = walletImageResolver)
WalletLoadingStateFactory(
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
walletFeatureToggles = walletFeatureToggles,
)
}
override fun transform(prevState: WalletScreenState): WalletScreenState {
@ -52,6 +58,7 @@ internal class InitializeWalletsTransformer(
multiCurrencyCreator = {
WalletState.MultiCurrency.Locked(
walletCardState = userWallet.toLockedWalletCardState(),
buttons = createMultiWalletDisabledButtons(),
bottomSheetConfig = null,
onUnlockNotificationClick = clickIntents::onOpenUnlockWalletsBottomSheetClick,
)
@ -68,6 +75,7 @@ internal class InitializeWalletsTransformer(
visaWalletCreator = {
WalletState.Visa.Locked(
walletCardState = userWallet.toLockedWalletCardState(),
buttons = createMultiWalletDisabledButtons(),
bottomSheetConfig = null,
onUnlockNotificationClick = clickIntents::onOpenUnlockWalletsBottomSheetClick,
onExploreClick = clickIntents::onExploreClick,
@ -87,6 +95,17 @@ internal class InitializeWalletsTransformer(
)
}
private fun createMultiWalletDisabledButtons(): PersistentList<WalletManageButton> {
if (!walletFeatureToggles.isMainActionButtonsEnabled) return persistentListOf()
return persistentListOf(
WalletManageButton.Receive(enabled = false, dimContent = false, onClick = {}, onLongClick = null),
WalletManageButton.Send(enabled = false, dimContent = false, onClick = {}),
WalletManageButton.Buy(enabled = false, dimContent = false, onClick = {}),
WalletManageButton.Sell(enabled = false, dimContent = false, onClick = {}),
)
}
private fun createDisabledButtons(): PersistentList<WalletManageButton> {
return persistentListOf(
WalletManageButton.Receive(enabled = false, dimContent = false, onClick = {}, onLongClick = null),

View file

@ -6,6 +6,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import kotlinx.collections.immutable.toImmutableList
/**
@ -22,10 +23,15 @@ internal class ReinitializeWalletTransformer(
private val newUserWallet: UserWallet,
private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver,
private val walletFeatureToggles: WalletFeatureToggles,
) : WalletScreenStateTransformer {
private val walletLoadingStateFactory by lazy {
WalletLoadingStateFactory(clickIntents = clickIntents, walletImageResolver = walletImageResolver)
WalletLoadingStateFactory(
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
walletFeatureToggles = walletFeatureToggles,
)
}
override fun transform(prevState: WalletScreenState): WalletScreenState {

View file

@ -7,6 +7,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenSta
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import kotlinx.collections.immutable.toImmutableList
import timber.log.Timber
@ -14,10 +15,15 @@ internal class UnlockWalletTransformer(
private val unlockedWallets: List<UserWallet>,
private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver,
private val walletFeatureToggles: WalletFeatureToggles,
) : WalletScreenStateTransformer {
private val walletLoadingStateFactory by lazy {
WalletLoadingStateFactory(clickIntents = clickIntents, walletImageResolver = walletImageResolver)
WalletLoadingStateFactory(
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
walletFeatureToggles = walletFeatureToggles,
)
}
override fun transform(prevState: WalletScreenState): WalletScreenState {

View file

@ -9,6 +9,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfo
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
import com.tangem.feature.wallet.presentation.wallet.state.model.*
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
@ -21,6 +22,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
internal class WalletLoadingStateFactory(
private val clickIntents: WalletClickIntents,
private val walletImageResolver: WalletImageResolver,
private val walletFeatureToggles: WalletFeatureToggles,
) {
fun create(userWallet: UserWallet): WalletState {
@ -35,6 +37,7 @@ internal class WalletLoadingStateFactory(
return WalletState.MultiCurrency.Content(
pullToRefreshConfig = createPullToRefreshConfig(),
walletCardState = userWallet.toLoadingWalletCardState(),
buttons = createMultiWalletActions(),
warnings = persistentListOf(),
bottomSheetConfig = null,
tokensListState = WalletTokensListState.ContentState.Loading,
@ -62,6 +65,7 @@ internal class WalletLoadingStateFactory(
return WalletState.Visa.Content(
pullToRefreshConfig = createPullToRefreshConfig(),
walletCardState = userWallet.toLoadingWalletCardState(),
buttons = createMultiWalletActions(),
warnings = persistentListOf(),
bottomSheetConfig = null,
balancesAndLimitBlockState = BalancesAndLimitsBlockState.Loading,
@ -89,6 +93,16 @@ internal class WalletLoadingStateFactory(
)
}
private fun createMultiWalletActions(): PersistentList<WalletManageButton> {
if (!walletFeatureToggles.isMainActionButtonsEnabled) return persistentListOf()
return persistentListOf(
WalletManageButton.Buy(enabled = false, dimContent = true, onClick = { }),
WalletManageButton.Swap(enabled = false, dimContent = true, onClick = { }),
WalletManageButton.Sell(enabled = false, dimContent = true, onClick = { }),
)
}
private fun createDimmedButtons(): PersistentList<WalletManageButton> {
return persistentListOf(
WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null),

View file

@ -75,8 +75,8 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.PushNotificat
import com.tangem.feature.wallet.presentation.wallet.ui.components.TokenActionsBottomSheet
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.*
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.actions
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.organizeTokensButton
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.controlButtons
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.BalancesAndLimitsBottomSheet
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.VisaTxDetailsBottomSheet
@ -187,12 +187,23 @@ private fun WalletContent(
)
}
(selectedWallet as? WalletState.SingleCurrency)?.let {
controlButtons(
configs = it.buttons,
selectedWalletIndex = selectedWalletIndex,
modifier = movableItemModifier.padding(top = betweenItemsPadding),
)
when (selectedWallet) {
is WalletState.MultiCurrency,
is WalletState.Visa,
-> {
actions(
actions = selectedWallet.buttons,
selectedWalletIndex = selectedWalletIndex,
modifier = movableItemModifier.padding(top = betweenItemsPadding),
)
}
is WalletState.SingleCurrency -> {
lazyActions(
actions = selectedWallet.buttons,
selectedWalletIndex = selectedWalletIndex,
modifier = movableItemModifier.padding(top = betweenItemsPadding),
)
}
}
notifications(configs = selectedWallet.warnings, modifier = itemModifier)

View file

@ -0,0 +1,74 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.buttons.HorizontalActionChips
import com.tangem.core.ui.components.buttons.actions.ActionButton
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletManageButton
import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
private const val ACTIONS_CONTENT_TYPE = "Actions"
/**
* Actions in scrollable container. Like, "Buy", "Sell", etc
*
* @param actions list of buttons
* @param selectedWalletIndex selected wallet index for creating a unique key
* @param modifier modifier
*
[REDACTED_AUTHOR]
*/
internal fun LazyListScope.lazyActions(
actions: ImmutableList<WalletManageButton>,
selectedWalletIndex: Int,
modifier: Modifier = Modifier,
) {
item(key = ACTIONS_CONTENT_TYPE + selectedWalletIndex, contentType = ACTIONS_CONTENT_TYPE) {
HorizontalActionChips(
buttons = actions.map(WalletManageButton::config).toImmutableList(),
modifier = modifier.animateItem(),
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
)
}
}
/**
* Action buttons. Like, "Buy", "Sell", etc
*
* @param actions list of buttons
* @param selectedWalletIndex selected wallet index for creating a unique key
* @param modifier modifier
*
[REDACTED_AUTHOR]
*/
internal fun LazyListScope.actions(
actions: ImmutableList<WalletManageButton>,
selectedWalletIndex: Int,
modifier: Modifier = Modifier,
) {
if (actions.isEmpty()) return
item(key = ACTIONS_CONTENT_TYPE + selectedWalletIndex, contentType = ACTIONS_CONTENT_TYPE) {
Row(
modifier = modifier
.padding(horizontal = 16.dp)
.fillMaxWidth()
.animateItem(),
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing8),
verticalAlignment = Alignment.CenterVertically,
) {
actions.fastForEach {
key(it::class.java) {
ActionButton(config = it.config, modifier = Modifier.weight(1f))
}
}
}
}
}

View file

@ -1,37 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.ui.Modifier
import com.tangem.core.ui.components.buttons.HorizontalActionChips
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletManageButton
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
private const val CONTROL_BUTTONS_CONTENT_TYPE = "ControlButtons"
/**
* Single currency control buttons. Like, "Buy", "Sell", etc
*
* @param configs list of buttons
* @param selectedWalletIndex selected wallet index for creating a unique key
* @param modifier modifier
*
[REDACTED_AUTHOR]
*/
@OptIn(ExperimentalFoundationApi::class)
internal fun LazyListScope.controlButtons(
configs: ImmutableList<WalletManageButton>,
selectedWalletIndex: Int,
modifier: Modifier = Modifier,
) {
item(key = CONTROL_BUTTONS_CONTENT_TYPE + selectedWalletIndex, contentType = CONTROL_BUTTONS_CONTENT_TYPE) {
HorizontalActionChips(
buttons = configs.map(WalletManageButton::config).toImmutableList(),
modifier = modifier.animateItemPlacement(),
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
)
}
}

View file

@ -31,6 +31,7 @@ import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvid
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.JobHolder
@ -69,6 +70,7 @@ internal class WalletViewModel @Inject constructor(
private val shouldAskPermissionUseCase: ShouldAskPermissionUseCase,
private val walletImageResolver: WalletImageResolver,
private val tokenListStore: MultiWalletTokenListStore,
private val walletFeatureToggles: WalletFeatureToggles,
analyticsEventsHandler: AnalyticsEventHandler,
) : ViewModel() {
@ -300,6 +302,7 @@ internal class WalletViewModel @Inject constructor(
wallets = action.wallets,
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
walletFeatureToggles = walletFeatureToggles,
),
)
@ -334,6 +337,7 @@ internal class WalletViewModel @Inject constructor(
newUserWallet = action.selectedWallet,
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
walletFeatureToggles = walletFeatureToggles,
),
)
}
@ -350,6 +354,7 @@ internal class WalletViewModel @Inject constructor(
userWallet = action.selectedWallet,
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
walletFeatureToggles = walletFeatureToggles,
),
)
@ -401,6 +406,7 @@ internal class WalletViewModel @Inject constructor(
unlockedWallets = action.unlockedWallets,
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
walletFeatureToggles = walletFeatureToggles,
),
)