Updated on 2026-08-14
This commit is contained in:
parent
d31d3f8a9b
commit
d4b7aa85e1
18 changed files with 1225 additions and 183 deletions
9
core/ui/src/main/res/drawable/ic_chewron_down_20.xml
Normal file
9
core/ui/src/main/res/drawable/ic_chewron_down_20.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M13.452,7.634C13.838,7.239 14.471,7.233 14.866,7.618C15.261,8.004 15.267,8.638 14.882,9.033L10.879,13.129C10.396,13.623 9.604,13.623 9.121,13.129L5.118,9.033C4.732,8.638 4.74,8.004 5.135,7.618C5.53,7.233 6.163,7.239 6.549,7.634L10.001,11.166L13.452,7.634Z"
|
||||
android:fillColor="#656565"/>
|
||||
</vector>
|
||||
9
core/ui/src/main/res/drawable/ic_staking_new_16.xml
Normal file
9
core/ui/src/main/res/drawable/ic_staking_new_16.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M14.106,9.477C14.395,9.315 14.76,9.418 14.923,9.707C15.085,9.995 14.983,10.361 14.694,10.523L9.471,13.461C8.558,13.975 7.442,13.975 6.529,13.461L1.306,10.523C1.017,10.361 0.915,9.995 1.077,9.707C1.24,9.418 1.606,9.315 1.895,9.477L7.118,12.415C7.666,12.723 8.335,12.724 8.883,12.415L14.106,9.477ZM6.529,2.54C7.443,2.026 8.557,2.026 9.471,2.54L14.694,5.477C14.883,5.583 15,5.784 15,6.001C15,6.217 14.883,6.417 14.694,6.523L9.471,9.461C8.558,9.975 7.442,9.975 6.529,9.461L1.306,6.523C1.117,6.417 1,6.217 1,6.001C1,5.784 1.117,5.583 1.306,5.477L6.529,2.54ZM8.883,3.585C8.335,3.277 7.666,3.277 7.118,3.585L2.824,6.001L7.118,8.416C7.666,8.723 8.335,8.724 8.883,8.416L13.177,6.001L8.883,3.585Z"
|
||||
android:fillColor="#656565"/>
|
||||
</vector>
|
||||
|
|
@ -8,7 +8,6 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.models.news.ShortArticle
|
||||
import com.tangem.features.feed.ui.feed.components.articles.ArticleConfigUM
|
||||
import com.tangem.features.feed.ui.utils.mapFormattedDate
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
|
|
@ -16,7 +15,7 @@ import kotlinx.collections.immutable.toPersistentList
|
|||
import kotlinx.collections.immutable.toPersistentSet
|
||||
|
||||
internal class ShortArticleToArticleConfigUMConverter(
|
||||
private val isTrending: Provider<Boolean>?,
|
||||
private val isTrending: Boolean?,
|
||||
) : Converter<List<ShortArticle>, ImmutableList<ArticleConfigUM>> {
|
||||
|
||||
override fun convert(value: List<ShortArticle>): ImmutableList<ArticleConfigUM> {
|
||||
|
|
@ -25,7 +24,7 @@ internal class ShortArticleToArticleConfigUMConverter(
|
|||
id = shortArticle.id,
|
||||
title = shortArticle.title,
|
||||
score = shortArticle.score,
|
||||
isTrending = isTrending?.invoke() ?: shortArticle.isTrending,
|
||||
isTrending = isTrending ?: shortArticle.isTrending,
|
||||
tags = buildArticleTags(shortArticle),
|
||||
createdAt = mapFormattedDate(shortArticle.createdAt),
|
||||
isViewed = shortArticle.viewed,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import com.tangem.features.feed.model.feed.analytics.FeedAnalyticsEvent
|
|||
import com.tangem.features.feed.ui.feed.state.FeedListUM
|
||||
import com.tangem.features.feed.ui.feed.state.NewsUM
|
||||
import com.tangem.features.feed.ui.feed.state.NewsUMState
|
||||
import com.tangem.utils.Provider
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import org.joda.time.DateTime
|
||||
|
|
@ -92,6 +91,6 @@ internal class UpdateTrendingNewsStateTransformer(
|
|||
}
|
||||
|
||||
private fun getShortArticleConfigConverter(isTrending: Boolean): ShortArticleToArticleConfigUMConverter {
|
||||
return ShortArticleToArticleConfigUMConverter(isTrending = Provider { isTrending })
|
||||
return ShortArticleToArticleConfigUMConverter(isTrending = isTrending)
|
||||
}
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ internal class MarketsTokenDetailsModel @Inject constructor(
|
|||
)
|
||||
|
||||
private val shortArticleToArticleConfigUMConverter by lazy {
|
||||
ShortArticleToArticleConfigUMConverter(isTrending = Provider { false })
|
||||
ShortArticleToArticleConfigUMConverter(isTrending = false)
|
||||
}
|
||||
|
||||
private val descriptionConverter = DescriptionConverter(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.compose.animation.AnimatedContent
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -21,25 +22,15 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SmallButtonShimmer
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.UnableToLoadData
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.buttons.SecondarySmallButton
|
||||
import com.tangem.core.ui.components.buttons.SmallButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.list.InfiniteListHandler
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.feed.ui.earn.components.EarnItemPlaceholder
|
||||
import com.tangem.features.feed.ui.earn.components.EarnListItem
|
||||
import com.tangem.features.feed.ui.earn.components.MostlyUsedCard
|
||||
import com.tangem.features.feed.ui.earn.components.MostlyUsedPlaceholder
|
||||
import com.tangem.core.ui.res.*
|
||||
import com.tangem.features.feed.ui.earn.components.*
|
||||
import com.tangem.features.feed.ui.earn.state.*
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
|
|
@ -51,6 +42,7 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) {
|
|||
val density = LocalDensity.current
|
||||
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() }
|
||||
val listState = rememberLazyListState()
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
|
||||
if (state.bestOpportunities is EarnBestOpportunitiesUM.Content) {
|
||||
PaginationHandler(
|
||||
|
|
@ -69,7 +61,9 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) {
|
|||
item(key = "mostly_used_header") {
|
||||
SectionHeader(
|
||||
title = stringResourceSafe(R.string.earn_mostly_used),
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
modifier = Modifier.padding(
|
||||
top = if (isRedesignEnabled) 10.dp else 16.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +77,9 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) {
|
|||
item(key = "best_opportunities_header") {
|
||||
SectionHeader(
|
||||
title = stringResourceSafe(R.string.earn_best_opportunities),
|
||||
modifier = Modifier.padding(top = 20.dp),
|
||||
modifier = Modifier.padding(
|
||||
top = if (isRedesignEnabled) 32.dp else 20.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -97,14 +93,17 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) {
|
|||
)
|
||||
}
|
||||
|
||||
bestOpportunitiesItems(
|
||||
state = state.bestOpportunities,
|
||||
)
|
||||
if (isRedesignEnabled) {
|
||||
bestOpportunitiesItemsV2(state = state.bestOpportunities)
|
||||
} else {
|
||||
bestOpportunitiesItemsV1(state = state.bestOpportunities)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MostlyUsedContent(state: EarnListUM, onScroll: () -> Unit) {
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
AnimatedContent(
|
||||
targetState = state,
|
||||
contentKey = { it::class.java },
|
||||
|
|
@ -115,10 +114,7 @@ private fun MostlyUsedContent(state: EarnListUM, onScroll: () -> Unit) {
|
|||
}
|
||||
is EarnListUM.Content -> {
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(
|
||||
horizontal = 16.dp,
|
||||
vertical = 12.dp,
|
||||
),
|
||||
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
itemsIndexed(
|
||||
|
|
@ -127,12 +123,7 @@ private fun MostlyUsedContent(state: EarnListUM, onScroll: () -> Unit) {
|
|||
) { index, item ->
|
||||
val cardModifier = Modifier.conditional(
|
||||
condition = index == FOURTH_ITEM_INDEX,
|
||||
modifier = {
|
||||
onFirstVisible(
|
||||
minFractionVisible = 0.5f,
|
||||
callback = onScroll,
|
||||
)
|
||||
},
|
||||
modifier = { onFirstVisible(minFractionVisible = 0.5f, callback = onScroll) },
|
||||
)
|
||||
MostlyUsedCard(
|
||||
modifier = cardModifier,
|
||||
|
|
@ -147,15 +138,24 @@ private fun MostlyUsedContent(state: EarnListUM, onScroll: () -> Unit) {
|
|||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||
.background(
|
||||
color = TangemTheme.colors.background.action,
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
.conditionalCompose(
|
||||
condition = isRedesignEnabled,
|
||||
modifier = {
|
||||
background(
|
||||
color = TangemTheme.colors2.surface.level3,
|
||||
shape = RoundedCornerShape(TangemTheme.dimens2.x4),
|
||||
)
|
||||
},
|
||||
otherModifier = {
|
||||
background(
|
||||
color = TangemTheme.colors.background.action,
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
)
|
||||
},
|
||||
)
|
||||
.padding(vertical = 32.dp, horizontal = 12.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
UnableToLoadData(onRetryClick = animatedState.onRetryClicked)
|
||||
}
|
||||
) { UnableToLoadData(onRetryClick = animatedState.onRetryClicked) }
|
||||
}
|
||||
EarnListUM.Empty -> Unit // no need to handle
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ private fun BestOpportunitiesFilters(
|
|||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.bestOpportunitiesItems(state: EarnBestOpportunitiesUM) {
|
||||
private fun LazyListScope.bestOpportunitiesItemsV1(state: EarnBestOpportunitiesUM) {
|
||||
when (state) {
|
||||
is EarnBestOpportunitiesUM.Loading -> {
|
||||
val lastIndex = PLACEHOLDER_ITEMS_COUNT - 1
|
||||
|
|
@ -187,7 +187,7 @@ private fun LazyListScope.bestOpportunitiesItems(state: EarnBestOpportunitiesUM)
|
|||
count = PLACEHOLDER_ITEMS_COUNT,
|
||||
key = { "placeholder_$it" },
|
||||
) { index ->
|
||||
EarnItemPlaceholder(
|
||||
EarnItemPlaceholderV1(
|
||||
modifier = Modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
|
|
@ -249,56 +249,102 @@ private fun LazyListScope.bestOpportunitiesItems(state: EarnBestOpportunitiesUM)
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FilterButtons(
|
||||
earnFilterUM: EarnFilterUM,
|
||||
onNetworkFilterClick: () -> Unit,
|
||||
onTypeFilterClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
text = when (earnFilterUM.selectedNetworkFilter) {
|
||||
is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks)
|
||||
is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks)
|
||||
is EarnFilterNetworkUM.Network -> TextReference.Str(earnFilterUM.selectedNetworkFilter.text)
|
||||
},
|
||||
onClick = onNetworkFilterClick,
|
||||
icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24),
|
||||
isEnabled = earnFilterUM.isNetworkFilterEnabled,
|
||||
),
|
||||
)
|
||||
|
||||
SpacerWMax()
|
||||
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
text = earnFilterUM.selectedTypeFilter.text,
|
||||
onClick = onTypeFilterClick,
|
||||
icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24),
|
||||
isEnabled = earnFilterUM.isTypeFilterEnabled,
|
||||
),
|
||||
)
|
||||
private fun LazyListScope.bestOpportunitiesItemsV2(state: EarnBestOpportunitiesUM) {
|
||||
when (state) {
|
||||
is EarnBestOpportunitiesUM.Loading -> {
|
||||
val lastIndex = PLACEHOLDER_ITEMS_COUNT - 1
|
||||
items(
|
||||
count = PLACEHOLDER_ITEMS_COUNT,
|
||||
key = { "placeholder_$it" },
|
||||
) { index ->
|
||||
EarnItemPlaceholderV2(
|
||||
modifier = Modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = lastIndex,
|
||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
is EarnBestOpportunitiesUM.Empty -> {
|
||||
item(key = "best_opportunities_empty") {
|
||||
SpacerH(12.dp)
|
||||
BestOpportunitiesEmpty() // TODO in [REDACTED_TASK_KEY]
|
||||
}
|
||||
}
|
||||
is EarnBestOpportunitiesUM.EmptyFiltered -> {
|
||||
item(key = "best_opportunities_empty_filtered") {
|
||||
SpacerH(12.dp)
|
||||
BestOpportunitiesEmptyFiltered(onClearFilterClick = state.onClearFilterClick) // TODO in [REDACTED_TASK_KEY]
|
||||
}
|
||||
}
|
||||
is EarnBestOpportunitiesUM.Content -> {
|
||||
if (state.items.isNotEmpty()) {
|
||||
val lastIndex = state.items.lastIndex
|
||||
itemsIndexed(
|
||||
items = state.items,
|
||||
key = { _, item -> "${item.tokenName}-${item.network}" },
|
||||
) { index, item ->
|
||||
EarnListItem(
|
||||
item = item,
|
||||
modifier = Modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = lastIndex,
|
||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
is EarnBestOpportunitiesUM.Error -> {
|
||||
item(key = "best_opportunities_error") {
|
||||
SpacerH(12.dp)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
.background(
|
||||
color = TangemTheme.colors2.surface.level3,
|
||||
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
|
||||
)
|
||||
.padding(vertical = 142.dp, horizontal = 114.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
UnableToLoadData(onRetryClick = state.onRetryClicked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FilterButtonsShimmer(modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
SmallButtonShimmer(
|
||||
modifier = Modifier.width(110.dp),
|
||||
)
|
||||
|
||||
SpacerWMax()
|
||||
|
||||
SmallButtonShimmer(
|
||||
modifier = Modifier.width(90.dp),
|
||||
)
|
||||
Row(modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp)) {
|
||||
if (LocalRedesignEnabled.current) {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.width(130.dp)
|
||||
.height(36.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
SpacerWMax()
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.width(106.dp)
|
||||
.height(36.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
} else {
|
||||
SmallButtonShimmer(
|
||||
modifier = Modifier.width(110.dp),
|
||||
)
|
||||
SpacerWMax()
|
||||
SmallButtonShimmer(
|
||||
modifier = Modifier.width(90.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -364,14 +410,25 @@ private fun BestOpportunitiesEmptyFiltered(onClearFilterClick: () -> Unit, modif
|
|||
|
||||
@Composable
|
||||
private fun SectionHeader(title: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 20.dp, end = 16.dp),
|
||||
text = title,
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
if (LocalRedesignEnabled.current) {
|
||||
Text(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 24.dp),
|
||||
text = title,
|
||||
style = TangemTheme.typography2.headingSemibold20,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 20.dp, end = 16.dp),
|
||||
text = title,
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -392,7 +449,7 @@ private fun PaginationHandler(listState: LazyListState, state: EarnBestOpportuni
|
|||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnContentPreview() {
|
||||
private fun EarnContentPreviewV1() {
|
||||
TangemThemePreview {
|
||||
val background = TangemTheme.colors.background.tertiary
|
||||
CompositionLocalProvider(
|
||||
|
|
@ -434,7 +491,49 @@ private fun EarnContentPreview() {
|
|||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnContentLoadingPreview() {
|
||||
private fun EarnContentPreviewV2() {
|
||||
TangemThemePreviewRedesign {
|
||||
val background = TangemTheme.colors2.surface.level3
|
||||
CompositionLocalProvider(
|
||||
LocalMainBottomSheetColor provides remember { mutableStateOf(background) },
|
||||
) {
|
||||
EarnContent(
|
||||
state = previewEarnUM(
|
||||
mostlyUsed = EarnListUM.Content(
|
||||
items = persistentListOf(
|
||||
previewEarnListItemUM(),
|
||||
previewEarnListItemUM(
|
||||
tokenName = "Cosmos",
|
||||
symbol = "ATOM",
|
||||
network = "Cosmos",
|
||||
),
|
||||
),
|
||||
),
|
||||
bestOpportunities = EarnBestOpportunitiesUM.Content(
|
||||
items = persistentListOf(
|
||||
previewEarnListItemUM(
|
||||
tokenName = "Cosmos Hub",
|
||||
symbol = "ATOM",
|
||||
network = "Cosmos network",
|
||||
),
|
||||
previewEarnListItemUM(
|
||||
tokenName = "Tether",
|
||||
symbol = "USDT",
|
||||
network = "Ethereum Network",
|
||||
),
|
||||
),
|
||||
onLoadMore = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnContentLoadingPreviewV1() {
|
||||
TangemThemePreview {
|
||||
val background = TangemTheme.colors.background.tertiary
|
||||
CompositionLocalProvider(
|
||||
|
|
@ -453,7 +552,26 @@ private fun EarnContentLoadingPreview() {
|
|||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnContentErrorPreview() {
|
||||
private fun EarnContentLoadingPreviewV2() {
|
||||
TangemThemePreviewRedesign {
|
||||
val background = TangemTheme.colors2.surface.level3
|
||||
CompositionLocalProvider(
|
||||
LocalMainBottomSheetColor provides remember { mutableStateOf(background) },
|
||||
) {
|
||||
EarnContent(
|
||||
state = previewEarnUM(
|
||||
mostlyUsed = EarnListUM.Error(onRetryClicked = {}),
|
||||
bestOpportunities = EarnBestOpportunitiesUM.Loading,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnContentErrorPreviewV1() {
|
||||
TangemThemePreview {
|
||||
val background = TangemTheme.colors.background.tertiary
|
||||
CompositionLocalProvider(
|
||||
|
|
@ -481,7 +599,35 @@ private fun EarnContentErrorPreview() {
|
|||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnContentEmptyPreview() {
|
||||
private fun EarnContentErrorPreviewV2() {
|
||||
TangemThemePreviewRedesign {
|
||||
val background = TangemTheme.colors2.surface.level3
|
||||
CompositionLocalProvider(
|
||||
LocalMainBottomSheetColor provides remember { mutableStateOf(background) },
|
||||
) {
|
||||
EarnContent(
|
||||
state = previewEarnUM(
|
||||
mostlyUsed = EarnListUM.Content(
|
||||
items = persistentListOf(
|
||||
previewEarnListItemUM(),
|
||||
previewEarnListItemUM(
|
||||
tokenName = "Cosmos",
|
||||
symbol = "ATOM",
|
||||
network = "Cosmos",
|
||||
),
|
||||
),
|
||||
),
|
||||
bestOpportunities = EarnBestOpportunitiesUM.Error(onRetryClicked = {}),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnContentEmptyPreviewV1() {
|
||||
TangemThemePreview {
|
||||
val background = TangemTheme.colors.background.tertiary
|
||||
CompositionLocalProvider(
|
||||
|
|
@ -506,6 +652,34 @@ private fun EarnContentEmptyPreview() {
|
|||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnContentEmptyPreviewV2() {
|
||||
TangemThemePreviewRedesign {
|
||||
val background = TangemTheme.colors2.surface.level3
|
||||
CompositionLocalProvider(
|
||||
LocalMainBottomSheetColor provides remember { mutableStateOf(background) },
|
||||
) {
|
||||
EarnContent(
|
||||
state = previewEarnUM(
|
||||
mostlyUsed = EarnListUM.Content(
|
||||
items = persistentListOf(
|
||||
previewEarnListItemUM(),
|
||||
previewEarnListItemUM(
|
||||
tokenName = "Cosmos",
|
||||
symbol = "ATOM",
|
||||
network = "Cosmos",
|
||||
),
|
||||
),
|
||||
),
|
||||
bestOpportunities = EarnBestOpportunitiesUM.Empty,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun previewEarnListItemUM(
|
||||
tokenName: String = "USDC",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
package com.tangem.features.feed.ui.earn.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun CardFilterBlock(modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
color = TangemTheme.colors2.surface.level2,
|
||||
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
|
||||
)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = TangemTheme.colors2.border.neutral.primary,
|
||||
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
|
||||
),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package com.tangem.features.feed.ui.earn.components
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
|
||||
import com.tangem.core.ui.ds.button.SecondaryTangemButton
|
||||
import com.tangem.core.ui.ds.button.TangemButtonShape
|
||||
import com.tangem.core.ui.ds.button.TangemButtonSize
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.feed.impl.R
|
||||
|
||||
@Composable
|
||||
internal inline fun <reified T : TangemBottomSheetConfigContent> EarnFilterBottomSheet(
|
||||
config: TangemBottomSheetConfig,
|
||||
crossinline content: @Composable ColumnScope.(T) -> Unit,
|
||||
) {
|
||||
TangemBottomSheet<T>(
|
||||
config = config,
|
||||
containerColor = TangemTheme.colors2.surface.level3,
|
||||
title = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TangemTheme.dimens.spacing24)
|
||||
.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.earn_filter_by),
|
||||
style = TangemTheme.typography2.headingSemibold17,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
SecondaryTangemButton(
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
onClick = config.onDismissRequest,
|
||||
iconRes = R.drawable.ic_close_24,
|
||||
size = TangemButtonSize.X9,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
)
|
||||
}
|
||||
},
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
package com.tangem.features.feed.ui.earn.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
|
|
@ -15,11 +13,13 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
|
||||
|
|
@ -28,28 +28,53 @@ import com.tangem.core.ui.components.inputrow.inner.DividerContainer
|
|||
import com.tangem.core.ui.components.rows.RowContentContainer
|
||||
import com.tangem.core.ui.components.rows.RowText
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.ds.checkbox.TangemCheckbox
|
||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
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.TangemThemePreviewRedesign
|
||||
import com.tangem.features.feed.impl.R
|
||||
import com.tangem.features.feed.ui.earn.state.EarnFilterByNetworkBottomSheetContentUM
|
||||
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
@Composable
|
||||
internal fun EarnFilterByNetworkBottomSheet(config: TangemBottomSheetConfig) {
|
||||
if (LocalRedesignEnabled.current) {
|
||||
EarnFilterByNetworkBottomSheetV2(config = config)
|
||||
} else {
|
||||
EarnFilterByNetworkBottomSheetV1(config = config)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EarnFilterByNetworkBottomSheetV1(config: TangemBottomSheetConfig) {
|
||||
TangemBottomSheet<EarnFilterByNetworkBottomSheetContentUM>(
|
||||
config = config,
|
||||
titleText = resourceReference(R.string.earn_filter_by),
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
content = { Content(it) },
|
||||
content = { ContentV1(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Content(content: EarnFilterByNetworkBottomSheetContentUM) {
|
||||
private fun EarnFilterByNetworkBottomSheetV2(config: TangemBottomSheetConfig) {
|
||||
EarnFilterBottomSheet<EarnFilterByNetworkBottomSheetContentUM>(
|
||||
config = config,
|
||||
content = { ContentV2(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentV1(content: EarnFilterByNetworkBottomSheetContentUM) {
|
||||
val allMyNetworks = remember(content) {
|
||||
content.networks.filterIsInstance<EarnFilterNetworkUM.AllNetworks>() +
|
||||
content.networks.filterIsInstance<EarnFilterNetworkUM.MyNetworks>()
|
||||
|
|
@ -79,6 +104,132 @@ private fun Content(content: EarnFilterByNetworkBottomSheetContentUM) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentV2(content: EarnFilterByNetworkBottomSheetContentUM) {
|
||||
val allMyNetworks = remember(content) {
|
||||
(content.networks.filterIsInstance<EarnFilterNetworkUM.AllNetworks>() +
|
||||
content.networks.filterIsInstance<EarnFilterNetworkUM.MyNetworks>()).toImmutableList()
|
||||
}
|
||||
val specificNetworks = remember(content) {
|
||||
content
|
||||
.networks
|
||||
.filterIsInstance<EarnFilterNetworkUM.Network>()
|
||||
.toImmutableList()
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
NetworksTypesBlock(
|
||||
allMyNetworks = allMyNetworks,
|
||||
onOptionClick = content.onOptionClick,
|
||||
)
|
||||
|
||||
SpecificNetworksBlock(
|
||||
specificNetworks = specificNetworks,
|
||||
onOptionClick = content.onOptionClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NetworksTypesBlock(
|
||||
allMyNetworks: ImmutableList<EarnFilterNetworkUM>,
|
||||
onOptionClick: (EarnFilterNetworkUM) -> Unit,
|
||||
) {
|
||||
CardFilterBlock {
|
||||
allMyNetworks.fastForEachIndexed { index, item ->
|
||||
TangemRowContainer(
|
||||
modifier = Modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = allMyNetworks.lastIndex,
|
||||
addDefaultPadding = false,
|
||||
)
|
||||
.clickable { onOptionClick(item) },
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 12.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP),
|
||||
text = when (item) {
|
||||
is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks)
|
||||
is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks)
|
||||
is EarnFilterNetworkUM.Network -> TextReference.Str(item.text)
|
||||
}.resolveReference(),
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
)
|
||||
|
||||
TangemCheckbox(
|
||||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.layoutId(layoutId = TangemRowLayoutId.TAIL),
|
||||
isChecked = item.isSelected,
|
||||
onCheckedChange = { onOptionClick(item) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SpecificNetworksBlock(
|
||||
specificNetworks: ImmutableList<EarnFilterNetworkUM.Network>,
|
||||
onOptionClick: (EarnFilterNetworkUM) -> Unit,
|
||||
) {
|
||||
if (specificNetworks.isNotEmpty()) {
|
||||
CardFilterBlock {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(top = 16.dp, bottom = 8.dp),
|
||||
text = stringResourceSafe(id = R.string.earn_filter_networks),
|
||||
style = TangemTheme.typography2.bodyRegular14,
|
||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
||||
)
|
||||
specificNetworks.fastForEachIndexed { index, item ->
|
||||
TangemRowContainer(
|
||||
modifier = Modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = specificNetworks.lastIndex,
|
||||
addDefaultPadding = false,
|
||||
)
|
||||
.clickable { onOptionClick(item) },
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 12.dp),
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.layoutId(TangemRowLayoutId.HEAD),
|
||||
imageVector = ImageVector.vectorResource(item.iconRes),
|
||||
contentDescription = item.symbol,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.layoutId(layoutId = TangemRowLayoutId.START_TOP),
|
||||
text = item.text,
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
)
|
||||
|
||||
TangemCheckbox(
|
||||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.layoutId(layoutId = TangemRowLayoutId.TAIL),
|
||||
isChecked = item.isSelected,
|
||||
onCheckedChange = { onOptionClick(item) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.allMyNetworksList(
|
||||
allMyNetworks: List<EarnFilterNetworkUM>,
|
||||
onOptionClicked: (EarnFilterNetworkUM) -> Unit,
|
||||
|
|
@ -201,7 +352,7 @@ private fun LazyListScope.specificNetworksList(
|
|||
@Preview(widthDp = 360, heightDp = 800)
|
||||
@Preview(widthDp = 360, heightDp = 800, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
private fun PreviewV1() {
|
||||
TangemThemePreview(
|
||||
alwaysShowBottomSheets = true,
|
||||
) {
|
||||
|
|
@ -235,4 +386,43 @@ private fun Preview() {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(widthDp = 360, heightDp = 800)
|
||||
@Preview(widthDp = 360, heightDp = 800, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewV2() {
|
||||
TangemThemePreviewRedesign(
|
||||
alwaysShowBottomSheets = true,
|
||||
) {
|
||||
Box(Modifier.background(TangemTheme.colors.background.secondary)) {
|
||||
EarnFilterByNetworkBottomSheet(
|
||||
TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = {},
|
||||
content = EarnFilterByNetworkBottomSheetContentUM(
|
||||
networks = persistentListOf(
|
||||
EarnFilterNetworkUM.AllNetworks(isSelected = true),
|
||||
EarnFilterNetworkUM.MyNetworks(isSelected = false),
|
||||
EarnFilterNetworkUM.Network(
|
||||
id = "ethereum",
|
||||
text = "Ethereum",
|
||||
symbol = "ETH",
|
||||
iconRes = R.drawable.img_btc_22,
|
||||
isSelected = false,
|
||||
),
|
||||
EarnFilterNetworkUM.Network(
|
||||
id = "polygon",
|
||||
text = "Polygon",
|
||||
symbol = "MATIC",
|
||||
iconRes = R.drawable.img_btc_22,
|
||||
isSelected = false,
|
||||
),
|
||||
),
|
||||
onOptionClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,34 +5,61 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.inputrow.InputRowChecked
|
||||
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.ds.checkbox.TangemCheckbox
|
||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
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.TangemThemePreviewRedesign
|
||||
import com.tangem.features.feed.impl.R
|
||||
import com.tangem.features.feed.ui.earn.state.EarnFilterByTypeBottomSheetContentUM
|
||||
import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM
|
||||
|
||||
@Composable
|
||||
internal fun EarnFilterByTypeBottomSheet(config: TangemBottomSheetConfig) {
|
||||
if (LocalRedesignEnabled.current) {
|
||||
EarnFilterByTypeBottomSheetV2(config)
|
||||
} else {
|
||||
EarnFilterByTypeBottomSheetV1(config)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EarnFilterByTypeBottomSheetV1(config: TangemBottomSheetConfig) {
|
||||
TangemBottomSheet<EarnFilterByTypeBottomSheetContentUM>(
|
||||
config = config,
|
||||
titleText = resourceReference(R.string.earn_filter_by),
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
content = { Content(it) },
|
||||
content = { ContentV1(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Content(content: EarnFilterByTypeBottomSheetContentUM) {
|
||||
private fun EarnFilterByTypeBottomSheetV2(config: TangemBottomSheetConfig) {
|
||||
EarnFilterBottomSheet<EarnFilterByTypeBottomSheetContentUM>(
|
||||
config = config,
|
||||
content = { ContentV2(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentV1(content: EarnFilterByTypeBottomSheetContentUM) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
|
|
@ -62,10 +89,45 @@ private fun Content(content: EarnFilterByTypeBottomSheetContentUM) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentV2(content: EarnFilterByTypeBottomSheetContentUM) {
|
||||
CardFilterBlock(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
EarnFilterTypeUM.entries.forEachIndexed { index, type ->
|
||||
TangemRowContainer(
|
||||
modifier = Modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = EarnFilterTypeUM.entries.lastIndex,
|
||||
addDefaultPadding = false,
|
||||
)
|
||||
.clickable { content.onOptionClick(type) },
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens2.x4, vertical = TangemTheme.dimens2.x3),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP),
|
||||
text = type.text.resolveReference(),
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
)
|
||||
|
||||
TangemCheckbox(
|
||||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.layoutId(layoutId = TangemRowLayoutId.TAIL),
|
||||
isChecked = type == content.selectedOption,
|
||||
onCheckedChange = { content.onOptionClick(type) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(widthDp = 360, heightDp = 640)
|
||||
@Preview(widthDp = 360, heightDp = 640, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
private fun PreviewV1() {
|
||||
TangemThemePreview(
|
||||
alwaysShowBottomSheets = true,
|
||||
) {
|
||||
|
|
@ -82,4 +144,26 @@ private fun Preview() {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(widthDp = 360, heightDp = 640)
|
||||
@Preview(widthDp = 360, heightDp = 640, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewV2() {
|
||||
TangemThemePreviewRedesign(
|
||||
alwaysShowBottomSheets = true,
|
||||
) {
|
||||
Box(Modifier.background(TangemTheme.colors.background.secondary)) {
|
||||
EarnFilterByTypeBottomSheet(
|
||||
TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = {},
|
||||
content = EarnFilterByTypeBottomSheetContentUM(
|
||||
selectedOption = EarnFilterTypeUM.All,
|
||||
onOptionClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,12 +4,16 @@ import android.content.res.Configuration
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -18,15 +22,33 @@ import com.tangem.core.ui.components.SpacerH
|
|||
import com.tangem.core.ui.components.SpacerW
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.ds.image.TangemIcon
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.res.*
|
||||
import com.tangem.features.feed.ui.earn.state.EarnListItemUM
|
||||
|
||||
@Composable
|
||||
internal fun EarnListItem(item: EarnListItemUM, modifier: Modifier = Modifier) {
|
||||
if (LocalRedesignEnabled.current) {
|
||||
EarnListItemV2(
|
||||
item = item,
|
||||
modifier = modifier,
|
||||
)
|
||||
} else {
|
||||
EarnListItemV1(
|
||||
item = item,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EarnListItemV1(item: EarnListItemUM, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -82,27 +104,117 @@ internal fun EarnListItem(item: EarnListItemUM, modifier: Modifier = Modifier) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EarnListItemV2(item: EarnListItemUM, modifier: Modifier = Modifier) {
|
||||
TangemRowContainer(
|
||||
modifier = modifier.clickable { item.onItemClick() },
|
||||
contentPadding = PaddingValues(12.dp),
|
||||
content = {
|
||||
TangemIcon(
|
||||
tangemIconUM = TangemIconUM.Currency(item.currencyIconState),
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.HEAD)
|
||||
.padding(end = TangemTheme.dimens2.x2),
|
||||
)
|
||||
|
||||
TokenTitle(
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.START_TOP)
|
||||
.padding(end = TangemTheme.dimens2.x2),
|
||||
name = item.tokenName.resolveReference(),
|
||||
symbol = item.symbol.resolveReference(),
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM)
|
||||
.padding(end = TangemTheme.dimens2.x2),
|
||||
text = item.network.resolveReference(),
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.END_TOP),
|
||||
text = item.earnValue.resolveReference(),
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
maxLines = 1,
|
||||
)
|
||||
|
||||
ModeBlock(
|
||||
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.END_BOTTOM),
|
||||
earnType = item.earnType,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenTitle(name: String, symbol: String, modifier: Modifier = Modifier) {
|
||||
Row(modifier = modifier) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f, fill = false)
|
||||
.alignByBaseline(),
|
||||
text = name,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
if (LocalRedesignEnabled.current) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f, fill = false)
|
||||
.alignByBaseline(),
|
||||
text = name,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
SpacerW(4.dp)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
text = symbol,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Visible,
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f, fill = false)
|
||||
.alignByBaseline(),
|
||||
text = name,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
SpacerW(4.dp)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
text = symbol,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.body2,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Visible,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ModeBlock(earnType: TextReference, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_staking_new_16),
|
||||
tint = TangemTheme.colors2.markers.iconGray,
|
||||
contentDescription = null,
|
||||
)
|
||||
SpacerW(4.dp)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
text = symbol,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.body2,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Visible,
|
||||
text = earnType.resolveReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -110,7 +222,7 @@ private fun TokenTitle(name: String, symbol: String, modifier: Modifier = Modifi
|
|||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnListItemPreview() {
|
||||
private fun EarnListItemPreviewV1() {
|
||||
TangemThemePreview {
|
||||
Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) {
|
||||
EarnListItem(
|
||||
|
|
@ -151,4 +263,53 @@ private fun EarnListItemPreview() {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnListItemPreviewV2() {
|
||||
TangemThemePreviewRedesign {
|
||||
Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) {
|
||||
SpacerH(12.dp)
|
||||
EarnListItem(
|
||||
item = EarnListItemUM(
|
||||
network = stringReference("Ethereum"),
|
||||
symbol = stringReference("ETH"),
|
||||
tokenName = stringReference("Ethereum"),
|
||||
currencyIconState = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = R.drawable.img_eth_22,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
earnValue = stringReference("APY 8.50%"),
|
||||
earnType = stringReference("Yield"),
|
||||
onItemClick = {},
|
||||
),
|
||||
)
|
||||
SpacerH(12.dp)
|
||||
EarnListItem(
|
||||
item = EarnListItemUM(
|
||||
network = stringReference("Ethereum"),
|
||||
symbol = stringReference("USDT"),
|
||||
tokenName = stringReference("Tether"),
|
||||
currencyIconState = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = R.drawable.img_eth_22,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
earnValue = stringReference("APY 8.50%"),
|
||||
earnType = stringReference("Yield"),
|
||||
onItemClick = {},
|
||||
),
|
||||
)
|
||||
SpacerH(12.dp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,27 +8,13 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerW
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
|
||||
@Composable
|
||||
internal fun EarnListPlaceholder(modifier: Modifier = Modifier, placeholderCount: Int = PLACEHOLDER_ITEMS_COUNT) {
|
||||
Column(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
) {
|
||||
repeat(placeholderCount) {
|
||||
EarnItemPlaceholder()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun EarnItemPlaceholder(modifier: Modifier = Modifier) {
|
||||
internal fun EarnItemPlaceholderV1(modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -38,9 +24,7 @@ internal fun EarnItemPlaceholder(modifier: Modifier = Modifier) {
|
|||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
CircleShimmer(
|
||||
modifier = Modifier.size(36.dp),
|
||||
)
|
||||
CircleShimmer(modifier = Modifier.size(36.dp))
|
||||
|
||||
SpacerW(12.dp)
|
||||
|
||||
|
|
@ -91,18 +75,86 @@ internal fun EarnItemPlaceholder(modifier: Modifier = Modifier) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun EarnItemPlaceholderV2(modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
CircleShimmer(modifier = Modifier.size(40.dp))
|
||||
|
||||
SpacerW(4.dp)
|
||||
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.width(96.dp)
|
||||
.height(20.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
SpacerWMax()
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.width(56.dp)
|
||||
.height(20.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerH(4.dp)
|
||||
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.width(46.dp)
|
||||
.height(16.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
SpacerWMax()
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.width(46.dp)
|
||||
.height(16.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val PLACEHOLDER_ITEMS_COUNT = 8
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnListPlaceholderPreview() {
|
||||
private fun EarnListPlaceholderPreviewV1() {
|
||||
TangemThemePreview {
|
||||
Box(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
) {
|
||||
EarnListPlaceholder()
|
||||
repeat(PLACEHOLDER_ITEMS_COUNT) {
|
||||
EarnItemPlaceholderV1()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun EarnListPlaceholderPreviewV2() {
|
||||
TangemThemePreviewRedesign {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors2.surface.level3),
|
||||
) {
|
||||
repeat(PLACEHOLDER_ITEMS_COUNT) {
|
||||
EarnItemPlaceholderV2()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package com.tangem.features.feed.ui.earn.components
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.buttons.SecondarySmallButton
|
||||
import com.tangem.core.ui.components.buttons.SmallButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.ds.button.PrimaryInverseTangemButton
|
||||
import com.tangem.core.ui.ds.button.TangemButtonShape
|
||||
import com.tangem.core.ui.ds.button.TangemButtonSize
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
||||
import com.tangem.features.feed.ui.earn.state.EarnFilterUM
|
||||
|
||||
@Composable
|
||||
internal fun FilterButtons(
|
||||
earnFilterUM: EarnFilterUM,
|
||||
onNetworkFilterClick: () -> Unit,
|
||||
onTypeFilterClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (LocalRedesignEnabled.current) {
|
||||
FilterButtonsV2(
|
||||
earnFilterUM = earnFilterUM,
|
||||
onNetworkFilterClick = onNetworkFilterClick,
|
||||
onTypeFilterClick = onTypeFilterClick,
|
||||
modifier = modifier,
|
||||
)
|
||||
} else {
|
||||
FilterButtonsV1(
|
||||
earnFilterUM = earnFilterUM,
|
||||
onNetworkFilterClick = onNetworkFilterClick,
|
||||
onTypeFilterClick = onTypeFilterClick,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FilterButtonsV1(
|
||||
earnFilterUM: EarnFilterUM,
|
||||
onNetworkFilterClick: () -> Unit,
|
||||
onTypeFilterClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
text = when (earnFilterUM.selectedNetworkFilter) {
|
||||
is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks)
|
||||
is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks)
|
||||
is EarnFilterNetworkUM.Network -> TextReference.Str(earnFilterUM.selectedNetworkFilter.text)
|
||||
},
|
||||
onClick = onNetworkFilterClick,
|
||||
icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24),
|
||||
isEnabled = earnFilterUM.isNetworkFilterEnabled,
|
||||
),
|
||||
)
|
||||
|
||||
SpacerWMax()
|
||||
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
text = earnFilterUM.selectedTypeFilter.text,
|
||||
onClick = onTypeFilterClick,
|
||||
icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24),
|
||||
isEnabled = earnFilterUM.isTypeFilterEnabled,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FilterButtonsV2(
|
||||
earnFilterUM: EarnFilterUM,
|
||||
onNetworkFilterClick: () -> Unit,
|
||||
onTypeFilterClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp)) {
|
||||
PrimaryInverseTangemButton(
|
||||
text = when (earnFilterUM.selectedNetworkFilter) {
|
||||
is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks)
|
||||
is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks)
|
||||
is EarnFilterNetworkUM.Network -> TextReference.Str(earnFilterUM.selectedNetworkFilter.text)
|
||||
},
|
||||
onClick = onNetworkFilterClick,
|
||||
iconRes = R.drawable.ic_chewron_down_20,
|
||||
iconPosition = com.tangem.core.ui.ds.button.TangemButtonIconPosition.End,
|
||||
size = TangemButtonSize.X9,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
enabled = earnFilterUM.isNetworkFilterEnabled,
|
||||
)
|
||||
|
||||
SpacerWMax()
|
||||
|
||||
PrimaryInverseTangemButton(
|
||||
text = earnFilterUM.selectedTypeFilter.text,
|
||||
onClick = onTypeFilterClick,
|
||||
iconRes = R.drawable.ic_chewron_down_20,
|
||||
iconPosition = com.tangem.core.ui.ds.button.TangemButtonIconPosition.End,
|
||||
size = TangemButtonSize.X9,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
enabled = earnFilterUM.isTypeFilterEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ internal fun MostlyUsedCard(item: EarnListItemUM, onClick: () -> Unit, modifier:
|
|||
private fun MostlyUsedCardV2(item: EarnListItemUM, onClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
OpportunitiesBG(
|
||||
modifier = modifier
|
||||
.width(148.dp)
|
||||
.width(178.dp)
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.clickable(onClick = onClick),
|
||||
icon = TangemIconUM.Currency(item.currencyIconState),
|
||||
|
|
|
|||
|
|
@ -2,14 +2,9 @@ package com.tangem.features.feed.ui.earn.components
|
|||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
|
@ -17,27 +12,36 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
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.TangemThemePreviewRedesign
|
||||
|
||||
@Composable
|
||||
internal fun MostlyUsedPlaceholder(modifier: Modifier = Modifier) {
|
||||
internal fun MostlyUsedPlaceholder(
|
||||
modifier: Modifier = Modifier,
|
||||
contentPadding: PaddingValues = PaddingValues(
|
||||
horizontal = 16.dp,
|
||||
vertical = 12.dp,
|
||||
),
|
||||
) {
|
||||
LazyRow(
|
||||
modifier = modifier,
|
||||
contentPadding = PaddingValues(
|
||||
horizontal = 16.dp,
|
||||
vertical = 12.dp,
|
||||
),
|
||||
contentPadding = contentPadding,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
items(PLACEHOLDER_ITEMS_COUNT) {
|
||||
MostlyUsedItemPlaceholder()
|
||||
if (LocalRedesignEnabled.current) {
|
||||
MostlyUsedItemPlaceholderV2()
|
||||
} else {
|
||||
MostlyUsedItemPlaceholderV1()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MostlyUsedItemPlaceholder(modifier: Modifier = Modifier) {
|
||||
private fun MostlyUsedItemPlaceholderV1(modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.width(148.dp)
|
||||
|
|
@ -69,13 +73,52 @@ fun MostlyUsedItemPlaceholder(modifier: Modifier = Modifier) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MostlyUsedItemPlaceholderV2(modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.width(178.dp)
|
||||
.height(130.dp)
|
||||
.background(
|
||||
color = TangemTheme.colors2.surface.level3,
|
||||
shape = RoundedCornerShape(TangemTheme.dimens2.x4),
|
||||
)
|
||||
.padding(12.dp),
|
||||
) {
|
||||
CircleShimmer(modifier = Modifier.size(40.dp))
|
||||
SpacerH(22.dp)
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.width(56.dp)
|
||||
.height(20.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
SpacerH(4.dp)
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.width(46.dp)
|
||||
.height(16.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private const val PLACEHOLDER_ITEMS_COUNT = 3
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun MostlyUsedPlaceholderPreview() {
|
||||
private fun MostlyUsedPlaceholderPreviewV1() {
|
||||
TangemThemePreview {
|
||||
MostlyUsedPlaceholder()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun MostlyUsedPlaceholderPreviewV2() {
|
||||
TangemThemePreviewRedesign {
|
||||
MostlyUsedPlaceholder()
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,15 @@ package com.tangem.features.feed.ui.feed.components
|
|||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
|
|
@ -13,6 +18,9 @@ import com.tangem.core.ui.components.SpacerW
|
|||
import com.tangem.core.ui.components.buttons.SecondarySmallButton
|
||||
import com.tangem.core.ui.components.buttons.SmallButtonConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun Header(
|
||||
|
|
@ -21,6 +29,7 @@ internal fun Header(
|
|||
shouldShowSeeAll: Boolean,
|
||||
title: @Composable () -> Unit,
|
||||
) {
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
AnimatedContent(isLoading) { animatedState ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
|
|
@ -30,19 +39,47 @@ internal fun Header(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
if (animatedState) {
|
||||
RectangleShimmer(modifier = Modifier.size(width = 104.dp, height = 18.dp))
|
||||
if (isRedesignEnabled) {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier.size(width = 130.dp, height = 24.dp),
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
)
|
||||
} else {
|
||||
RectangleShimmer(modifier = Modifier.size(width = 104.dp, height = 18.dp))
|
||||
}
|
||||
} else {
|
||||
Box(modifier = Modifier.weight(1f)) {
|
||||
title()
|
||||
}
|
||||
SpacerW(8.dp)
|
||||
AnimatedVisibility(shouldShowSeeAll) {
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
text = TextReference.Res(R.string.common_see_all),
|
||||
onClick = onSeeAllClick,
|
||||
),
|
||||
)
|
||||
if (isRedesignEnabled) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.clickable(onClick = onSeeAllClick),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.common_see_all),
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
|
||||
tint = TangemTheme.colors2.markers.iconGray,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
text = TextReference.Res(R.string.common_see_all),
|
||||
onClick = onSeeAllClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.features.feed.ui.feed.components
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -16,9 +16,12 @@ import com.tangem.core.ui.components.UnableToLoadData
|
|||
import com.tangem.core.ui.components.block.BlockCard
|
||||
import com.tangem.core.ui.components.block.TangemBlockCardColors
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.feed.ui.earn.components.EarnItemPlaceholderV1
|
||||
import com.tangem.features.feed.ui.earn.components.EarnListItem
|
||||
import com.tangem.features.feed.ui.earn.components.EarnListPlaceholder
|
||||
import com.tangem.features.feed.ui.earn.components.MostlyUsedCard
|
||||
import com.tangem.features.feed.ui.earn.components.MostlyUsedPlaceholder
|
||||
import com.tangem.features.feed.ui.earn.state.EarnListItemUM
|
||||
import com.tangem.features.feed.ui.earn.state.EarnListUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -26,7 +29,15 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
@Composable
|
||||
internal fun EarnBlock(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifier: Modifier = Modifier) {
|
||||
if (earnListUM is EarnListUM.Empty) return
|
||||
if (LocalRedesignEnabled.current) {
|
||||
EarnBlockV2(onSeeAllClick = onSeeAllClick, earnListUM = earnListUM, modifier = modifier)
|
||||
} else {
|
||||
EarnBlockV1(onSeeAllClick = onSeeAllClick, earnListUM = earnListUM, modifier = modifier)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EarnBlockV1(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifier: Modifier = Modifier) {
|
||||
Column(modifier = modifier) {
|
||||
Header(
|
||||
title = {
|
||||
|
|
@ -56,7 +67,11 @@ internal fun EarnBlock(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifi
|
|||
when (earnListUM) {
|
||||
is EarnListUM.Content -> EarnContentBlock(items = earnListUM.items)
|
||||
is EarnListUM.Error -> EarnErrorBlock(onRetryClick = earnListUM.onRetryClicked)
|
||||
EarnListUM.Loading -> EarnListPlaceholder(placeholderCount = PLACEHOLDER_ITEM_COUNT)
|
||||
EarnListUM.Loading -> {
|
||||
repeat(PLACEHOLDER_ITEM_COUNT) {
|
||||
EarnItemPlaceholderV1()
|
||||
}
|
||||
}
|
||||
EarnListUM.Empty -> Unit
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +80,55 @@ internal fun EarnBlock(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifi
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EarnBlockV2(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifier: Modifier = Modifier) {
|
||||
Column(modifier = modifier) {
|
||||
Header(
|
||||
title = {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.markets_earn_common_title),
|
||||
style = TangemTheme.typography2.headingSemibold20,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
)
|
||||
},
|
||||
onSeeAllClick = onSeeAllClick,
|
||||
isLoading = earnListUM is EarnListUM.Loading,
|
||||
shouldShowSeeAll = earnListUM is EarnListUM.Content,
|
||||
)
|
||||
|
||||
SpacerH(12.dp)
|
||||
AnimatedContent(
|
||||
targetState = earnListUM,
|
||||
contentKey = { it::class.java },
|
||||
) { earnListUM ->
|
||||
when (earnListUM) {
|
||||
is EarnListUM.Content -> EarnContentBlock(items = earnListUM.items)
|
||||
is EarnListUM.Error -> {
|
||||
BlockCard(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
colors = TangemBlockCardColors.copy(containerColor = TangemTheme.colors2.surface.level3),
|
||||
) {
|
||||
EarnErrorBlock(onRetryClick = earnListUM.onRetryClicked)
|
||||
}
|
||||
}
|
||||
EarnListUM.Loading -> {
|
||||
MostlyUsedPlaceholder(
|
||||
contentPadding = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 8.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
EarnListUM.Empty -> Unit
|
||||
}
|
||||
}
|
||||
SpacerH(32.dp)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EarnErrorBlock(onRetryClick: () -> Unit) {
|
||||
UnableToLoadData(
|
||||
|
|
@ -77,9 +141,30 @@ private fun EarnErrorBlock(onRetryClick: () -> Unit) {
|
|||
|
||||
@Composable
|
||||
private fun EarnContentBlock(items: ImmutableList<EarnListItemUM>) {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
items.fastForEach { item ->
|
||||
EarnListItem(item = item)
|
||||
if (LocalRedesignEnabled.current) {
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 8.dp,
|
||||
),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
items(
|
||||
items = items,
|
||||
key = { item -> "${item.tokenName}-${item.network}" },
|
||||
) { item ->
|
||||
MostlyUsedCard(
|
||||
item = item,
|
||||
onClick = item.onItemClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
items.fastForEach { item ->
|
||||
EarnListItem(item = item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ private inline fun BaseScaffoldWithMarkets(
|
|||
val peekHeight = bottomSheetHeaderHeightProvider() + TangemTheme.dimens2.x3 + bottomBarHeight
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val background = TangemTheme.colors2.surface.level3
|
||||
val background = TangemTheme.colors2.surface.level2
|
||||
|
||||
val bottomSheetState = rememberTangemStandardBottomSheetState()
|
||||
val scaffoldState = rememberTangemBottomSheetScaffoldState(bottomSheetState = bottomSheetState)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue