Updated on 2026-08-14

This commit is contained in:
Tangem 2023-10-10 13:30:11 +03:00
commit e2791d9b35
33 changed files with 103 additions and 294 deletions

View file

@ -89,7 +89,7 @@ private fun FiatBalance(
)
is TokenDetailsBalanceBlockState.Error -> Text(
modifier = modifier,
text = BigDecimalFormatter.EMPTY_BALANCE_SIGN,
text = if (isBalanceHidden) STARS else BigDecimalFormatter.EMPTY_BALANCE_SIGN,
style = TangemTheme.typography.h2,
color = TangemTheme.colors.text.primary1,
)
@ -117,7 +117,7 @@ private fun CryptoBalance(
)
is TokenDetailsBalanceBlockState.Error -> Text(
modifier = modifier,
text = BigDecimalFormatter.EMPTY_BALANCE_SIGN,
text = if (isBalanceHidden) STARS else BigDecimalFormatter.EMPTY_BALANCE_SIGN,
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)

View file

@ -57,19 +57,6 @@ internal object WalletPreviewData {
)
}
val walletCardHiddenContentState by lazy {
WalletCardState.HiddenContent(
id = UserWalletId("42"),
title = "Wallet 1",
imageResId = R.drawable.ill_wallet2_cards3_120_106,
onRenameClick = { _, _ -> },
onDeleteClick = {},
balance = "8923,05 $",
additionalInfo = TextReference.Str("3 cards • Seed phrase"),
cardCount = 1,
)
}
val walletCardErrorState by lazy {
WalletCardState.Error(
id = UserWalletId("24"),
@ -84,7 +71,6 @@ internal object WalletPreviewData {
mapOf(
UserWalletId(stringValue = "123") to walletCardContentState,
UserWalletId(stringValue = "321") to walletCardLoadingState,
UserWalletId(stringValue = "42") to walletCardHiddenContentState,
UserWalletId(stringValue = "24") to walletCardErrorState,
)
}
@ -131,7 +117,6 @@ internal object WalletPreviewData {
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $"),
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = "5,412 MATIC"),
priceChangeState = TokenItemState.PriceChangeState.Unknown,
isBalanceHidden = false,
onItemClick = {},
onItemLongClick = {},
)
@ -155,7 +140,6 @@ internal object WalletPreviewData {
valueInPercent = "2.0%",
type = PriceChangeType.UP,
),
isBalanceHidden = false,
onItemClick = {},
onItemLongClick = {},
)
@ -167,7 +151,6 @@ internal object WalletPreviewData {
iconState = tokenIconState,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = "3 172,14 $"),
isBalanceHidden = false,
)
}
@ -298,6 +281,7 @@ internal object WalletPreviewData {
onCancelClick = {},
),
scrollListToTop = consumedEvent(),
isBalanceHidden = true,
)
}

View file

