Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-19 17:45:42 +02:00
parent 92802e6968
commit 3a4531c656
5 changed files with 97 additions and 85 deletions

View file

@ -17,9 +17,9 @@ import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.decompose.navigation.inner.InnerRouter
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
import com.tangem.core.ui.res.LocalMainBottomSheetColor
import com.tangem.core.ui.res.TangemTheme
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.markets.PreselectedMarketsInterval
import com.tangem.domain.markets.PreselectedMarketsOrder
import com.tangem.domain.markets.TokenMarketParams
import com.tangem.domain.models.earn.PreselectedEarnType
import com.tangem.domain.news.model.NewsListConfig
@ -32,8 +32,6 @@ import com.tangem.features.feed.entry.components.FeedEntryComponent
import com.tangem.features.feed.entry.components.FeedEntryRoute
import com.tangem.features.feed.model.FeedEntryModel
import com.tangem.features.feed.model.feed.FeedModelClickIntents
import com.tangem.domain.markets.PreselectedMarketsInterval
import com.tangem.domain.markets.PreselectedMarketsOrder
import com.tangem.features.feed.model.market.list.state.MarketsListUM
import com.tangem.features.feed.model.market.list.state.SortByTypeUM
import com.tangem.features.feed.ui.EntryContent
@ -199,26 +197,21 @@ internal class DefaultFeedEntryComponent @AssistedInject constructor(
@Composable
override fun Content(modifier: Modifier) {
val background = TangemTheme.colors.background.tertiary
CompositionLocalProvider(
LocalMainBottomSheetColor provides remember(background) { mutableStateOf(background) },
) {
val bottomSheetState = remember {
derivedStateOf { BottomSheetState.EXPANDED }
}
BackHandler {
router.pop()
}
EntryContent(
bottomSheetState = bottomSheetState,
stackState = stack.subscribeAsState(),
onHeaderSizeChange = {},
onExpandSheet = {},
isOpenedInBottomSheet = false,
)
val bottomSheetState = remember {
derivedStateOf { BottomSheetState.EXPANDED }
}
BackHandler {
router.pop()
}
EntryContent(
bottomSheetState = bottomSheetState,
stackState = stack.subscribeAsState(),
onHeaderSizeChange = {},
onExpandSheet = {},
isOpenedInBottomSheet = false,
)
}
private fun onChildBack() {

View file

@ -148,11 +148,13 @@ private fun EntryContentV2(
}
val effectiveTopBarHeight = topBarHeight + statusBarInset
val effectiveFadeHeight = fadeHeightOverride.value ?: effectiveTopBarHeight
val isTopFadeSolid = isOpenedInBottomSheet && bottomSheetState.value == BottomSheetState.COLLAPSED
Surface(color = background, contentColor = background) {
CompositionLocalProvider(
LocalHazeState provides hazeState,
LocalContentTopFadeHeightOverride provides fadeHeightOverride,
LocalBottomSheetTopFadeSolid provides isTopFadeSolid,
) {
Box(modifier = Modifier.fillMaxSize()) {
ContentBlock(
@ -240,8 +242,8 @@ private fun BoxScope.ContentBlock(
.hazeSourceTangem(zIndex = 0f, state = LocalHazeState.current)
.topFade(
height = effectiveFadeHeight,
color = TangemTheme.colors2.surface.level2.copy(BASE_FADE_LEVEL),
solidStop = .6f,
color = feedTopFadeColor(TangemTheme.colors2.surface.level2.copy(BASE_FADE_LEVEL)),
solidStop = feedTopFadeSolidStop(),
),
contentPadding = PaddingValues(top = topBarHeight),
bottomSheetState = bottomSheetState,

View file

@ -0,0 +1,48 @@
package com.tangem.features.feed.ui
import androidx.compose.runtime.Composable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.graphics.Color
import com.tangem.core.ui.res.LocalMainBottomSheetColor
import com.tangem.features.feed.ui.utils.FadeConstants.FIRST_STEP
import com.tangem.features.feed.ui.utils.FadeConstants.FIRST_STEP_FADE_LEVEL
/**
* When `true`, top fade areas render as a solid color (no gradient) used while the wallet
* bottom sheet is collapsed so the peek header matches [LocalMainBottomSheetColor].
*/
internal val LocalBottomSheetTopFadeSolid = compositionLocalOf { false }
private const val EXPANDED_TOP_FADE_SOLID_STOP = 0.6f
private const val COLLAPSED_TOP_FADE_SOLID_STOP = 1f
@Composable
internal fun feedTopFadeSolidStop(): Float {
return if (LocalBottomSheetTopFadeSolid.current) {
COLLAPSED_TOP_FADE_SOLID_STOP
} else {
EXPANDED_TOP_FADE_SOLID_STOP
}
}
@Composable
internal fun feedTopFadeColor(defaultFadeColor: Color): Color {
return if (LocalBottomSheetTopFadeSolid.current) {
LocalMainBottomSheetColor.current.value
} else {
defaultFadeColor
}
}
@Composable
internal fun feedTopFadeColorStops(defaultFadeColor: Color): Array<Pair<Float, Color>> {
if (LocalBottomSheetTopFadeSolid.current) {
val solidColor = LocalMainBottomSheetColor.current.value
return arrayOf(0f to solidColor, 1f to solidColor)
}
return arrayOf(
0f to defaultFadeColor,
FIRST_STEP to defaultFadeColor.copy(FIRST_STEP_FADE_LEVEL),
1f to Color.Transparent,
)
}

View file

@ -13,7 +13,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
@ -29,23 +28,22 @@ import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
import com.tangem.core.ui.components.fields.SearchBar
import com.tangem.core.ui.components.fields.TangemSearchBarDefaults
import com.tangem.core.ui.components.fields.entity.SearchBarUM
import com.tangem.core.ui.components.haze.hazeSourceTangem
import com.tangem.core.ui.event.consumedEvent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.*
import com.tangem.core.ui.res.LocalMainBottomSheetColor
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.features.feed.impl.R
import com.tangem.features.feed.model.market.list.state.*
import com.tangem.features.feed.ui.LocalContentTopFadeHeightOverride
import com.tangem.features.feed.ui.feed.state.FeedListSearchBar
import com.tangem.features.feed.ui.feedTopFadeColorStops
import com.tangem.features.feed.ui.market.list.components.MarketsListLazyColumn
import com.tangem.features.feed.ui.market.list.components.MarketsListSortByBottomSheet
import com.tangem.features.feed.ui.market.list.components.Options
import com.tangem.features.feed.ui.utils.FadeConstants.BASE_FADE_LEVEL
import com.tangem.features.feed.ui.utils.FadeConstants.FIRST_STEP
import com.tangem.features.feed.ui.utils.FadeConstants.FIRST_STEP_FADE_LEVEL
import dev.chrisbanes.haze.rememberHazeState
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay
@ -109,19 +107,16 @@ internal fun TopBarWithSearch(
@Composable
internal fun MarketsList(contentPadding: PaddingValues, state: MarketsListUM, modifier: Modifier = Modifier) {
val background = LocalMainBottomSheetColor.current.value
// should use here new overrided haze state cause on level upper already applied
CompositionLocalProvider(LocalHazeState provides rememberHazeState()) {
Column(
modifier = modifier
.fillMaxSize()
.imePadding()
.drawBehind { drawRect(background) },
) {
Content(state = state, contentPadding = contentPadding)
}
MarketsListSortByBottomSheet(config = state.sortByBottomSheet)
KeyboardEvents(isSortByBottomSheetShown = state.sortByBottomSheet.isShown)
Column(
modifier = modifier
.fillMaxSize()
.imePadding()
.drawBehind { drawRect(background) },
) {
Content(state = state, contentPadding = contentPadding)
}
MarketsListSortByBottomSheet(config = state.sortByBottomSheet)
KeyboardEvents(isSortByBottomSheetShown = state.sortByBottomSheet.isShown)
}
@Suppress("LongMethod")
@ -209,30 +204,18 @@ private fun ColumnScope.ContentV2(contentPadding: PaddingValues, state: MarketsL
val fadeColor = TangemTheme.colors2.surface.level2.copy(BASE_FADE_LEVEL)
val topPadding = contentPadding.calculateTopPadding()
val centralFadeOverride = LocalContentTopFadeHeightOverride.current
DisposableEffect(centralFadeOverride) {
centralFadeOverride?.value = 0.dp
onDispose { centralFadeOverride?.value = null }
}
Box(modifier = Modifier.fillMaxSize()) {
ItemsList(
topContentPadding = contentPadding.calculateTopPadding() + optionsHeight,
modifier = Modifier
.align(Alignment.TopStart)
.hazeSourceTangem(zIndex = 1f),
modifier = Modifier.align(Alignment.TopStart),
topContentPadding = topPadding + optionsHeight,
scrolledState = scrolledState,
isInSearchMode = state.isInSearchMode,
state = state.list,
)
TopFade(
modifier = Modifier.padding(top = contentPadding.calculateTopPadding()),
colorStops = arrayOf(
0f to fadeColor,
FIRST_STEP to fadeColor.copy(FIRST_STEP_FADE_LEVEL),
1f to Color.Transparent,
),
height = 20.dp + optionsHeight,
modifier = Modifier.padding(top = topPadding),
colorStops = feedTopFadeColorStops(fadeColor),
height = TangemTheme.dimens2.x4 + optionsHeight,
)
Options(
modifier = Modifier

View file

@ -9,7 +9,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
@ -18,7 +17,6 @@ import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.components.TopFade
import com.tangem.core.ui.components.chip.Chip
import com.tangem.core.ui.components.chip.entity.ChipUM
import com.tangem.core.ui.components.haze.hazeSourceTangem
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.ds.tabs.TangemTab
import com.tangem.core.ui.event.EventEffect
@ -27,14 +25,12 @@ import com.tangem.core.ui.res.LocalMainBottomSheetColor
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.feed.ui.LocalContentTopFadeHeightOverride
import com.tangem.features.feed.ui.feed.components.articles.ArticleConfigUM
import com.tangem.features.feed.ui.feedTopFadeColorStops
import com.tangem.features.feed.ui.news.list.components.NewsListLazyColumn
import com.tangem.features.feed.ui.news.list.state.NewsListState
import com.tangem.features.feed.ui.news.list.state.NewsListUM
import com.tangem.features.feed.ui.utils.FadeConstants.BASE_FADE_LEVEL
import com.tangem.features.feed.ui.utils.FadeConstants.FIRST_STEP
import com.tangem.features.feed.ui.utils.FadeConstants.FIRST_STEP_FADE_LEVEL
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableSet
@ -44,6 +40,7 @@ internal fun NewsListContent(contentPadding: PaddingValues, state: NewsListUM, m
NewsListContentV2(
contentPadding = contentPadding,
state = state,
modifier = modifier,
)
} else {
NewsListContentV1(
@ -93,33 +90,25 @@ internal fun NewsListContentV1(contentPadding: PaddingValues, state: NewsListUM,
}
@Composable
internal fun NewsListContentV2(contentPadding: PaddingValues, state: NewsListUM) {
internal fun NewsListContentV2(contentPadding: PaddingValues, state: NewsListUM, modifier: Modifier = Modifier) {
val background = LocalMainBottomSheetColor.current.value
val lazyListState = rememberLazyListState()
val chipsListState = rememberLazyListState()
var chipsHeight by remember { mutableStateOf(0.dp) }
val density = LocalDensity.current
val fadeColor = TangemTheme.colors2.surface.level2.copy(BASE_FADE_LEVEL)
val topPadding = contentPadding.calculateTopPadding()
val centralFadeOverride = LocalContentTopFadeHeightOverride.current
DisposableEffect(centralFadeOverride) {
centralFadeOverride?.value = 0.dp
onDispose { centralFadeOverride?.value = null }
}
val fadeColor = TangemTheme.colors2.surface.level2.copy(BASE_FADE_LEVEL)
ScrollChipsToSelected(state = state, chipsListState = chipsListState)
Box(
modifier = Modifier
modifier = modifier
.fillMaxSize()
.background(background),
) {
NewsListLazyColumn(
topContentPadding = contentPadding.calculateTopPadding() + 16.dp + chipsHeight,
modifier = Modifier
.align(Alignment.TopStart)
.hazeSourceTangem(zIndex = 0f),
topContentPadding = topPadding + TangemTheme.dimens2.x4 + chipsHeight,
modifier = Modifier.align(Alignment.TopStart),
newsListState = state.newsListState,
listOfArticles = state.listOfArticles,
lazyListState = lazyListState,
@ -127,12 +116,9 @@ internal fun NewsListContentV2(contentPadding: PaddingValues, state: NewsListUM)
)
TopFade(
colorStops = arrayOf(
0f to fadeColor,
FIRST_STEP to fadeColor.copy(FIRST_STEP_FADE_LEVEL),
1f to Color.Transparent,
),
height = topPadding + TangemTheme.dimens2.x5 + chipsHeight,
modifier = Modifier.padding(top = topPadding),
colorStops = feedTopFadeColorStops(fadeColor),
height = TangemTheme.dimens2.x4 + chipsHeight,
)
LazyRow(