Updated on 2026-08-14
This commit is contained in:
parent
03ae5e3331
commit
a54c3ce6ea
17 changed files with 269 additions and 241 deletions
|
|
@ -1,8 +1,6 @@
|
|||
package com.tangem.common.ui.markets.tokenselector
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.EaseOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
|
|
@ -10,6 +8,7 @@ import androidx.compose.material3.Icon
|
|||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
|
|
@ -19,19 +18,18 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.Fade
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetType
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.components.haze.hazeSourceTangem
|
||||
import com.tangem.core.ui.components.topFade
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||
import com.tangem.core.ui.extensions.clickableSingle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
import dev.chrisbanes.haze.HazeState
|
||||
import dev.chrisbanes.haze.rememberHazeState
|
||||
|
||||
|
|
@ -84,8 +82,11 @@ private fun TokenSelectorContent(
|
|||
Box(modifier = modifier.fillMaxWidth()) {
|
||||
val bottomFadeReserve = if (embedded) 0.dp else TangemTheme.dimens2.x10
|
||||
val bottomListPadding = bottomFadeReserve + scrollBottomInset
|
||||
val topFadeColor = TangemTheme.colors2.surface.level2.copy(alpha = .95f)
|
||||
LazyColumn(
|
||||
modifier = Modifier.hazeSourceTangem(state = hazeState, 1f),
|
||||
modifier = Modifier
|
||||
.hazeSourceTangem(state = hazeState, 1f)
|
||||
.topFade(height = topBarHeight, color = topFadeColor, solidStop = .6f),
|
||||
contentPadding = PaddingValues(
|
||||
start = TangemTheme.dimens2.x4,
|
||||
end = TangemTheme.dimens2.x4,
|
||||
|
|
@ -102,12 +103,6 @@ private fun TokenSelectorContent(
|
|||
hazeState = hazeState,
|
||||
onChangeHeight = { topBarHeight = it },
|
||||
)
|
||||
Fade(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.BottomCenter),
|
||||
height = TangemTheme.dimens2.x10,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -119,7 +114,6 @@ private fun TokenSelectorSheetTopBar(
|
|||
onChangeHeight: (Dp) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val bgColor = TangemTheme.colors2.surface.level2
|
||||
val density = LocalDensity.current
|
||||
TangemTopBar(
|
||||
modifier = modifier
|
||||
|
|
@ -129,15 +123,6 @@ private fun TokenSelectorSheetTopBar(
|
|||
onChangeHeight(coordinates.size.height.toDp())
|
||||
}
|
||||
}
|
||||
}
|
||||
.hazeEffectTangem(state = hazeState) {
|
||||
backgroundColor = bgColor
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .55f,
|
||||
endIntensity = 0f,
|
||||
preferPerformance = true,
|
||||
easing = EaseOut,
|
||||
)
|
||||
},
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
title = resourceReference(R.string.markets_search_portfolio_header),
|
||||
|
|
@ -148,10 +133,8 @@ private fun TokenSelectorSheetTopBar(
|
|||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x11)
|
||||
.background(
|
||||
color = TangemTheme.colors2.button.backgroundSecondary,
|
||||
shape = CircleShape,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.hazeEffectTangem(state = hazeState) { blurRadius = 8.dp }
|
||||
.clickableSingle(onClick = onDismiss)
|
||||
.padding(TangemTheme.dimens2.x2_5),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,18 @@ fun BottomFade(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TopFade(vararg colorStops: Pair<Float, Color>, modifier: Modifier = Modifier, height: Dp = 100.dp) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(height)
|
||||
.background(
|
||||
brush = Brush.verticalGradient(colorStops = colorStops),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A composable that draws a fade effect at the bottom of the screen. Used on screens with a list of repeating
|
||||
* elements and floating button at the bottom of the screen.
|
||||
|
|
|
|||
|
|
@ -25,10 +25,8 @@ fun Modifier.edgeFade(
|
|||
isVisible: Boolean = true,
|
||||
animationSpec: AnimationSpec<Dp>? = null,
|
||||
color: Color = TangemTheme.colors.background.secondary,
|
||||
solidStop: Float = 0f,
|
||||
): Modifier = composed {
|
||||
require(value = size > 0.dp) {
|
||||
"Size must be greater than '0'"
|
||||
}
|
||||
val animatedSize = animationSpec?.let { spec ->
|
||||
animateDpAsState(
|
||||
targetValue = if (isVisible) size else 0.dp,
|
||||
|
|
@ -45,6 +43,7 @@ fun Modifier.edgeFade(
|
|||
|
||||
val staticSizePx = if (isVisible) size.toPx() else 0f
|
||||
val sizePx = animatedSize?.value?.toPx() ?: staticSizePx
|
||||
if (sizePx <= 0f) return@forEach
|
||||
|
||||
val fraction = when (side) {
|
||||
FadePosition.LEFT, FadePosition.RIGHT -> sizePx / this.size.width
|
||||
|
|
@ -54,6 +53,7 @@ fun Modifier.edgeFade(
|
|||
drawRect(
|
||||
brush = Brush.linearGradient(
|
||||
0f to color,
|
||||
solidStop.coerceIn(minimumValue = 0f, maximumValue = 1f) * fraction to color,
|
||||
fraction to Color.Transparent,
|
||||
start = start,
|
||||
end = end,
|
||||
|
|
@ -74,6 +74,25 @@ fun Modifier.bottomFade(
|
|||
color = color,
|
||||
)
|
||||
|
||||
/**
|
||||
* Draws a vertical gradient fade over the top edge of the content.
|
||||
*
|
||||
* @param height the fade region height
|
||||
* @param color the solid color at the top edge that fades to transparent at the bottom of the region
|
||||
* @param solidStop fraction (0..1) of [height] kept fully [color] before the fade starts
|
||||
*/
|
||||
@Composable
|
||||
fun Modifier.topFade(
|
||||
height: Dp,
|
||||
color: Color = TangemTheme.colors.background.secondary,
|
||||
solidStop: Float = 0f,
|
||||
): Modifier = edgeFade(
|
||||
FadePosition.TOP,
|
||||
size = height,
|
||||
color = color,
|
||||
solidStop = solidStop,
|
||||
)
|
||||
|
||||
enum class FadePosition {
|
||||
TOP, BOTTOM, LEFT, RIGHT
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,9 +46,11 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.ds.button.GhostTangemButton
|
||||
import com.tangem.core.ui.ds.button.TangemButtonSize
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
|
|
@ -177,7 +179,11 @@ private fun DecorationBox(
|
|||
contentAlignment = BiasAlignment(horizontalBias = alignmentBias, verticalBias = 0f),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.background(color, shape.toShape())
|
||||
.clip(shape.toShape())
|
||||
.background(color)
|
||||
.hazeEffectTangem {
|
||||
blurRadius = 8.dp
|
||||
}
|
||||
.padding(TangemTheme.dimens2.x3),
|
||||
) {
|
||||
Row(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.tangem.features.feed.components.earn
|
||||
|
||||
import androidx.compose.animation.core.EaseOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
|
@ -11,9 +9,10 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
|
|
@ -41,7 +40,6 @@ import com.tangem.features.feed.model.earn.EarnModel
|
|||
import com.tangem.features.feed.model.earn.analytics.EarnSource
|
||||
import com.tangem.features.feed.ui.components.FeedSearchBar
|
||||
import com.tangem.features.feed.ui.earn.EarnContent
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
|
||||
internal class DefaultEarnComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
|
|
@ -66,16 +64,6 @@ internal class DefaultEarnComponent(
|
|||
FeedSearchBar(
|
||||
isSearchBarClickable = bottomSheetState.value == BottomSheetState.EXPANDED,
|
||||
feedListSearchBar = state.feedListSearchBar,
|
||||
modifier = Modifier
|
||||
.drawBehind { drawRect(background) }
|
||||
.hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .55f,
|
||||
endIntensity = 0f,
|
||||
preferPerformance = true,
|
||||
easing = EaseOut,
|
||||
)
|
||||
},
|
||||
startContent = {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_back_28),
|
||||
|
|
@ -83,10 +71,8 @@ internal class DefaultEarnComponent(
|
|||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x11)
|
||||
.background(
|
||||
color = TangemTheme.colors2.button.backgroundSecondary,
|
||||
shape = CircleShape,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.hazeEffectTangem { blurRadius = 8.dp }
|
||||
.clickableSingle(
|
||||
onClick = state.onBackClick,
|
||||
enabled = bottomSheetState.value == BottomSheetState.EXPANDED,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.tangem.features.feed.components.market.details
|
||||
|
||||
import androidx.compose.animation.core.EaseOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
|
@ -12,8 +10,10 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.LifecycleStartEffect
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
|
|
@ -50,7 +50,6 @@ import com.tangem.features.feed.model.market.details.analytics.MarketDetailsAnal
|
|||
import com.tangem.features.feed.model.market.details.state.TokenNetworksState
|
||||
import com.tangem.features.feed.ui.market.detailed.MarketsTokenDetailsContent
|
||||
import com.tangem.features.feed.ui.market.detailed.MarketsTokenDetailsTopBar
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.Serializable
|
||||
|
|
@ -161,14 +160,6 @@ internal class DefaultMarketsTokenDetailsComponent(
|
|||
val background = LocalMainBottomSheetColor.current.value
|
||||
if (LocalRedesignEnabled.current) {
|
||||
TangemTopBar(
|
||||
modifier = Modifier.hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .55f,
|
||||
endIntensity = 0f,
|
||||
preferPerformance = true,
|
||||
easing = EaseOut,
|
||||
)
|
||||
},
|
||||
startContent = {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_back_28),
|
||||
|
|
@ -176,10 +167,8 @@ internal class DefaultMarketsTokenDetailsComponent(
|
|||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x11)
|
||||
.background(
|
||||
color = TangemTheme.colors2.button.backgroundSecondary,
|
||||
shape = CircleShape,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.hazeEffectTangem { blurRadius = 8.dp }
|
||||
.clickableSingle(
|
||||
onClick = { params.onBackClicked() },
|
||||
enabled = bottomSheetState.value == BottomSheetState.EXPANDED,
|
||||
|
|
@ -194,10 +183,8 @@ internal class DefaultMarketsTokenDetailsComponent(
|
|||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x11)
|
||||
.background(
|
||||
color = TangemTheme.colors2.button.backgroundSecondary,
|
||||
shape = CircleShape,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.hazeEffectTangem { blurRadius = 8.dp }
|
||||
.clickableSingle(
|
||||
onClick = state.onShareClick,
|
||||
enabled = bottomSheetState.value == BottomSheetState.EXPANDED,
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.LifecycleStartEffect
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
|
|
@ -34,7 +35,6 @@ import com.tangem.features.feed.model.market.list.state.SortByTypeUM
|
|||
import com.tangem.features.feed.ui.components.FeedSearchBar
|
||||
import com.tangem.features.feed.ui.market.list.MarketsList
|
||||
import com.tangem.features.feed.ui.market.list.TopBarWithSearch
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
internal class DefaultMarketsTokenListComponent(
|
||||
|
|
@ -54,21 +54,13 @@ internal class DefaultMarketsTokenListComponent(
|
|||
override fun Title(bottomSheetState: State<BottomSheetState>) {
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
val bsState by bottomSheetState
|
||||
val background = LocalMainBottomSheetColor.current.value
|
||||
|
||||
if (LocalRedesignEnabled.current) {
|
||||
val background = LocalMainBottomSheetColor.current.value
|
||||
FeedSearchBar(
|
||||
isSearchBarClickable = bottomSheetState.value == BottomSheetState.EXPANDED,
|
||||
feedListSearchBar = state.feedListSearchBar,
|
||||
modifier = Modifier
|
||||
.drawBehind { drawRect(background) }
|
||||
.hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .55f,
|
||||
endIntensity = .2f,
|
||||
preferPerformance = true,
|
||||
)
|
||||
},
|
||||
modifier = Modifier.background(background.copy(alpha = .95f)),
|
||||
startContent = {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_back_28),
|
||||
|
|
@ -76,10 +68,8 @@ internal class DefaultMarketsTokenListComponent(
|
|||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x11)
|
||||
.background(
|
||||
color = TangemTheme.colors2.button.backgroundSecondary,
|
||||
shape = CircleShape,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.hazeEffectTangem { blurRadius = 8.dp }
|
||||
.clickableSingle(
|
||||
onClick = clickIntents.onBackClicked,
|
||||
enabled = bottomSheetState.value == BottomSheetState.EXPANDED,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.tangem.features.feed.components.news.details
|
||||
|
||||
import androidx.compose.animation.core.EaseOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
|
@ -11,8 +9,10 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
|
|
@ -34,7 +34,6 @@ import com.tangem.domain.news.model.NewsListConfig
|
|||
import com.tangem.features.feed.model.news.details.NewsDetailsModel
|
||||
import com.tangem.features.feed.ui.news.details.NewsDetailsContent
|
||||
import com.tangem.features.feed.ui.news.details.state.ArticlesStateUM
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
internal class DefaultNewsDetailsComponent(
|
||||
|
|
@ -50,14 +49,6 @@ internal class DefaultNewsDetailsComponent(
|
|||
val state by newsDetailsModel.state.collectAsStateWithLifecycle()
|
||||
if (LocalRedesignEnabled.current) {
|
||||
TangemTopBar(
|
||||
modifier = Modifier.hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .55f,
|
||||
endIntensity = 0f,
|
||||
preferPerformance = true,
|
||||
easing = EaseOut,
|
||||
)
|
||||
},
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
startContent = {
|
||||
Icon(
|
||||
|
|
@ -66,10 +57,8 @@ internal class DefaultNewsDetailsComponent(
|
|||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x11)
|
||||
.background(
|
||||
color = TangemTheme.colors2.button.backgroundSecondary,
|
||||
shape = CircleShape,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.hazeEffectTangem { blurRadius = 8.dp }
|
||||
.clickableSingle(
|
||||
onClick = state.onBackClick,
|
||||
enabled = bottomSheetState.value == BottomSheetState.EXPANDED,
|
||||
|
|
@ -84,10 +73,8 @@ internal class DefaultNewsDetailsComponent(
|
|||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x11)
|
||||
.background(
|
||||
color = TangemTheme.colors2.button.backgroundSecondary,
|
||||
shape = CircleShape,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.hazeEffectTangem { blurRadius = 8.dp }
|
||||
.clickableSingle(
|
||||
onClick = state.onShareClick,
|
||||
enabled = bottomSheetState.value == BottomSheetState.EXPANDED &&
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
|
|
@ -32,7 +34,6 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
import com.tangem.domain.news.model.NewsListConfig
|
||||
import com.tangem.features.feed.model.news.list.NewsListModel
|
||||
import com.tangem.features.feed.ui.news.list.NewsListContent
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
internal class DefaultNewsListComponent(
|
||||
|
|
@ -48,14 +49,7 @@ internal class DefaultNewsListComponent(
|
|||
val state by newsListModel.state.collectAsStateWithLifecycle()
|
||||
if (LocalRedesignEnabled.current) {
|
||||
TangemTopBar(
|
||||
modifier = Modifier.hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .55f,
|
||||
endIntensity = .2f,
|
||||
preferPerformance = true,
|
||||
)
|
||||
backgroundColor = background
|
||||
},
|
||||
modifier = Modifier.background(background.copy(alpha = .95f)),
|
||||
title = resourceReference(R.string.common_news),
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
startContent = {
|
||||
|
|
@ -65,10 +59,8 @@ internal class DefaultNewsListComponent(
|
|||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x11)
|
||||
.background(
|
||||
color = TangemTheme.colors2.button.backgroundSecondary,
|
||||
shape = CircleShape,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.hazeEffectTangem { blurRadius = 8.dp }
|
||||
.clickableSingle(
|
||||
onClick = state.onBackClick,
|
||||
enabled = bottomSheetState.value == BottomSheetState.EXPANDED,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.features.feed.components.search
|
||||
|
||||
import androidx.compose.animation.core.EaseOut
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -13,7 +12,6 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
|
||||
import com.tangem.core.ui.ds.field.search.TangemFieldShape
|
||||
|
|
@ -25,7 +23,6 @@ import com.tangem.domain.markets.TokenMarketParams
|
|||
import com.tangem.features.feed.model.search.SearchModel
|
||||
import com.tangem.features.feed.ui.search.SearchContent
|
||||
import com.tangem.features.feed.ui.search.state.SearchCallbacks
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
|
||||
internal class DefaultSearchComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
|
|
@ -53,14 +50,6 @@ internal class DefaultSearchComponent(
|
|||
}
|
||||
|
||||
TangemTopBar(
|
||||
modifier = Modifier.hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .55f,
|
||||
endIntensity = 0f,
|
||||
preferPerformance = true,
|
||||
easing = EaseOut,
|
||||
)
|
||||
},
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
reserveSlotSpace = false,
|
||||
content = {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.arkivanov.decompose.extensions.compose.stack.Children
|
|||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||
import com.tangem.core.ui.components.haze.hazeSourceTangem
|
||||
import com.tangem.core.ui.components.topFade
|
||||
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
|
||||
import com.tangem.core.ui.extensions.conditionalCompose
|
||||
import com.tangem.core.ui.res.LocalHazeState
|
||||
|
|
@ -26,10 +27,19 @@ import com.tangem.core.ui.res.LocalRedesignEnabled
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.WindowInsetsZero
|
||||
import com.tangem.features.feed.components.FeedEntryChildFactory
|
||||
import com.tangem.features.feed.ui.utils.FadeConstants.BASE_FADE_LEVEL
|
||||
import com.tangem.features.feed.ui.utils.contentFeedEntryStackAnimation
|
||||
import com.tangem.features.feed.ui.utils.topBarFeedEntryAnimatedContentTransitionSpec
|
||||
import dev.chrisbanes.haze.rememberHazeState
|
||||
|
||||
/**
|
||||
|
||||
* When the value is `null` (default), the fade covers `topBarHeight`. A screen with sticky chrome
|
||||
* (e.g. category chips, sort options) can set this to `0.dp` to disable the centralized fade and
|
||||
* apply its own fade on its inner haze source covering the full sticky header (topbar + chrome).
|
||||
*/
|
||||
internal val LocalContentTopFadeHeightOverride = compositionLocalOf<MutableState<Dp?>?> { null }
|
||||
|
||||
@OptIn(ExperimentalDecomposeApi::class)
|
||||
@Composable
|
||||
internal fun EntryContent(
|
||||
|
|
@ -128,75 +138,131 @@ private fun EntryContentV2(
|
|||
onExpandSheet: () -> Unit,
|
||||
isOpenedInBottomSheet: Boolean,
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
val background = LocalMainBottomSheetColor.current.value
|
||||
val animationContent = remember { contentFeedEntryStackAnimation() }
|
||||
val animationAppBar = remember(stackState) { topBarFeedEntryAnimatedContentTransitionSpec(stackState) }
|
||||
|
||||
var topBarHeight by remember { mutableStateOf(0.dp) }
|
||||
val hazeState = rememberHazeState()
|
||||
val fadeHeightOverride = remember { mutableStateOf<Dp?>(null) }
|
||||
val effectiveFadeHeight = fadeHeightOverride.value ?: topBarHeight
|
||||
|
||||
Surface(contentColor = background) {
|
||||
CompositionLocalProvider(LocalHazeState provides hazeState) {
|
||||
CompositionLocalProvider(
|
||||
LocalHazeState provides hazeState,
|
||||
LocalContentTopFadeHeightOverride provides fadeHeightOverride,
|
||||
) {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
Children(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
stack = stackState.value,
|
||||
animation = animationContent,
|
||||
) { child ->
|
||||
child.instance.Content(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.conditionalCompose(
|
||||
condition = !isOpenedInBottomSheet,
|
||||
modifier = {
|
||||
padding(top = topBarHeight)
|
||||
},
|
||||
)
|
||||
.hazeSourceTangem(zIndex = 0f, state = hazeState),
|
||||
contentPadding = PaddingValues(
|
||||
top = if (isOpenedInBottomSheet) topBarHeight else TangemTheme.dimens2.x2_5,
|
||||
),
|
||||
bottomSheetState = bottomSheetState,
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.then(
|
||||
if (!isOpenedInBottomSheet) {
|
||||
Modifier.statusBarsPadding()
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
)
|
||||
.onGloballyPositioned { coordinates ->
|
||||
if (coordinates.size.height > 0) {
|
||||
with(density) {
|
||||
val height = coordinates.size.height.toDp()
|
||||
topBarHeight = height
|
||||
onHeaderSizeChange(height)
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
AnimatedContent(
|
||||
targetState = stackState.value.active,
|
||||
transitionSpec = animationAppBar,
|
||||
contentKey = { it.key },
|
||||
label = "FeedEntryAppBar",
|
||||
) { state ->
|
||||
state.instance.Title(bottomSheetState)
|
||||
}
|
||||
CollapsedTitleClickOverlay(
|
||||
bottomSheetState = bottomSheetState,
|
||||
onExpandSheet = onExpandSheet,
|
||||
)
|
||||
}
|
||||
ContentBlock(
|
||||
bottomSheetState = bottomSheetState,
|
||||
effectiveFadeHeight = effectiveFadeHeight,
|
||||
isOpenedInBottomSheet = isOpenedInBottomSheet,
|
||||
stackState = stackState,
|
||||
topBarHeight = topBarHeight,
|
||||
)
|
||||
TitleBlock(
|
||||
bottomSheetState = bottomSheetState,
|
||||
stackState = stackState,
|
||||
onTopBarHeightChang = { dp ->
|
||||
onHeaderSizeChange(dp)
|
||||
topBarHeight = dp
|
||||
},
|
||||
isOpenedInBottomSheet = isOpenedInBottomSheet,
|
||||
onExpandSheet = onExpandSheet,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.TitleBlock(
|
||||
bottomSheetState: State<BottomSheetState>,
|
||||
stackState: State<ChildStack<FeedEntryChildFactory.Child, ComposableModularBottomSheetContentComponent>>,
|
||||
onTopBarHeightChang: (Dp) -> Unit,
|
||||
isOpenedInBottomSheet: Boolean,
|
||||
onExpandSheet: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
val animationAppBar = remember(stackState) { topBarFeedEntryAnimatedContentTransitionSpec(stackState) }
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.align(Alignment.TopStart)
|
||||
.then(
|
||||
if (!isOpenedInBottomSheet) {
|
||||
Modifier.statusBarsPadding()
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
)
|
||||
.onGloballyPositioned { coordinates ->
|
||||
if (coordinates.size.height > 0) {
|
||||
with(density) {
|
||||
val height = coordinates.size.height.toDp()
|
||||
onTopBarHeightChang(height)
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
AnimatedContent(
|
||||
targetState = stackState.value.active,
|
||||
transitionSpec = animationAppBar,
|
||||
contentKey = { it.key },
|
||||
label = "FeedEntryAppBar",
|
||||
) { state ->
|
||||
state.instance.Title(bottomSheetState)
|
||||
}
|
||||
CollapsedTitleClickOverlay(
|
||||
bottomSheetState = bottomSheetState,
|
||||
onExpandSheet = onExpandSheet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.ContentBlock(
|
||||
bottomSheetState: State<BottomSheetState>,
|
||||
effectiveFadeHeight: Dp,
|
||||
isOpenedInBottomSheet: Boolean,
|
||||
stackState: State<ChildStack<FeedEntryChildFactory.Child, ComposableModularBottomSheetContentComponent>>,
|
||||
topBarHeight: Dp,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val animationContent = remember { contentFeedEntryStackAnimation() }
|
||||
|
||||
Children(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
stack = stackState.value,
|
||||
animation = animationContent,
|
||||
) { child ->
|
||||
child.instance.Content(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.conditionalCompose(
|
||||
condition = !isOpenedInBottomSheet,
|
||||
modifier = {
|
||||
padding(top = topBarHeight)
|
||||
},
|
||||
)
|
||||
.hazeSourceTangem(zIndex = 0f, state = LocalHazeState.current)
|
||||
.conditionalCompose(
|
||||
condition = isOpenedInBottomSheet,
|
||||
modifier = {
|
||||
topFade(
|
||||
height = effectiveFadeHeight,
|
||||
color = TangemTheme.colors2.surface.level2.copy(BASE_FADE_LEVEL),
|
||||
solidStop = .6f,
|
||||
)
|
||||
},
|
||||
),
|
||||
contentPadding = PaddingValues(
|
||||
top = if (isOpenedInBottomSheet) topBarHeight else TangemTheme.dimens2.x2_5,
|
||||
),
|
||||
bottomSheetState = bottomSheetState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.CollapsedTitleClickOverlay(bottomSheetState: State<BottomSheetState>, onExpandSheet: () -> Unit) {
|
||||
if (bottomSheetState.value == BottomSheetState.COLLAPSED) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SpacerW
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||
import com.tangem.core.ui.extensions.conditional
|
||||
|
|
@ -107,7 +108,9 @@ private fun FeedSearchBarV2(
|
|||
end = if (endContent != null) TangemTheme.dimens2.x3 else 0.dp,
|
||||
)
|
||||
.clip(CircleShape)
|
||||
.background(color = TangemTheme.colors2.button.backgroundSecondary)
|
||||
.hazeEffectTangem {
|
||||
blurRadius = 8.dp
|
||||
}
|
||||
.conditional(condition = isSearchBarClickable) {
|
||||
clickable(onClick = feedListSearchBar.onBarClick)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.features.feed.ui.feed
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.core.EaseOut
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
|
|
@ -16,9 +15,7 @@ import androidx.compose.ui.platform.testTag
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.conditionalCompose
|
||||
import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -31,7 +28,6 @@ import com.tangem.features.feed.ui.feed.preview.FeedListPreviewDataProvider.crea
|
|||
import com.tangem.features.feed.ui.feed.state.FeedListSearchBar
|
||||
import com.tangem.features.feed.ui.feed.state.FeedListUM
|
||||
import com.tangem.features.feed.ui.feed.state.GlobalFeedState
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
|
||||
@Composable
|
||||
internal fun FeedListHeader(
|
||||
|
|
@ -39,26 +35,10 @@ internal fun FeedListHeader(
|
|||
feedListSearchBar: FeedListSearchBar,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val background = LocalMainBottomSheetColor.current.value
|
||||
FeedSearchBar(
|
||||
isSearchBarClickable = isSearchBarClickable,
|
||||
feedListSearchBar = feedListSearchBar,
|
||||
modifier = modifier
|
||||
.drawBehind { drawRect(background) }
|
||||
.conditionalCompose(
|
||||
condition = LocalRedesignEnabled.current,
|
||||
modifier = {
|
||||
hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .75f,
|
||||
endIntensity = 0f,
|
||||
preferPerformance = true,
|
||||
easing = EaseOut,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
.testTag(SEARCH_BAR),
|
||||
modifier = modifier.testTag(SEARCH_BAR),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ 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
|
||||
|
|
@ -32,18 +33,18 @@ 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.LocalHazeState
|
||||
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.core.ui.res.*
|
||||
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.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
|
||||
|
|
@ -205,6 +206,14 @@ private fun ColumnScope.ContentV2(contentPadding: PaddingValues, state: MarketsL
|
|||
val scrolledState = remember { mutableStateOf(false) }
|
||||
var optionsHeight 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 }
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
ItemsList(
|
||||
|
|
@ -216,10 +225,19 @@ private fun ColumnScope.ContentV2(contentPadding: PaddingValues, state: MarketsL
|
|||
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,
|
||||
)
|
||||
Options(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.padding(bottom = TangemTheme.dimens2.x4, top = contentPadding.calculateTopPadding())
|
||||
.padding(bottom = TangemTheme.dimens2.x4, top = topPadding)
|
||||
.padding(horizontal = TangemTheme.dimens2.x4)
|
||||
.onGloballyPositioned { coordinates ->
|
||||
if (coordinates.size.height > 0) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.features.feed.ui.market.list.components
|
||||
|
||||
import androidx.compose.animation.core.EaseOut
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
|
|
@ -20,14 +19,12 @@ import com.tangem.core.ui.ds.image.TangemIconUM
|
|||
import com.tangem.core.ui.ds.tabs.TangemSegmentUM
|
||||
import com.tangem.core.ui.ds.tabs.TangemSegmentedPicker
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.feed.impl.R
|
||||
import com.tangem.features.feed.model.market.list.state.MarketsListUM
|
||||
import com.tangem.features.feed.model.market.list.state.SortByMenuUM
|
||||
import com.tangem.features.feed.model.market.list.state.SortByTypeUM
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import com.tangem.core.ui.ds.button.TangemButtonIconPosition as RedesignTangemButtonIconPosition
|
||||
|
||||
|
|
@ -120,7 +117,6 @@ private fun OptionsV2(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var isShowDropdownMenu by rememberSaveable { mutableStateOf(false) }
|
||||
val background = LocalMainBottomSheetColor.current.value
|
||||
|
||||
val segmentItems = remember {
|
||||
persistentListOf(
|
||||
|
|
@ -147,16 +143,7 @@ private fun OptionsV2(
|
|||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(IntrinsicSize.Max)
|
||||
.hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .2f,
|
||||
endIntensity = 0f,
|
||||
easing = EaseOut,
|
||||
preferPerformance = true,
|
||||
)
|
||||
backgroundColor = background
|
||||
},
|
||||
.height(IntrinsicSize.Max),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
PrimaryInverseTangemButton(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.features.feed.ui.news.list
|
||||
|
||||
import androidx.compose.animation.core.EaseOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
|
|
@ -10,25 +9,32 @@ 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
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.hazeEffectTangem
|
||||
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
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
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.features.feed.ui.LocalContentTopFadeHeightOverride
|
||||
import com.tangem.features.feed.ui.feed.components.articles.ArticleConfigUM
|
||||
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 dev.chrisbanes.haze.HazeProgressive
|
||||
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
|
||||
|
||||
|
|
@ -93,6 +99,14 @@ internal fun NewsListContentV2(contentPadding: PaddingValues, state: NewsListUM)
|
|||
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 }
|
||||
}
|
||||
|
||||
ScrollChipsToSelected(state = state, chipsListState = chipsListState)
|
||||
|
||||
|
|
@ -104,33 +118,35 @@ internal fun NewsListContentV2(contentPadding: PaddingValues, state: NewsListUM)
|
|||
NewsListLazyColumn(
|
||||
topContentPadding = contentPadding.calculateTopPadding() + 16.dp + chipsHeight,
|
||||
modifier = Modifier
|
||||
.hazeSourceTangem(zIndex = 0f)
|
||||
.align(Alignment.TopStart),
|
||||
.align(Alignment.TopStart)
|
||||
.hazeSourceTangem(zIndex = 0f),
|
||||
newsListState = state.newsListState,
|
||||
listOfArticles = state.listOfArticles,
|
||||
lazyListState = lazyListState,
|
||||
onArticleClick = state.onArticleClick,
|
||||
)
|
||||
|
||||
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 + chipsHeight,
|
||||
)
|
||||
|
||||
LazyRow(
|
||||
state = chipsListState,
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.padding(top = contentPadding.calculateTopPadding(), bottom = TangemTheme.dimens2.x4)
|
||||
.padding(top = topPadding, bottom = TangemTheme.dimens2.x4)
|
||||
.onGloballyPositioned { coordinates ->
|
||||
if (coordinates.size.height > 0) {
|
||||
with(density) {
|
||||
chipsHeight = coordinates.size.height.toDp()
|
||||
}
|
||||
}
|
||||
}
|
||||
.hazeEffectTangem {
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = .2f,
|
||||
endIntensity = 0f,
|
||||
easing = EaseOut,
|
||||
preferPerformance = true,
|
||||
)
|
||||
backgroundColor = background
|
||||
},
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.features.feed.ui.utils
|
||||
|
||||
internal object FadeConstants {
|
||||
const val BASE_FADE_LEVEL = .95f
|
||||
const val FIRST_STEP = .8f
|
||||
const val FIRST_STEP_FADE_LEVEL = .7f
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue