From 575389311f5eff95048c7d1197df01da21f2e410 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 24 Aug 2023 16:21:28 +0800 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/TokensDomainModule.kt | 8 ++ .../buttons/HorizontalActionChips.kt | 2 +- .../ui/components/buttons/actions/Actions.kt | 43 ++++--- .../tokens/GetCryptoCurrencyActionsUseCase.kt | 8 +- .../presentation/common/WalletPreviewData.kt | 16 +-- .../state/components/WalletManageButton.kt | 80 ++++++------- .../WalletCryptoCurrencyActionsConverter.kt | 50 ++++++++ .../state/factory/WalletLockedConverter.kt | 110 ++++++++++++++++++ .../factory/WalletRefreshStateConverter.kt | 40 ++++--- .../factory/WalletSkeletonStateConverter.kt | 13 +-- .../state/factory/WalletStateFactory.kt | 98 ++++------------ .../wallet/viewmodels/WalletClickIntents.kt | 6 + .../wallet/viewmodels/WalletViewModel.kt | 29 ++++- 13 files changed, 333 insertions(+), 170 deletions(-) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletCryptoCurrencyActionsConverter.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletLockedConverter.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index 0acb93c93c..3dd86e4e03 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -70,4 +70,12 @@ internal object TokensDomainModule { ): ApplyTokenListSortingUseCase { return ApplyTokenListSortingUseCase(currenciesRepository, dispatchers) } + + @Provides + @ViewModelScoped + fun provideGetCryptoCurrencyActionsUseCase( + dispatchers: CoroutineDispatcherProvider, + ): GetCryptoCurrencyActionsUseCase { + return GetCryptoCurrencyActionsUseCase(dispatchers) + } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/buttons/HorizontalActionChips.kt b/core/ui/src/main/java/com/tangem/core/ui/components/buttons/HorizontalActionChips.kt index 6b20a931f8..b34aa9c970 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/buttons/HorizontalActionChips.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/buttons/HorizontalActionChips.kt @@ -33,7 +33,7 @@ fun HorizontalActionChips( ) { items( items = buttons, - key = { config -> "${config.text.hashCode()} ${config.iconResId}" }, + key = { config -> config.text.hashCode() }, itemContent = { ActionButton(config = it) }, ) } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/buttons/actions/Actions.kt b/core/ui/src/main/java/com/tangem/core/ui/components/buttons/actions/Actions.kt index 65422a2f7b..2167ad385c 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/buttons/actions/Actions.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/buttons/actions/Actions.kt @@ -1,5 +1,6 @@ package com.tangem.core.ui.components.buttons.actions +import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -7,6 +8,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -78,43 +80,52 @@ private fun Button( modifier: Modifier = Modifier, color: Color = TangemTheme.colors.button.secondary, ) { + val backgroundColor by animateColorAsState( + targetValue = if (config.enabled) color else TangemTheme.colors.button.disabled, + label = "Update background color", + ) + Row( modifier = modifier .heightIn(min = TangemTheme.dimens.size36) .clip(shape) - .background( - color = if (config.enabled) color else TangemTheme.colors.button.disabled, - shape = shape, - ) + .background(color = backgroundColor, shape = shape) .clickable(enabled = config.enabled, onClick = config.onClick) - .padding( - start = TangemTheme.dimens.spacing16, - end = TangemTheme.dimens.spacing24, - ) + .padding(start = TangemTheme.dimens.spacing16, end = TangemTheme.dimens.spacing24) .padding(vertical = TangemTheme.dimens.spacing8), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, ) { - Icon( - painter = painterResource(id = config.iconResId), - contentDescription = null, - modifier = Modifier.size(size = TangemTheme.dimens.size20), - tint = when { + val iconTint by animateColorAsState( + targetValue = when { !config.enabled -> TangemTheme.colors.icon.informative config.dimContent -> TangemTheme.colors.icon.secondary else -> TangemTheme.colors.icon.primary1 }, + label = "Update tint color", + ) + + Icon( + painter = painterResource(id = config.iconResId), + contentDescription = null, + modifier = Modifier.size(size = TangemTheme.dimens.size20), + tint = iconTint, ) SpacerW8() - Text( - text = config.text.resolveReference(), - color = when { + val textColor by animateColorAsState( + targetValue = when { !config.enabled -> TangemTheme.colors.text.disabled config.dimContent -> TangemTheme.colors.text.secondary else -> TangemTheme.colors.text.primary1 }, + label = "Update text color", + ) + + Text( + text = config.text.resolveReference(), + color = textColor, overflow = TextOverflow.Ellipsis, maxLines = 1, style = TangemTheme.typography.button, diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt index ec8f8f39f8..d705aacf94 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt @@ -3,7 +3,9 @@ package com.tangem.domain.tokens import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOn class GetCryptoCurrencyActionsUseCase( private val dispatchers: CoroutineDispatcherProvider, @@ -22,10 +24,10 @@ class GetCryptoCurrencyActionsUseCase( tokenId = tokenId, states = listOf( TokenActionsState.ActionState.Buy(true), - TokenActionsState.ActionState.Sell(true), + TokenActionsState.ActionState.Send(true), TokenActionsState.ActionState.Receive(true), - TokenActionsState.ActionState.Swap(true), TokenActionsState.ActionState.Sell(true), + TokenActionsState.ActionState.Swap(true), ), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt index 91d8ccbd5d..bf75186348 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt @@ -277,13 +277,15 @@ internal object WalletPreviewData { ).toImmutableList(), ) - private val manageButtons = persistentListOf( - WalletManageButton.Buy(onClick = {}), - WalletManageButton.Send(onClick = {}), - WalletManageButton.Receive(onClick = {}), - WalletManageButton.Exchange(onClick = {}), - WalletManageButton.CopyAddress(onClick = {}), - ) + private val manageButtons by lazy { + persistentListOf( + WalletManageButton.Buy(enabled = true, onClick = {}), + WalletManageButton.Send(enabled = true, onClick = {}), + WalletManageButton.Receive(onClick = {}), + WalletManageButton.Sell(enabled = true, onClick = {}), + WalletManageButton.Swap(enabled = true, onClick = {}), + ) + } val multicurrencyWalletScreenState by lazy { WalletMultiCurrencyState.Content( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/components/WalletManageButton.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/components/WalletManageButton.kt index e8745338ed..46f70a5b22 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/components/WalletManageButton.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/components/WalletManageButton.kt @@ -8,7 +8,7 @@ import com.tangem.feature.wallet.impl.R /** * Wallet manage button state * - * @param config action config + * @property config action config * [REDACTED_AUTHOR] */ @@ -16,87 +16,79 @@ import com.tangem.feature.wallet.impl.R sealed class WalletManageButton(val config: ActionButtonConfig) { /** Lambda be invoked when manage button is clicked */ - abstract val onClick: (() -> Unit)? + abstract val onClick: () -> Unit /** * Buy * - * @param onClick lambda be invoked when manage button is clicked + * @property enabled button click availability + * @property onClick lambda be invoked when Buy button is clicked */ - data class Buy(override val onClick: (() -> Unit)? = null) : WalletManageButton( + data class Buy(val enabled: Boolean, override val onClick: () -> Unit) : WalletManageButton( config = ActionButtonConfig( text = TextReference.Res(id = R.string.common_buy), iconResId = R.drawable.ic_plus_24, - onClick = onClick ?: {}, - enabled = onClick != null, - ), - ) - - /** - * Sell - * - * @param onClick lambda be invoked when manage button is clicked - */ - data class Sell(override val onClick: (() -> Unit)? = null) : WalletManageButton( - config = ActionButtonConfig( - text = TextReference.Res(id = R.string.common_sell), - iconResId = R.drawable.ic_currency_24, - onClick = onClick ?: {}, - enabled = onClick != null, + onClick = onClick, + enabled = enabled, ), ) /** * Send * - * @param onClick lambda be invoked when manage button is clicked + * @property enabled button click availability + * @property onClick lambda be invoked when Send button is clicked */ - data class Send(override val onClick: (() -> Unit)? = null) : WalletManageButton( + data class Send(val enabled: Boolean, override val onClick: () -> Unit) : WalletManageButton( config = ActionButtonConfig( text = TextReference.Res(id = R.string.common_send), iconResId = R.drawable.ic_arrow_up_24, - onClick = onClick ?: {}, - enabled = onClick != null, + onClick = onClick, + enabled = enabled, ), ) /** * Receive * - * @param onClick lambda be invoked when manage button is clicked + * @property onClick lambda be invoked when Receive button is clicked */ data class Receive(override val onClick: () -> Unit) : WalletManageButton( config = ActionButtonConfig( text = TextReference.Res(id = R.string.common_receive), iconResId = R.drawable.ic_arrow_down_24, onClick = onClick, + enabled = true, ), ) /** - * Exchange + * Sell * - * @param onClick lambda be invoked when manage button is clicked + * @property enabled button click availability + * @property onClick lambda be invoked when Sell button is clicked */ - data class Exchange(override val onClick: (() -> Unit)? = null) : WalletManageButton( + data class Sell(val enabled: Boolean, override val onClick: () -> Unit) : WalletManageButton( config = ActionButtonConfig( - text = TextReference.Res(id = R.string.common_exchange), - iconResId = R.drawable.ic_exchange_vertical_24, - onClick = onClick ?: {}, - enabled = onClick != null, - ), - ) - - /** - * Copy address - * - * @param onClick lambda be invoked when manage button is clicked - */ - data class CopyAddress(override val onClick: () -> Unit) : WalletManageButton( - config = ActionButtonConfig( - text = TextReference.Res(id = R.string.common_copy_address), - iconResId = R.drawable.ic_copy_24, + text = TextReference.Res(id = R.string.common_sell), + iconResId = R.drawable.ic_currency_24, onClick = onClick, + enabled = enabled, + ), + ) + + /** + * Swap + * + * @property enabled button click availability + * @property onClick lambda be invoked when Swap button is clicked + */ + data class Swap(val enabled: Boolean, override val onClick: () -> Unit) : WalletManageButton( + config = ActionButtonConfig( + text = TextReference.Res(id = R.string.common_swap), + iconResId = R.drawable.ic_exchange_vertical_24, + onClick = onClick, + enabled = enabled, ), ) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletCryptoCurrencyActionsConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletCryptoCurrencyActionsConverter.kt new file mode 100644 index 0000000000..ea88f686dd --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletCryptoCurrencyActionsConverter.kt @@ -0,0 +1,50 @@ +package com.tangem.feature.wallet.presentation.wallet.state.factory + +import com.tangem.common.Provider +import com.tangem.domain.tokens.model.TokenActionsState +import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState +import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState +import com.tangem.feature.wallet.presentation.wallet.state.WalletState +import com.tangem.feature.wallet.presentation.wallet.state.components.WalletManageButton +import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents +import com.tangem.utils.converter.Converter +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList + +internal class WalletCryptoCurrencyActionsConverter( + private val currentStateProvider: Provider, + private val clickIntents: WalletClickIntents, +) : Converter, WalletState> { + + override fun convert(value: List): WalletState { + return when (val state = currentStateProvider()) { + is WalletSingleCurrencyState.Content -> state.copy(buttons = value.mapToManageButtons()) + is WalletSingleCurrencyState.Locked, + is WalletMultiCurrencyState, + is WalletState.Initial, + -> state + } + } + + private fun List.mapToManageButtons(): ImmutableList { + return this + .mapNotNull { action -> + when (action) { + is TokenActionsState.ActionState.Buy -> { + WalletManageButton.Buy(enabled = action.enabled, onClick = clickIntents::onBuyClick) + } + is TokenActionsState.ActionState.Receive -> { + WalletManageButton.Receive(onClick = clickIntents::onReceiveClick) + } + is TokenActionsState.ActionState.Sell -> { + WalletManageButton.Sell(enabled = action.enabled, onClick = clickIntents::onSellClick) + } + is TokenActionsState.ActionState.Send -> { + WalletManageButton.Send(enabled = action.enabled, onClick = clickIntents::onSellClick) + } + is TokenActionsState.ActionState.Swap -> null + } + } + .toImmutableList() + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletLockedConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletLockedConverter.kt new file mode 100644 index 0000000000..5ec6613bb8 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletLockedConverter.kt @@ -0,0 +1,110 @@ +package com.tangem.feature.wallet.presentation.wallet.state.factory + +import com.tangem.common.Provider +import com.tangem.domain.common.CardTypesResolver +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory +import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState +import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState +import com.tangem.feature.wallet.presentation.wallet.state.WalletState +import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState +import com.tangem.feature.wallet.presentation.wallet.state.components.WalletManageButton +import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTopBarConfig +import com.tangem.feature.wallet.presentation.wallet.state.components.WalletsListConfig +import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents +import com.tangem.utils.converter.Converter +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList + +internal class WalletLockedConverter( + private val currentStateProvider: Provider, + private val currentCardTypeResolverProvider: Provider, + private val currentWalletProvider: Provider, + private val clickIntents: WalletClickIntents, +) : Converter { + + override fun convert(value: Unit): WalletState { + return when (val state = currentStateProvider()) { + is WalletState.ContentState -> { + val cardTypeResolver = currentCardTypeResolverProvider() + + if (cardTypeResolver.isMultiwalletAllowed()) { + state.toMultiCurrencyLockedState(cardTypeResolver) + } else { + state.toSingleCurrencyLockedState(cardTypeResolver) + } + } + is WalletState.Initial -> state + } + } + + private fun WalletState.ContentState.toMultiCurrencyLockedState( + cardTypeResolver: CardTypesResolver, + ): WalletMultiCurrencyState.Locked { + return WalletMultiCurrencyState.Locked( + onBackClick = onBackClick, + topBarConfig = createTopBarConfig(), + walletsListConfig = createWalletsListConfig(cardTypeResolver), + pullToRefreshConfig = pullToRefreshConfig, + onUnlockWalletsNotificationClick = clickIntents::onUnlockWalletNotificationClick, + onUnlockClick = clickIntents::onUnlockWalletClick, + onScanClick = clickIntents::onScanCardClick, + ) + } + + private fun WalletState.ContentState.toSingleCurrencyLockedState( + cardTypeResolver: CardTypesResolver, + ): WalletSingleCurrencyState.Locked { + return WalletSingleCurrencyState.Locked( + onBackClick = onBackClick, + topBarConfig = createTopBarConfig(), + walletsListConfig = createWalletsListConfig(cardTypeResolver), + pullToRefreshConfig = pullToRefreshConfig, + buttons = createButtons(), + onUnlockWalletsNotificationClick = clickIntents::onUnlockWalletNotificationClick, + onUnlockClick = clickIntents::onUnlockWalletClick, + onScanClick = clickIntents::onScanCardClick, + onExploreClick = clickIntents::onExploreClick, + ) + } + + private fun WalletState.ContentState.createTopBarConfig(): WalletTopBarConfig { + return topBarConfig.copy(onMoreClick = clickIntents::onUnlockWalletNotificationClick) + } + + private fun WalletState.ContentState.createWalletsListConfig( + cardTypeResolver: CardTypesResolver, + ): WalletsListConfig { + return walletsListConfig.copy( + wallets = walletsListConfig.wallets + .map { walletCardState -> + WalletCardState.LockedContent( + id = walletCardState.id, + title = walletCardState.title, + additionalInfo = if (cardTypeResolver.isMultiwalletAllowed()) { + WalletAdditionalInfoFactory.resolve( + cardTypesResolver = cardTypeResolver, + wallet = currentWalletProvider(), + ) + } else { + null + }, + imageResId = walletCardState.imageResId, + onRenameClick = walletCardState.onRenameClick, + onDeleteClick = walletCardState.onDeleteClick, + ) + } + .toImmutableList(), + ) + } + + private fun createButtons(): ImmutableList { + return persistentListOf( + WalletManageButton.Buy(enabled = false, onClick = {}), + WalletManageButton.Send(enabled = false, onClick = {}), + WalletManageButton.Receive(onClick = {}), + WalletManageButton.Sell(enabled = false, onClick = {}), + ) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletRefreshStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletRefreshStateConverter.kt index faa6a40114..f820ff8444 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletRefreshStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletRefreshStateConverter.kt @@ -8,11 +8,8 @@ import com.tangem.feature.wallet.presentation.common.state.TokenItemState import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletState -import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState -import com.tangem.feature.wallet.presentation.wallet.state.components.WalletPullToRefreshConfig -import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState +import com.tangem.feature.wallet.presentation.wallet.state.components.* import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState.TokensListItemState -import com.tangem.feature.wallet.presentation.wallet.state.components.WalletsListConfig import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.ImmutableList @@ -36,22 +33,23 @@ internal class WalletRefreshStateConverter( private fun WalletMultiCurrencyState.Content.getRefreshState(): WalletMultiCurrencyState.Content { return copy( - walletsListConfig = getWalletsListConfig(), - pullToRefreshConfig = getPullToRefreshConfig(), - tokensListState = getTokenListState(), + walletsListConfig = createWalletsListConfig(), + pullToRefreshConfig = createPullToRefreshConfig(), + tokensListState = createTokenListState(), ) } private fun WalletSingleCurrencyState.Content.getRefreshState(): WalletSingleCurrencyState.Content { return copy( - walletsListConfig = getWalletsListConfig(), - pullToRefreshConfig = getPullToRefreshConfig(), - txHistoryState = getTxHistoryState(), + walletsListConfig = createWalletsListConfig(), + pullToRefreshConfig = createPullToRefreshConfig(), + buttons = buttons.mapToDisabledButton(), + txHistoryState = createTxHistoryState(), marketPriceBlockState = MarketPriceBlockState.Loading(currencyName = marketPriceBlockState.currencyName), ) } - private fun WalletState.ContentState.getWalletsListConfig(): WalletsListConfig { + private fun WalletState.ContentState.createWalletsListConfig(): WalletsListConfig { val selectedWallet = walletsListConfig.wallets[walletsListConfig.selectedWalletIndex] val additionalInfo = if (currentCardTypeResolverProvider().isMultiwalletAllowed()) { selectedWallet.additionalInfo @@ -74,11 +72,11 @@ internal class WalletRefreshStateConverter( ) } - private fun WalletState.ContentState.getPullToRefreshConfig(): WalletPullToRefreshConfig { + private fun WalletState.ContentState.createPullToRefreshConfig(): WalletPullToRefreshConfig { return pullToRefreshConfig.copy(isRefreshing = true) } - private fun WalletMultiCurrencyState.Content.getTokenListState(): WalletTokensListState { + private fun WalletMultiCurrencyState.Content.createTokenListState(): WalletTokensListState { return when (tokensListState) { is WalletTokensListState.Content -> { WalletTokensListState.Loading( @@ -100,7 +98,21 @@ internal class WalletRefreshStateConverter( .toImmutableList() } - private fun WalletSingleCurrencyState.Content.getTxHistoryState(): TxHistoryState { + private fun ImmutableList.mapToDisabledButton(): ImmutableList { + return this + .mapNotNull { button -> + when (button) { + is WalletManageButton.Buy -> button.copy(enabled = false) + is WalletManageButton.Send -> button.copy(enabled = false) + is WalletManageButton.Receive -> button + is WalletManageButton.Sell -> button.copy(enabled = false) + is WalletManageButton.Swap -> null + } + } + .toImmutableList() + } + + private fun WalletSingleCurrencyState.Content.createTxHistoryState(): TxHistoryState { if (txHistoryState is TxHistoryState.Content) { txHistoryState.contentItems.update { TxHistoryState.getDefaultLoadingTransactions(onExploreClick = clickIntents::onExploreClick) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletSkeletonStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletSkeletonStateConverter.kt index a783f78001..6b5fcc5d49 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletSkeletonStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletSkeletonStateConverter.kt @@ -63,7 +63,7 @@ internal class WalletSkeletonStateConverter( pullToRefreshConfig = createPullToRefreshConfig(), notifications = persistentListOf(), bottomSheetConfig = null, - buttons = getButtons(), + buttons = createButtons(), marketPriceBlockState = MarketPriceBlockState.Loading(currencyName = currencyName), txHistoryState = TxHistoryState.Content( contentItems = MutableStateFlow( @@ -127,15 +127,12 @@ internal class WalletSkeletonStateConverter( return WalletPullToRefreshConfig(isRefreshing = false, onRefresh = clickIntents::onRefreshSwipe) } - // TODO: [REDACTED_JIRA] - private fun getButtons(): ImmutableList { + private fun createButtons(): ImmutableList { return persistentListOf( - WalletManageButton.Buy(), - WalletManageButton.Send(), + WalletManageButton.Buy(enabled = false, onClick = {}), + WalletManageButton.Send(enabled = false, onClick = {}), WalletManageButton.Receive(onClick = {}), - WalletManageButton.Exchange(), - WalletManageButton.Sell(), - WalletManageButton.CopyAddress(onClick = {}), + WalletManageButton.Sell(enabled = false, onClick = {}), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletStateFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletStateFactory.kt index 52787d6a81..af79773b6c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletStateFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletStateFactory.kt @@ -8,26 +8,22 @@ import com.tangem.domain.common.CardTypesResolver import com.tangem.domain.tokens.error.CurrencyError import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.domain.tokens.model.TokenList import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.domain.txhistory.models.TxHistoryListError import com.tangem.domain.txhistory.models.TxHistoryStateError import com.tangem.domain.wallets.models.UserWallet -import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory import com.tangem.feature.wallet.presentation.wallet.state.ActionsBottomSheetConfig import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletState import com.tangem.feature.wallet.presentation.wallet.state.components.WalletBottomSheetConfig -import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState -import com.tangem.feature.wallet.presentation.wallet.state.components.WalletManageButton import com.tangem.feature.wallet.presentation.wallet.state.components.WalletNotification import com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory.WalletLoadedTxHistoryConverter import com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory.WalletLoadingTxHistoryConverter import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.Flow /** @@ -83,6 +79,15 @@ internal class WalletStateFactory( ) } + private val lockedConverter by lazy { + WalletLockedConverter( + currentStateProvider = currentStateProvider, + currentCardTypeResolverProvider = currentCardTypeResolverProvider, + currentWalletProvider = currentWalletProvider, + clickIntents = clickIntents, + ) + } + private val refreshStateConverter by lazy { WalletRefreshStateConverter( currentStateProvider = currentStateProvider, @@ -91,6 +96,13 @@ internal class WalletStateFactory( ) } + private val cryptoCurrencyActionsConverter by lazy { + WalletCryptoCurrencyActionsConverter( + currentStateProvider = currentStateProvider, + clickIntents = clickIntents, + ) + } + fun getInitialState(): WalletState = WalletState.Initial(onBackClick = clickIntents::onBackClick) fun getSkeletonState(wallets: List, selectedWalletIndex: Int): WalletState { @@ -184,77 +196,7 @@ internal class WalletStateFactory( return loadedTxHistoryConverter.convert(txHistoryEither) } - fun getLockedState(): WalletState { - val cardTypeResolver = currentCardTypeResolverProvider() - val state = requireNotNull(currentStateProvider() as? WalletState.ContentState) - return if (cardTypeResolver.isMultiwalletAllowed()) { - WalletMultiCurrencyState.Locked( - onBackClick = state.onBackClick, - topBarConfig = state.topBarConfig.copy( - onMoreClick = clickIntents::onUnlockWalletNotificationClick, - ), - walletsListConfig = state.walletsListConfig.copy( - wallets = state.walletsListConfig.wallets - .map { walletCardState -> - WalletCardState.LockedContent( - id = walletCardState.id, - title = walletCardState.title, - imageResId = walletCardState.imageResId, - additionalInfo = WalletAdditionalInfoFactory.resolve( - cardTypesResolver = cardTypeResolver, - wallet = currentWalletProvider(), - ), - onRenameClick = walletCardState.onRenameClick, - onDeleteClick = walletCardState.onDeleteClick, - ) - } - .toImmutableList(), - ), - pullToRefreshConfig = state.pullToRefreshConfig, - onUnlockWalletsNotificationClick = clickIntents::onUnlockWalletNotificationClick, - onUnlockClick = clickIntents::onUnlockWalletClick, - onScanClick = clickIntents::onScanCardClick, - ) - } else { - WalletSingleCurrencyState.Locked( - onBackClick = state.onBackClick, - topBarConfig = state.topBarConfig.copy( - onMoreClick = clickIntents::onUnlockWalletNotificationClick, - ), - walletsListConfig = state.walletsListConfig.copy( - wallets = state.walletsListConfig.wallets - .map { walletCardState -> - WalletCardState.LockedContent( - id = walletCardState.id, - title = walletCardState.title, - imageResId = walletCardState.imageResId, - onRenameClick = walletCardState.onRenameClick, - onDeleteClick = walletCardState.onDeleteClick, - ) - } - .toImmutableList(), - ), - pullToRefreshConfig = state.pullToRefreshConfig, - buttons = getButtons(), - onUnlockWalletsNotificationClick = clickIntents::onUnlockWalletNotificationClick, - onUnlockClick = clickIntents::onUnlockWalletClick, - onScanClick = clickIntents::onScanCardClick, - onExploreClick = clickIntents::onExploreClick, - ) - } - } - - // TODO: [REDACTED_JIRA] - private fun getButtons(): ImmutableList { - return persistentListOf( - WalletManageButton.Buy(), - WalletManageButton.Send(), - WalletManageButton.Receive(onClick = {}), - WalletManageButton.Exchange(), - WalletManageButton.Sell(), - WalletManageButton.CopyAddress(onClick = {}), - ) - } + fun getLockedState(): WalletState = lockedConverter.convert(Unit) fun getSingleCurrencyLoadedBalanceState( cryptoCurrencyEither: Either, @@ -267,4 +209,8 @@ internal class WalletStateFactory( ), ) } + + fun getSingleCurrencyManageButtonsState(actions: List): WalletState { + return cryptoCurrencyActionsConverter.convert(value = actions) + } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletClickIntents.kt index ad201200ed..ee7ed4346d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletClickIntents.kt @@ -46,4 +46,10 @@ internal interface WalletClickIntents : TxHistoryClickIntents { fun onRenameClick(userWalletId: UserWalletId, name: String) fun onDeleteClick(userWalletId: UserWalletId) + + fun onSendClick() + + fun onReceiveClick() + + fun onSellClick() } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt index 8e578615f1..d27c5d8ba9 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt @@ -17,6 +17,7 @@ import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.settings.IsUserAlreadyRateAppUseCase +import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase import com.tangem.domain.tokens.GetPrimaryCurrencyUseCase import com.tangem.domain.tokens.GetTokenListUseCase import com.tangem.domain.tokens.model.TokenList @@ -76,6 +77,7 @@ internal class WalletViewModel @Inject constructor( private val getExploreUrlUseCase: GetExploreUrlUseCase, private val unlockWalletsUseCase: UnlockWalletsUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, + private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase, private val dispatchers: CoroutineDispatcherProvider, ) : ViewModel(), DefaultLifecycleObserver, WalletClickIntents { @@ -112,6 +114,7 @@ internal class WalletViewModel @Inject constructor( private val tokensJobHolder = JobHolder() private val marketPriceJobHolder = JobHolder() + private val buttonsJobHolder = JobHolder() private val notificationsJobHolder = JobHolder() override fun onCreate(owner: LifecycleOwner) { @@ -178,8 +181,10 @@ internal class WalletViewModel @Inject constructor( private fun updateSingleCurrencyContent(index: Int, isRefreshing: Boolean) { val wallet = getWallet(index) + val blockchain = getCardTypeResolver(index).getBlockchain() + updateButtons(userWalletId = wallet.walletId, currencyId = blockchain.id) updateTxHistory( - blockchain = getCardTypeResolver(index).getBlockchain(), + blockchain = blockchain, derivationStyle = wallet.scanResponse.derivationStyleProvider.getDerivationStyle(), ) updateMarketPrice(userWalletId = wallet.walletId, isRefreshing = isRefreshing) @@ -225,6 +230,15 @@ internal class WalletViewModel @Inject constructor( .saveIn(marketPriceJobHolder) } + private fun updateButtons(userWalletId: UserWalletId, currencyId: String) { + getCryptoCurrencyActionsUseCase(userWalletId = userWalletId, tokenId = currencyId) + .distinctUntilChanged() + .onEach { uiState = stateFactory.getSingleCurrencyManageButtonsState(actions = it.states) } + .flowOn(dispatchers.io) + .launchIn(viewModelScope) + .saveIn(buttonsJobHolder) + } + private fun updateNotifications(index: Int, tokenList: TokenList? = null) { notificationsListFactory.create( cardTypesResolver = getCardTypeResolver(index = index), @@ -338,6 +352,7 @@ internal class WalletViewModel @Inject constructor( */ tokensJobHolder.update(job = null) marketPriceJobHolder.update(job = null) + buttonsJobHolder.update(job = null) notificationsJobHolder.update(job = null) val cacheState = WalletStateCache.getState(userWalletId = state.walletsListConfig.wallets[index].id) @@ -410,6 +425,18 @@ internal class WalletViewModel @Inject constructor( // TODO: [REDACTED_JIRA] } + override fun onSendClick() { + // TODO: [REDACTED_JIRA] + } + + override fun onReceiveClick() { + // TODO: [REDACTED_JIRA] + } + + override fun onSellClick() { + // TODO: [REDACTED_JIRA] + } + override fun onReloadClick() { uiState = stateFactory.getStateAfterContentRefreshing() updateSingleCurrencyContent(