Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-16 15:06:01 +01:00
parent 349969a2e3
commit 61a1a25067
4 changed files with 98 additions and 79 deletions

View file

@ -174,7 +174,12 @@ private fun Tags(tags: ImmutableList<LabelUM>, modifier: Modifier = Modifier) {
val expandIndicator = remember {
ContextualFlowRowOverflow.expandIndicator {
val remainingItems = tags.size - shownItemCount
Label(state = LabelUM(TextReference.Str("${StringsSigns.PLUS}$remainingItems")))
Label(
state = LabelUM(
text = TextReference.Str("${StringsSigns.PLUS}$remainingItems"),
maxLines = 1,
),
)
}
}
ContextualFlowRow(

View file

@ -12,6 +12,7 @@ data class LabelUM(
@DrawableRes val icon: Int? = null,
val onIconClick: (() -> Unit)? = null,
val onClick: (() -> Unit)? = null,
val maxLines: Int = Int.MAX_VALUE,
)
@Immutable

View file

@ -1,6 +1,9 @@
package com.tangem.features.feed.ui.feed
import androidx.compose.animation.*
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
@ -60,7 +63,7 @@ internal fun FeedListHeader(feedListSearchBar: FeedListSearchBar, modifier: Modi
modifier = modifier
.drawBehind { drawRect(background) }
.padding(horizontal = 16.dp)
.padding(bottom = 12.dp),
.padding(bottom = 8.dp),
)
}
@ -70,6 +73,7 @@ internal fun FeedList(state: FeedListUM, modifier: Modifier = Modifier) {
AnimatedContent(
modifier = modifier,
targetState = state.globalState,
transitionSpec = { fadeIn() togetherWith fadeOut() },
) { animatedState ->
when (animatedState) {
is GlobalFeedState.Loading -> {
@ -84,6 +88,7 @@ internal fun FeedList(state: FeedListUM, modifier: Modifier = Modifier) {
FeedListGlobalError(
onRetryClick = animatedState.onRetryClicked,
modifier = Modifier.drawBehind { drawRect(background) },
currentDate = state.currentDate,
)
}
is GlobalFeedState.Content -> {
@ -130,83 +135,67 @@ private fun FeedListContent(state: FeedListUM, modifier: Modifier = Modifier) {
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding())
.drawBehind { drawRect(background) },
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(WindowInsets.navigationBars.asPaddingValues()),
) {
SpacerH(20.dp)
DateBlock(state.currentDate)
SpacerH(32.dp)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
text = stringResourceSafe(R.string.feed_market_and_news),
style = TangemTheme.typography.h2,
color = TangemTheme.colors.text.primary1,
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
text = state.currentDate,
style = TangemTheme.typography.h2,
color = TangemTheme.colors.text.tertiary,
)
MarketBlock(
marketChart = state.marketChartConfig.marketCharts[SortByTypeUM.Rating],
feedListCallbacks = state.feedListCallbacks,
)
SpacerH(32.dp)
NewsBlock(
news = state.news,
feedListCallbacks = state.feedListCallbacks,
trendingArticle = state.trendingArticle,
)
AnimatedVisibility(state.marketChartConfig.marketCharts[SortByTypeUM.Rating] != null) {
val marketChart = remember(state.marketChartConfig.marketCharts[SortByTypeUM.Rating]) {
state.marketChartConfig.marketCharts[SortByTypeUM.Rating]
}
if (marketChart != null) {
MarketBlock(
marketChart = marketChart,
feedListCallbacks = state.feedListCallbacks,
)
}
}
NewsBlock(
news = state.news,
feedListCallbacks = state.feedListCallbacks,
trendingArticle = state.trendingArticle,
)
MarketPulseBlock(
marketChartConfig = state.marketChartConfig,
feedListCallbacks = state.feedListCallbacks,
)
}
MarketPulseBlock(
marketChartConfig = state.marketChartConfig,
feedListCallbacks = state.feedListCallbacks,
)
}
}
@Composable
private fun MarketBlock(marketChart: MarketChartUM, feedListCallbacks: FeedListCallbacks) {
Column(modifier = Modifier.fillMaxWidth()) {
Header(
title = {
Text(
text = stringResourceSafe(R.string.markets_common_title),
style = TangemTheme.typography.h3,
color = TangemTheme.colors.text.primary1,
)
},
onSeeAllClick = { feedListCallbacks.onMarketOpenClick(SortByTypeUM.Rating) },
)
private fun MarketBlock(marketChart: MarketChartUM?, feedListCallbacks: FeedListCallbacks) {
AnimatedContent(
targetState = marketChart,
label = "MarketBlockChartAnimation",
transitionSpec = { fadeIn() togetherWith fadeOut() },
) { currentChart ->
when (currentChart) {
is MarketChartUM.Content,
MarketChartUM.Loading,
is MarketChartUM.LoadingError,
-> {
Column(modifier = Modifier.fillMaxWidth()) {
Header(
title = {
Text(
text = stringResourceSafe(R.string.markets_common_title),
style = TangemTheme.typography.h3,
color = TangemTheme.colors.text.primary1,
)
},
onSeeAllClick = { feedListCallbacks.onMarketOpenClick(SortByTypeUM.Rating) },
)
SpacerH(12.dp)
SpacerH(12.dp)
Charts(
onItemClick = feedListCallbacks.onMarketItemClick,
modifier = Modifier.padding(horizontal = 16.dp),
marketChart = marketChart,
)
Charts(
onItemClick = feedListCallbacks.onMarketItemClick,
modifier = Modifier.padding(horizontal = 16.dp),
marketChart = currentChart,
)
SpacerH(32.dp)
SpacerH(32.dp)
}
}
null -> Unit
}
}
}
@ -490,16 +479,19 @@ private fun FilterChip(sortByTypeUM: SortByTypeUM, isSelected: Boolean, onClick:
}
@Composable
private fun FeedListGlobalError(onRetryClick: () -> Unit, modifier: Modifier = Modifier) {
private fun FeedListGlobalError(onRetryClick: () -> Unit, currentDate: String, modifier: Modifier = Modifier) {
val background = LocalMainBottomSheetColor.current.value
Box(
modifier = modifier
.fillMaxSize()
.drawBehind { drawRect(background) }
.padding(16.dp),
contentAlignment = Alignment.Center,
) {
UnableToLoadData(onRetryClick = onRetryClick)
Column(modifier) {
DateBlock(currentDate)
Box(
modifier = Modifier
.fillMaxSize()
.drawBehind { drawRect(background) }
.padding(16.dp),
contentAlignment = Alignment.Center,
) {
UnableToLoadData(onRetryClick = onRetryClick)
}
}
}
@ -519,7 +511,6 @@ private fun NewsErrorBlock(onRetryClick: () -> Unit) {
onSeeAllClick = {},
)
SpacerH(12.dp)
BlockCard(
modifier = Modifier.padding(horizontal = 16.dp),
colors = TangemBlockCardColors.copy(containerColor = TangemTheme.colors.background.action),
@ -531,9 +522,31 @@ private fun NewsErrorBlock(onRetryClick: () -> Unit) {
.padding(vertical = 35.dp, horizontal = 10.dp),
)
}
SpacerH(32.dp)
}
}
@Composable
private fun ColumnScope.DateBlock(currentDate: String) {
SpacerH(20.dp)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
text = stringResourceSafe(R.string.feed_market_and_news),
style = TangemTheme.typography.h2,
color = TangemTheme.colors.text.primary1,
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
text = currentDate,
style = TangemTheme.typography.h2,
color = TangemTheme.colors.text.tertiary,
)
}
private const val DEFAULT_CHART_SIZE_IN_MARKET = 5
private const val FOURTH_ITEM_INDEX = 3
private const val GRADIENT_START = 0f

View file

@ -83,7 +83,7 @@ internal fun TopBarWithSearch(
modifier = Modifier
.drawBehind { drawRect(background) }
.padding(horizontal = 16.dp)
.padding(bottom = 12.dp),
.padding(bottom = 8.dp),
state = marketsSearchBar.searchBarUM,
colors = TangemSearchBarDefaults.defaultTextFieldColors.copy(
focusedContainerColor = TangemTheme.colors.field.focused,