@ -33,6 +33,7 @@ private enum class LayoutId {
@Composable
internal fun TokenItem(
state: TokenItemState,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
reorderableTokenListState: ReorderableLazyListState? = null,
) {
@ -42,10 +43,6 @@ internal fun TokenItem(
.tokenClickable(state = state)
.background(color = TangemTheme.colors.background.primary),
) {
val isBalanceHidden = (state as? TokenItemState.Content)?.isBalanceHidden
?: (state as? TokenItemState.Draggable)?.isBalanceHidden
?: false
TokenIcon(state = state.iconState, modifier = Modifier.layoutId(layoutId = LayoutId.ICON))
TokenTitle(
@ -382,7 +379,7 @@ private fun calculateLayoutHeight(
@Composable
private fun Preview_CustomTokenItem_InLight(@PreviewParameter(TokenItemStateProvider::class) state: TokenItemState) {
TangemTheme(isDark = false) {
TokenItem(state = state)
TokenItem(state = state, isBalanceHidden = false)
}
}

View file

@ -57,7 +57,6 @@ internal sealed class TokenItemState {
override val fiatAmountState: FiatAmountState,
override val cryptoAmountState: CryptoAmountState.Content,
override val priceChangeState: PriceChangeState?,
val isBalanceHidden: Boolean,
val onItemClick: () -> Unit,
val onItemLongClick: () -> Unit,
) : TokenItemState()
@ -74,7 +73,6 @@ internal sealed class TokenItemState {
override val iconState: IconState,
override val titleState: TitleState,
override val cryptoAmountState: CryptoAmountState,
val isBalanceHidden: Boolean,
) : TokenItemState() {
override val fiatAmountState: FiatAmountState? = null
override val priceChangeState: PriceChangeState? = null

View file

@ -65,6 +65,7 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier
listState = tokensListState,
state = state.itemsState,
dndConfig = state.dndConfig,
isBalanceHidden = state.isBalanceHidden,
)
},
floatingActionButtonPosition = FabPosition.Center,
@ -84,6 +85,7 @@ private fun TokenList(
listState: LazyListState,
state: OrganizeTokensListState,
dndConfig: OrganizeTokensState.DragAndDropConfig,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
val hapticFeedback = LocalHapticFeedback.current
@ -131,6 +133,7 @@ private fun TokenList(
item = item,
reorderableState = reorderableListState,
onDragStart = onDragStart,
isBalanceHidden = isBalanceHidden,
)
}
}
@ -145,6 +148,7 @@ private fun LazyItemScope.DraggableItem(
item: DraggableItem,
reorderableState: ReorderableLazyListState,
onDragStart: () -> Unit,
isBalanceHidden: Boolean,
) {
var isDragging by remember {
mutableStateOf(value = false)
@ -169,6 +173,7 @@ private fun LazyItemScope.DraggableItem(
modifier = itemModifier,
state = item.tokenItemState,
reorderableTokenListState = reorderableState,
isBalanceHidden = isBalanceHidden,
)
// Should be presented in the list but remain invisible
is DraggableItem.Placeholder -> Box(modifier = Modifier.fillMaxWidth())

View file

@ -11,7 +11,6 @@ import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeToken
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.InProgressStateConverter
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.TokenListToStateConverter
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error.TokenListHiddenStateConverter
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error.TokenListErrorConverter
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error.TokenListSortingErrorConverter
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items.CryptoCurrencyToDraggableItemConverter
@ -25,14 +24,12 @@ internal class OrganizeTokensStateHolder(
private val intents: OrganizeTokensIntents,
private val dragAndDropIntents: DragAndDropIntents,
private val appCurrencyProvider: Provider<AppCurrency>,
private val isBalanceHiddenProvider: Provider<Boolean>,
private val listStateProvider: Provider<OrganizeTokensListState>,
) {
private val stateFlowInternal: MutableStateFlow<OrganizeTokensState> = MutableStateFlow(getInitialState())
private val tokenListConverter by lazy {
val tokensConverter = CryptoCurrencyToDraggableItemConverter(appCurrencyProvider, isBalanceHiddenProvider)
val tokensConverter = CryptoCurrencyToDraggableItemConverter(appCurrencyProvider)
val itemsConverter = TokenListToListStateConverter(
tokensConverter = tokensConverter,
groupsConverter = NetworkGroupToDraggableItemsConverter(tokensConverter),
@ -42,7 +39,6 @@ internal class OrganizeTokensStateHolder(
}
private val inProgressStateConverter by lazy { InProgressStateConverter() }
private val tokenListHiddenStateConverter by lazy { TokenListHiddenStateConverter(listStateProvider) }
private val tokenListErrorConverter by lazy {
TokenListErrorConverter(Provider(stateFlowInternal::value), inProgressStateConverter)
@ -83,7 +79,7 @@ internal class OrganizeTokensStateHolder(
}
fun updateHiddenState(isBalanceHidden: Boolean) {
updateState { copy(itemsState = tokenListHiddenStateConverter.convert(isBalanceHidden)) }
updateState { copy(isBalanceHidden = isBalanceHidden) }
}
fun updateStateWithError(error: TokenListError) {
@ -113,6 +109,7 @@ internal class OrganizeTokensStateHolder(
canDragItemOver = dragAndDropIntents::canDragItemOver,
),
scrollListToTop = consumedEvent(),
isBalanceHidden = true,
)
}

View file

@ -59,8 +59,6 @@ internal class OrganizeTokensViewModel @Inject constructor(
intents = this,
dragAndDropIntents = dragAndDropAdapter,
appCurrencyProvider = Provider(selectedAppCurrencyFlow::value),
isBalanceHiddenProvider = Provider { isBalanceHidden },
listStateProvider = Provider { uiState.value.itemsState },
)
private val userWalletId: UserWalletId by lazy {

View file

@ -12,6 +12,7 @@ internal data class OrganizeTokensState(
val actions: ActionsConfig,
val dndConfig: DragAndDropConfig,
val scrollListToTop: StateEvent<Unit>,
val isBalanceHidden: Boolean,
) {
data class HeaderConfig(

View file

@ -1,12 +0,0 @@
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter
internal class TokenItemHiddenStateConverter {
fun updateHiddenState(wasBalanceHidden: Boolean, isBalanceHidden: Boolean): Boolean {
return when {
!wasBalanceHidden && isBalanceHidden -> true
wasBalanceHidden && !isBalanceHidden -> false
else -> wasBalanceHidden
}
}
}

View file

@ -1,31 +0,0 @@
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error
import com.tangem.common.Provider
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.toPersistentList
internal class TokenListHiddenStateConverter(
private val currentStateProvider: Provider<OrganizeTokensListState>,
) : Converter<Boolean, OrganizeTokensListState> {
override fun convert(input: Boolean): OrganizeTokensListState {
val currentState = currentStateProvider()
val isBalanceHidden = input
return currentState.copySealed(
currentState.items.map { draggableItem ->
if (draggableItem is DraggableItem.Token) {
draggableItem.copy(
tokenItemState = draggableItem.tokenItemState.copy(
isBalanceHidden = isBalanceHidden,
),
)
} else {
draggableItem
}
}.toPersistentList(),
)
}
}

View file

@ -13,29 +13,26 @@ import com.tangem.utils.converter.Converter
internal class CryptoCurrencyToDraggableItemConverter(
private val appCurrencyProvider: Provider<AppCurrency>,
private val isBalanceHiddenProvider: Provider<Boolean>,
) : Converter<CryptoCurrencyStatus, DraggableItem.Token> {
private val iconStateConverter = CryptoCurrencyToIconStateConverter()
override fun convert(value: CryptoCurrencyStatus): DraggableItem.Token {
return createDraggableToken(value, appCurrencyProvider(), isBalanceHiddenProvider())
return createDraggableToken(value, appCurrencyProvider())
}
override fun convertList(input: Collection<CryptoCurrencyStatus>): List<DraggableItem.Token> {
val appCurrency = appCurrencyProvider()
val isBalanceHidden = isBalanceHiddenProvider()
return input.map { createDraggableToken(it, appCurrency, isBalanceHidden) }
return input.map { createDraggableToken(it, appCurrency) }
}
private fun createDraggableToken(
currencyStatus: CryptoCurrencyStatus,
appCurrency: AppCurrency,
isBalanceHidden: Boolean,
): DraggableItem.Token {
return DraggableItem.Token(
tokenItemState = createTokenItemState(currencyStatus, appCurrency, isBalanceHidden),
tokenItemState = createTokenItemState(currencyStatus, appCurrency),
groupId = getGroupHeaderId(currencyStatus.currency.network),
)
}
@ -43,7 +40,6 @@ internal class CryptoCurrencyToDraggableItemConverter(
private fun createTokenItemState(
currencyStatus: CryptoCurrencyStatus,
appCurrency: AppCurrency,
isBalanceHidden: Boolean,
): TokenItemState.Draggable {
val currency = currencyStatus.currency
@ -56,8 +52,6 @@ internal class CryptoCurrencyToDraggableItemConverter(
} else {
TokenItemState.CryptoAmountState.Content(text = getFormattedFiatAmount(currencyStatus, appCurrency))
},
isBalanceHidden = isBalanceHidden,
)
}

View file

@ -51,29 +51,6 @@ internal sealed interface WalletCardState {
val balance: String,
) : WalletCardState
/**
* Wallet card hidden content state
*
* @property id wallet id
* @property title wallet name
* @property imageResId wallet image resource id
* @property onRenameClick lambda be invoked when Rename button is clicked
* @property onDeleteClick lambda be invoked when Delete button is clicked
* @property additionalInfo wallet additional info
* @property cardCount number of cards in the wallet
* @property balance wallet balance
*/
data class HiddenContent(
override val id: UserWalletId,
override val title: String,
override val additionalInfo: TextReference,
override val imageResId: Int?,
override val onRenameClick: (UserWalletId, String) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,
val balance: String,
val cardCount: Int?,
) : WalletCardState
/**
* Wallet card locked state
*
@ -134,7 +111,6 @@ internal sealed interface WalletCardState {
return when (this) {
is Content -> copy(title = title)
is Error -> copy(title = title)
is HiddenContent -> copy(title = title)
is Loading -> copy(title = title)
is LockedContent -> copy(title = title)
}

View file

@ -30,7 +30,6 @@ internal class WalletLoadedTokensListConverter(
private val tokenListErrorConverter: TokenListErrorConverter,
appCurrencyProvider: Provider<AppCurrency>,
currentWalletProvider: Provider<UserWallet>,
isBalanceHiddenProvider: Provider<Boolean>,
clickIntents: WalletClickIntents,
) : Converter<Either<TokenListError, TokenList>, WalletState> {
@ -38,7 +37,6 @@ internal class WalletLoadedTokensListConverter(
currentStateProvider = currentStateProvider,
currentWalletProvider = currentWalletProvider,
appCurrencyProvider = appCurrencyProvider,
isBalanceHiddenProvider = isBalanceHiddenProvider,
clickIntents = clickIntents,
)

View file

@ -45,7 +45,6 @@ internal class WalletStateFactory(
private val currentCardTypeResolverProvider: Provider<CardTypesResolver>,
private val currentWalletProvider: Provider<UserWallet>,
private val appCurrencyProvider: Provider<AppCurrency>,
private val isBalanceHiddenProvider: Provider<Boolean>,
private val clickIntents: WalletClickIntents,
) {
@ -80,7 +79,6 @@ internal class WalletStateFactory(
tokenListErrorConverter = tokenListErrorConverter,
appCurrencyProvider = appCurrencyProvider,
currentWalletProvider = currentWalletProvider,
isBalanceHiddenProvider = isBalanceHiddenProvider,
clickIntents = clickIntents,
)
}
@ -95,7 +93,6 @@ internal class WalletStateFactory(
private val loadedTxHistoryConverter by lazy {
WalletLoadedTxHistoryConverter(
currentStateProvider = currentStateProvider,
isBalanceHiddenProvider = isBalanceHiddenProvider,
currentCardTypeResolverProvider = currentCardTypeResolverProvider,
clickIntents = clickIntents,
)

View file

@ -38,12 +38,6 @@ internal class WalletUpdateCardCountConverter(
),
cardCount = currentWalletProvider().getCardsCount(),
)
is WalletCardState.HiddenContent -> walletCard.copy(
additionalInfo = WalletAdditionalInfoFactory.resolve(
wallet = currentWalletProvider(),
),
cardCount = currentWalletProvider().getCardsCount(),
)
else -> walletCard
}
} else {

View file

@ -27,7 +27,6 @@ internal class WalletLoadedTxHistoryConverter(
private val currentStateProvider: Provider<WalletState>,
private val currentCardTypeResolverProvider: Provider<CardTypesResolver>,
private val clickIntents: WalletClickIntents,
private val isBalanceHiddenProvider: Provider<Boolean>,
) : Converter<Either<TxHistoryListError, Flow<PagingData<TxHistoryItem>>>, WalletState> {
private val walletTxHistoryItemFlowConverter by lazy {
@ -35,7 +34,6 @@ internal class WalletLoadedTxHistoryConverter(
currentStateProvider = currentStateProvider,
blockchain = currentCardTypeResolverProvider().getBlockchain(),
clickIntents = clickIntents,
isBalanceHiddenProvider = isBalanceHiddenProvider,
)
}

View file

@ -35,7 +35,6 @@ import org.joda.time.DateTimeZone
*/
internal class WalletTxHistoryItemFlowConverter(
private val currentStateProvider: Provider<WalletState>,
private val isBalanceHiddenProvider: Provider<Boolean>,
private val blockchain: Blockchain,
private val clickIntents: WalletClickIntents,
) : Converter<Flow<PagingData<TxHistoryItem>>, TxHistoryState?> {
@ -44,7 +43,6 @@ internal class WalletTxHistoryItemFlowConverter(
WalletTxHistoryTransactionStateConverter(
symbol = blockchain.currency,
decimals = blockchain.decimals(),
isBalanceHiddenProvider = isBalanceHiddenProvider,
)
}

View file

@ -1,7 +1,5 @@
package com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory
import com.tangem.common.Provider
import com.tangem.common.Strings
import com.tangem.core.ui.components.transactions.state.TransactionState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.txhistory.models.TxHistoryItem
@ -13,7 +11,6 @@ import com.tangem.utils.toFormattedCurrencyString
class WalletTxHistoryTransactionStateConverter(
private val symbol: String,
private val decimals: Int,
private val isBalanceHiddenProvider: Provider<Boolean>,
) : Converter<TxHistoryItem, TransactionState> {
override fun convert(value: TxHistoryItem): TransactionState {
@ -146,8 +143,6 @@ class WalletTxHistoryTransactionStateConverter(
}
private fun TxHistoryItem.getAmount(): String {
if (isBalanceHiddenProvider()) return Strings.STARS
val prefix = when (direction) {
is TxHistoryItem.TransactionDirection.Incoming -> "+"
is TxHistoryItem.TransactionDirection.Outgoing -> "-"

View file

@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.ui
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.ExperimentalMaterialApi
@ -126,7 +127,11 @@ private fun WalletContent(
horizontalAlignment = Alignment.CenterHorizontally,
) {
item {
WalletsList(config = state.walletsListConfig, lazyListState = walletsListState)
WalletsList(
config = state.walletsListConfig,
lazyListState = walletsListState,
isBalanceHidden = state.isBalanceHidden,
)
}
if (state is WalletSingleCurrencyState) {
@ -149,18 +154,7 @@ private fun WalletContent(
modifier = movableItemModifier,
)
if (state is WalletMultiCurrencyState) {
val contentTokenListState = state.tokensListState as? WalletTokensListState.ContentState
val organizeTokensButton = contentTokenListState?.organizeTokensButton
if (organizeTokensButton is OrganizeTokensButtonState.Visible) {
organizeTokensButton(
modifier = itemModifier,
isEnabled = organizeTokensButton.isEnabled,
onClick = organizeTokensButton.onClick,
)
}
}
organizeTokens(state = state, itemModifier = itemModifier)
}
}
}
@ -175,6 +169,21 @@ private fun WalletContent(
)
}
internal fun LazyListScope.organizeTokens(state: WalletState.ContentState, itemModifier: Modifier) {
if (state is WalletMultiCurrencyState) {
val contentTokenListState = state.tokensListState as? WalletTokensListState.ContentState
val organizeTokensButton = contentTokenListState?.organizeTokensButton
if (organizeTokensButton is OrganizeTokensButtonState.Visible) {
organizeTokensButton(
modifier = itemModifier,
isEnabled = organizeTokensButton.isEnabled,
onClick = organizeTokensButton.onClick,
)
}
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun UpdatableContainer(

View file

@ -38,7 +38,7 @@ private const val SHORT_SNAP_ELEMENT_COUNT = 50
*/
@OptIn(ExperimentalFoundationApi::class)
@Composable
internal fun WalletsList(config: WalletsListConfig, lazyListState: LazyListState) {
internal fun WalletsList(config: WalletsListConfig, lazyListState: LazyListState, isBalanceHidden: Boolean) {
val horizontalCardPadding = TangemTheme.dimens.spacing16
val screenWidth = LocalConfiguration.current.screenWidthDp.dp
val itemWidth by remember(screenWidth) { derivedStateOf { screenWidth - horizontalCardPadding * 2 } }
@ -57,6 +57,7 @@ internal fun WalletsList(config: WalletsListConfig, lazyListState: LazyListState
) { state ->
WalletCard(
state = state,
isBalanceHidden = isBalanceHidden,
modifier = Modifier
.animateItemPlacement()
.width(itemWidth),
@ -98,7 +99,11 @@ private fun rememberWalletsFlingBehaviour(lazyListState: LazyListState, itemWidt
@Composable
private fun Preview_WalletsList_LightTheme() {
TangemTheme(isDark = false) {
WalletsList(config = WalletPreviewData.walletListConfig, lazyListState = rememberLazyListState())
WalletsList(
config = WalletPreviewData.walletListConfig,
lazyListState = rememberLazyListState(),
isBalanceHidden = false,
)
}
}
@ -106,6 +111,10 @@ private fun Preview_WalletsList_LightTheme() {
@Composable
private fun Preview_WalletsList_DarkTheme() {
TangemTheme(isDark = true) {
WalletsList(config = WalletPreviewData.walletListConfig, lazyListState = rememberLazyListState())
WalletsList(
config = WalletPreviewData.walletListConfig,
lazyListState = rememberLazyListState(),
isBalanceHidden = false,
)
}
}

View file

@ -57,7 +57,7 @@ private const val HALF_OF_ITEM_WIDTH = 0.5
[REDACTED_AUTHOR]
*/
@Composable
internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
internal fun WalletCard(state: WalletCardState, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
@Suppress("DestructuringDeclarationWithTooManyEntries")
CardContainer(
name = state.title,
@ -82,6 +82,7 @@ internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
var balanceWidth by remember { mutableStateOf(value = Int.MIN_VALUE) }
Balance(
state = state,
isBalanceHidden = isBalanceHidden,
modifier = Modifier
.onSizeChanged { balanceWidth = it.width }
.padding(vertical = TangemTheme.dimens.spacing8)
@ -102,7 +103,6 @@ internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
when (state) {
is WalletCardState.Content,
is WalletCardState.Error,
is WalletCardState.HiddenContent,
-> {
end.linkTo(imageRef.start)
width = Dimension.fillToConstraints
@ -275,7 +275,7 @@ private fun TitleText(text: String, modifier: Modifier = Modifier) {
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun Balance(state: WalletCardState, modifier: Modifier = Modifier) {
private fun Balance(state: WalletCardState, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
AnimatedContent(
targetState = state,
label = "Update the balance",
@ -288,7 +288,7 @@ private fun Balance(state: WalletCardState, modifier: Modifier = Modifier) {
when (walletCardState) {
is WalletCardState.Content -> {
ResizableText(
text = walletCardState.balance,
text = if (isBalanceHidden) Strings.STARS else walletCardState.balance,
fontSizeRange = FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize),
modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size32),
color = TangemTheme.colors.text.primary1,
@ -297,8 +297,9 @@ private fun Balance(state: WalletCardState, modifier: Modifier = Modifier) {
style = TangemTheme.typography.h2,
)
}
is WalletCardState.HiddenContent -> NonContentBalanceText(TextReference.Str(Strings.STARS))
is WalletCardState.Error -> NonContentBalanceText(text = WalletCardState.EMPTY_BALANCE_TEXT)
is WalletCardState.Error -> NonContentBalanceText(
text = if (isBalanceHidden) WalletCardState.HIDDEN_BALANCE_TEXT else WalletCardState.EMPTY_BALANCE_TEXT,
)
is WalletCardState.Loading -> {
RectangleShimmer(modifier = Modifier.nonContentBalanceSize(TangemTheme.dimens))
}
@ -392,7 +393,7 @@ private fun Preview_WalletCard_LightTheme(
state: WalletCardState,
) {
TangemTheme(isDark = false) {
WalletCard(state = state)
WalletCard(state = state, isBalanceHidden = false)
}
}
@ -400,7 +401,7 @@ private fun Preview_WalletCard_LightTheme(
@Composable
private fun Preview_WalletCard_DarkTheme(@PreviewParameter(WalletCardStateProvider::class) state: WalletCardState) {
TangemTheme(isDark = true) {
WalletCard(state)
WalletCard(state = state, isBalanceHidden = false)
}
}
@ -408,7 +409,6 @@ private class WalletCardStateProvider : CollectionPreviewParameterProvider<Walle
collection = listOf(
WalletPreviewData.walletCardContentState,
WalletPreviewData.walletCardLoadingState,
WalletPreviewData.walletCardHiddenContentState,
WalletPreviewData.walletCardErrorState,
),
)

View file

@ -26,7 +26,7 @@ internal fun LazyListScope.contentItems(
modifier: Modifier = Modifier,
) {
when (state) {
is WalletMultiCurrencyState -> tokensListItems(state.tokensListState, modifier)
is WalletMultiCurrencyState -> tokensListItems(state.tokensListState, modifier, isBalanceHidden)
is WalletSingleCurrencyState -> txHistoryItems(state.txHistoryState, txHistoryItems, isBalanceHidden, modifier)
}
}

View file

@ -30,9 +30,17 @@ private const val NON_CONTENT_TOKENS_LIST_KEY = "NON_CONTENT_TOKENS_LIST"
*
[REDACTED_AUTHOR]
*/
internal fun LazyListScope.tokensListItems(state: WalletTokensListState, modifier: Modifier = Modifier) {
internal fun LazyListScope.tokensListItems(
state: WalletTokensListState,
modifier: Modifier = Modifier,
isBalanceHidden: Boolean,
) {
when (state) {
is WalletTokensListState.ContentState -> contentItems(items = state.items, modifier = modifier)
is WalletTokensListState.ContentState -> contentItems(
items = state.items,
isBalanceHidden = isBalanceHidden,
modifier = modifier,
)
WalletTokensListState.Empty -> nonContentItem(modifier = modifier)
}
}
@ -40,6 +48,7 @@ internal fun LazyListScope.tokensListItems(state: WalletTokensListState, modifie
private fun LazyListScope.contentItems(
items: ImmutableList<WalletTokensListState.TokensListItemState>,
modifier: Modifier = Modifier,
isBalanceHidden: Boolean,
) {
itemsIndexed(
items = items,
@ -48,6 +57,7 @@ private fun LazyListScope.contentItems(
itemContent = { index, item ->
MultiCurrencyContentItem(
state = item,
isBalanceHidden = isBalanceHidden,
modifier = modifier.roundedShapeItemDecoration(
currentIndex = index,
lastIndex = items.lastIndex,

View file

@ -16,13 +16,17 @@ import com.tangem.feature.wallet.presentation.wallet.state.components.WalletToke
[REDACTED_AUTHOR]
*/
@Composable
internal fun MultiCurrencyContentItem(state: WalletTokensListState.TokensListItemState, modifier: Modifier = Modifier) {
internal fun MultiCurrencyContentItem(
state: WalletTokensListState.TokensListItemState,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
when (state) {
is WalletTokensListState.TokensListItemState.NetworkGroupTitle -> {
NetworkGroupItem(networkName = state.name.resolveReference(), modifier = modifier)
}
is WalletTokensListState.TokensListItemState.Token -> {
TokenItem(state = state.state, modifier = modifier)
TokenItem(state = state.state, isBalanceHidden = isBalanceHidden, modifier = modifier)
}
}
}

View file

@ -13,7 +13,6 @@ import java.math.BigDecimal
internal class CryptoCurrencyStatusToTokenItemConverter(
private val appCurrencyProvider: Provider<AppCurrency>,
private val isBalanceHiddenProvider: Provider<Boolean>,
private val clickIntents: WalletClickIntents,
) : Converter<CryptoCurrencyStatus, TokenItemState> {
@ -55,7 +54,6 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
),
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = getFormattedAmount()),
priceChangeState = getPriceChangeConfig(),
isBalanceHidden = isBalanceHiddenProvider(),
onItemClick = { clickIntents.onTokenItemClick(currency) },
onItemLongClick = { clickIntents.onTokenItemLongClick(cryptoCurrencyStatus = this) },
)

View file

@ -14,7 +14,6 @@ internal class FiatBalanceToWalletCardConverter(
private val currentState: WalletCardState,
private val appCurrencyProvider: Provider<AppCurrency>,
private val currentWalletProvider: Provider<UserWallet>,
private val isBalanceHiddenProvider: Provider<Boolean>,
) : Converter<FiatBalance, WalletCardState> {
override fun convert(value: FiatBalance): WalletCardState {
@ -42,36 +41,19 @@ internal class FiatBalanceToWalletCardConverter(
private fun FiatBalance.Loaded.convertToWalletCardState(): WalletCardState {
val appCurrency = appCurrencyProvider()
return if (isBalanceHiddenProvider()) {
WalletCardState.HiddenContent(
id = currentState.id,
title = currentState.title,
imageResId = currentState.imageResId,
onRenameClick = currentState.onRenameClick,
onDeleteClick = currentState.onDeleteClick,
balance = formatFiatAmount(
fiatAmount = this.amount,
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
),
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = currentWalletProvider()),
cardCount = currentWalletProvider().getCardsCount(),
)
} else {
WalletCardState.Content(
id = currentState.id,
title = currentState.title,
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = currentWalletProvider()),
imageResId = currentState.imageResId,
onRenameClick = currentState.onRenameClick,
onDeleteClick = currentState.onDeleteClick,
balance = formatFiatAmount(
fiatAmount = this.amount,
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
),
cardCount = currentWalletProvider().getCardsCount(),
)
}
return WalletCardState.Content(
id = currentState.id,
title = currentState.title,
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = currentWalletProvider()),
imageResId = currentState.imageResId,
onRenameClick = currentState.onRenameClick,
onDeleteClick = currentState.onDeleteClick,
balance = formatFiatAmount(
fiatAmount = this.amount,
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
),
cardCount = currentWalletProvider().getCardsCount(),
)
}
}

View file

@ -2,66 +2,22 @@ package com.tangem.feature.wallet.presentation.wallet.utils
import com.tangem.common.Converter
import com.tangem.common.Provider
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.TokenItemHiddenStateConverter
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.WalletTokensListState
import kotlinx.collections.immutable.toImmutableList
internal class HiddenStateConverter(
private val currentStateProvider: Provider<WalletState>,
) : Converter<Boolean, WalletState> {
private val walletHiddenBalanceStateConverter by lazy { WalletHiddenBalanceStateConverter() }
private val tokenItemHiddenStateConverter by lazy { TokenItemHiddenStateConverter() }
override fun convert(value: Boolean): WalletState {
return when (val state = currentStateProvider() as? WalletState.ContentState) {
is WalletMultiCurrencyState.Content -> {
val updatedTokensList = (state.tokensListState as? WalletTokensListState.Content)?.let { content ->
content.copy(
items = content.items.map { tokenListItemState ->
if (tokenListItemState is WalletTokensListState.TokensListItemState.Token) {
if (tokenListItemState.state is TokenItemState.Content) {
tokenListItemState.copy(
state = tokenListItemState.state.copy(
isBalanceHidden = tokenItemHiddenStateConverter.updateHiddenState(
wasBalanceHidden = tokenListItemState.state.isBalanceHidden,
isBalanceHidden = value,
),
),
)
} else {
tokenListItemState
}
} else {
tokenListItemState
}
}.toImmutableList(),
)
} ?: state.tokensListState
state.copy(
walletsListConfig = state.walletsListConfig.copy(
wallets = state.walletsListConfig.wallets.map {
walletHiddenBalanceStateConverter.updateHiddenState(it, value)
}.toImmutableList(),
),
tokensListState = updatedTokensList,
)
state.copy(isBalanceHidden = value)
}
is WalletSingleCurrencyState.Content -> {
state.copy(
walletsListConfig = state.walletsListConfig.copy(
wallets = state.walletsListConfig.wallets.map {
walletHiddenBalanceStateConverter.updateHiddenState(it, value)
}.toImmutableList(),
),
)
state.copy(isBalanceHidden = value)
}
else -> currentStateProvider()

View file

@ -17,12 +17,10 @@ import kotlinx.collections.immutable.persistentListOf
internal class TokenListToContentItemsConverter(
appCurrencyProvider: Provider<AppCurrency>,
isBalanceHiddenProvider: Provider<Boolean>,
private val clickIntents: WalletClickIntents,
) : Converter<TokenList, WalletTokensListState> {
private val tokenStatusConverter = CryptoCurrencyStatusToTokenItemConverter(
isBalanceHiddenProvider = isBalanceHiddenProvider,
appCurrencyProvider = appCurrencyProvider,
clickIntents = clickIntents,
)

View file

@ -17,12 +17,10 @@ internal class TokenListToWalletStateConverter(
private val currentStateProvider: Provider<WalletState>,
private val currentWalletProvider: Provider<UserWallet>,
private val appCurrencyProvider: Provider<AppCurrency>,
private val isBalanceHiddenProvider: Provider<Boolean>,
clickIntents: WalletClickIntents,
) : Converter<TokenList, WalletState> {
private val tokenListToContentConverter = TokenListToContentItemsConverter(
isBalanceHiddenProvider = isBalanceHiddenProvider,
appCurrencyProvider = appCurrencyProvider,
clickIntents = clickIntents,
)
@ -50,7 +48,6 @@ internal class TokenListToWalletStateConverter(
currentState = selectedWalletCard,
currentWalletProvider = currentWalletProvider,
appCurrencyProvider = appCurrencyProvider,
isBalanceHiddenProvider = isBalanceHiddenProvider,
)
return walletsListConfig.copy(

View file

@ -1,44 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState
internal class WalletHiddenBalanceStateConverter {
fun updateHiddenState(walletCardState: WalletCardState, hiddenBalance: Boolean): WalletCardState {
return when {
walletCardState is WalletCardState.Content && hiddenBalance -> {
contentToHidden(walletCardState)
}
walletCardState is WalletCardState.HiddenContent && !hiddenBalance -> {
hiddenToContent(walletCardState)
}
else -> walletCardState
}
}
private fun contentToHidden(content: WalletCardState.Content): WalletCardState.HiddenContent {
return WalletCardState.HiddenContent(
id = content.id,
title = content.title,
additionalInfo = content.additionalInfo,
imageResId = content.imageResId,
onRenameClick = content.onRenameClick,
onDeleteClick = content.onDeleteClick,
balance = content.balance,
cardCount = content.cardCount,
)
}
private fun hiddenToContent(hiddenContent: WalletCardState.HiddenContent): WalletCardState.Content {
return WalletCardState.Content(
id = hiddenContent.id,
title = hiddenContent.title,
additionalInfo = hiddenContent.additionalInfo,
imageResId = hiddenContent.imageResId,
onRenameClick = hiddenContent.onRenameClick,
onDeleteClick = hiddenContent.onDeleteClick,
balance = hiddenContent.balance,
cardCount = hiddenContent.cardCount,
)
}
}

View file

@ -19,4 +19,11 @@ internal object WalletStateCache {
fun update(userWalletId: UserWalletId, state: WalletState.ContentState) {
states[userWalletId] = state
}
/** Update all content states */
fun updateAll(block: (WalletState.ContentState.() -> WalletState.ContentState)) {
states.keys.forEach {
states[it] = block(requireNotNull(states[it]))
}
}
}

View file

@ -129,7 +129,6 @@ internal class WalletViewModel @Inject constructor(
var router: InnerWalletRouter by Delegates.notNull()
private val selectedAppCurrencyFlow: StateFlow<AppCurrency> = createSelectedAppCurrencyFlow()
private var isBalanceHidden = true
private val notificationsListFactory = WalletNotificationsListFactory(
wasCardScannedUseCase = wasCardScannedUseCase,
@ -150,7 +149,6 @@ internal class WalletViewModel @Inject constructor(
wallets[requireNotNull(uiState as? WalletState.ContentState).walletsListConfig.selectedWalletIndex]
},
appCurrencyProvider = Provider(selectedAppCurrencyFlow::value),
isBalanceHiddenProvider = Provider { isBalanceHidden },
clickIntents = this,
)
@ -194,7 +192,7 @@ internal class WalletViewModel @Inject constructor(
isBalanceHiddenUseCase()
.flowWithLifecycle(owner.lifecycle)
.onEach { hidden ->
isBalanceHidden = hidden
WalletStateCache.updateAll { copySealed(isBalanceHidden = hidden) }
uiState = stateFactory.getHiddenBalanceState(isBalanceHidden = hidden)
}
.launchIn(viewModelScope)

View file

@ -126,8 +126,6 @@ internal class WalletsUpdateActionResolver(
}
previousWalletState is WalletCardState.Content &&
previousWalletState.cardCount != selectedWallet.getCardsCount() ||
previousWalletState is WalletCardState.HiddenContent &&
previousWalletState.cardCount != selectedWallet.getCardsCount() -> {
Action.UpdateWalletCardCount
}