Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-01 14:07:11 +03:00
parent f6d3003cb0
commit 2d8d9453bd
17 changed files with 763 additions and 55 deletions

View file

@ -58,7 +58,7 @@ internal fun ContentIcon(
}
@Composable
private fun CoinIcon(
fun CoinIcon(
url: String?,
@DrawableRes fallbackResId: Int,
alpha: Float,

View file

@ -4,14 +4,12 @@ import android.content.res.Configuration
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@ -20,8 +18,8 @@ import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameter
import androidx.compose.ui.unit.Dp
import com.tangem.core.ui.R
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.BigDecimalFormatter
/**
@ -116,7 +114,10 @@ private fun PriceBlock(state: MarketPriceBlockState, priceWidthDp: Dp) {
) {
Price(price = marketPriceBlockState.price, modifier = priceModifier)
PriceChangeInPercent(marketPriceBlockState.priceChangeConfig)
PriceChangeInPercent(
valueInPercent = marketPriceBlockState.priceChangeConfig.valueInPercent,
type = marketPriceBlockState.priceChangeConfig.type,
)
}
} else {
Price(price = BigDecimalFormatter.EMPTY_BALANCE_SIGN, modifier = priceModifier)
@ -136,47 +137,6 @@ private fun Price(price: String, modifier: Modifier = Modifier) {
)
}
@Composable
private fun PriceChangeInPercent(config: PriceChangeState.Content) {
AnimatedContent(
targetState = config.type,
contentAlignment = Alignment.CenterStart,
label = "Update price change",
) { type ->
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing2),
) {
Icon(
modifier = Modifier.size(TangemTheme.dimens.size8),
painter = painterResource(
id = when (type) {
PriceChangeType.UP -> R.drawable.ic_arrow_up_8
PriceChangeType.DOWN -> R.drawable.ic_arrow_down_8
PriceChangeType.NEUTRAL -> R.drawable.ic_elipse_8
},
),
tint = when (type) {
PriceChangeType.UP -> TangemTheme.colors.icon.accent
PriceChangeType.DOWN -> TangemTheme.colors.icon.warning
PriceChangeType.NEUTRAL -> TangemTheme.colors.icon.inactive
},
contentDescription = null,
)
Text(
text = config.valueInPercent,
color = when (type) {
PriceChangeType.UP -> TangemTheme.colors.text.accent
PriceChangeType.DOWN -> TangemTheme.colors.text.warning
PriceChangeType.NEUTRAL -> TangemTheme.colors.text.disabled
},
style = TangemTheme.typography.body2,
)
}
}
}
@Composable
private fun LoadingContent() {
Row(

View file

@ -0,0 +1,96 @@
package com.tangem.core.ui.components.marketprice
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
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.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@Composable
fun PriceChangeInPercent(
valueInPercent: String,
type: PriceChangeType,
modifier: Modifier = Modifier,
textStyle: TextStyle = TangemTheme.typography.body2,
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing2),
) {
Icon(
modifier = Modifier
.size(TangemTheme.dimens.size8)
.align(Alignment.CenterVertically),
imageVector = ImageVector.vectorResource(
id = when (type) {
PriceChangeType.UP -> R.drawable.ic_arrow_up_8
PriceChangeType.DOWN -> R.drawable.ic_arrow_down_8
PriceChangeType.NEUTRAL -> R.drawable.ic_elipse_8
},
),
tint = when (type) {
PriceChangeType.UP -> TangemTheme.colors.icon.accent
PriceChangeType.DOWN -> TangemTheme.colors.icon.warning
PriceChangeType.NEUTRAL -> TangemTheme.colors.icon.inactive
},
contentDescription = null,
)
Text(
text = valueInPercent,
color = when (type) {
PriceChangeType.UP -> TangemTheme.colors.text.accent
PriceChangeType.DOWN -> TangemTheme.colors.text.warning
PriceChangeType.NEUTRAL -> TangemTheme.colors.text.disabled
},
style = textStyle,
overflow = TextOverflow.Visible,
maxLines = 1,
)
}
}
//region Preview
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview() {
TangemThemePreview {
Column {
PriceChangeInPercent(
valueInPercent = "52.00%",
type = PriceChangeType.NEUTRAL,
)
PriceChangeInPercent(
valueInPercent = "52.00%",
type = PriceChangeType.UP,
)
PriceChangeInPercent(
valueInPercent = "52.00%",
type = PriceChangeType.DOWN,
)
PriceChangeInPercent(
valueInPercent = "52.00%",
type = PriceChangeType.DOWN,
textStyle = TangemTheme.typography.caption2,
)
}
}
}
//endregion Preview

View file

@ -46,18 +46,18 @@ data class WindowSize(
fun heightAtMost(value: Dp): Boolean = this.height <= value
private fun getWidthWindowSizeType(windowDp: Dp): WindowSizeType = when {
windowDp < 300.dp -> WindowSizeType.ExtraSmall
windowDp < 380.dp -> WindowSizeType.Small
windowDp < 540.dp -> WindowSizeType.Normal
windowDp < 700.dp -> WindowSizeType.Large
windowDp <= 320.dp -> WindowSizeType.ExtraSmall
windowDp <= 360.dp -> WindowSizeType.Small
windowDp <= 540.dp -> WindowSizeType.Normal
windowDp <= 700.dp -> WindowSizeType.Large
else -> WindowSizeType.ExtraLarge
}
private fun getHeightWindowSizeType(heightDp: Dp): WindowSizeType = when {
heightDp < 480.dp -> WindowSizeType.ExtraSmall
heightDp < 640.dp -> WindowSizeType.Small
heightDp < 860.dp -> WindowSizeType.Normal
heightDp < 1100.dp -> WindowSizeType.Large
heightDp <= 480.dp -> WindowSizeType.ExtraSmall
heightDp <= 640.dp -> WindowSizeType.Small
heightDp <= 860.dp -> WindowSizeType.Normal
heightDp <= 1100.dp -> WindowSizeType.Large
else -> WindowSizeType.ExtraLarge
}
}

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M15.05,6.65C15.05,6.07 14.58,5.6 14,5.6C13.42,5.6 12.95,6.07 12.95,6.65V12.95H6.65C6.07,12.95 5.6,13.42 5.6,14C5.6,14.58 6.07,15.05 6.65,15.05H12.95V21.35C12.95,21.93 13.42,22.4 14,22.4C14.58,22.4 15.05,21.93 15.05,21.35V15.05H21.35C21.93,15.05 22.4,14.58 22.4,14C22.4,13.42 21.93,12.95 21.35,12.95H15.05V6.65Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

1
features/markets/api/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,18 @@
plugins {
alias(deps.plugins.android.library)
alias(deps.plugins.kotlin.android)
id("kotlin-parcelize")
id("configuration")
}
android {
namespace = "com.tangem.features.markets.api"
}
dependencies {
implementation(deps.compose.foundation)
/* Project - Core */
implementation(projects.core.decompose)
implementation(projects.core.ui)
}

View file

@ -0,0 +1,6 @@
package com.tangem.features.markets
enum class BottomSheetState {
EXPANDED,
COLLAPSED,
}

View file

@ -0,0 +1,12 @@
package com.tangem.features.markets
import androidx.compose.runtime.Stable
@Stable
interface MarketsListComponent {
// TODO
// @Composable
// fun BottomSheetContent(state: State<BottomSheetState>, onHeaderSizeChange: (Dp) -> Unit, modifier: Modifier)
}

1
features/markets/impl/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,24 @@
plugins {
alias(deps.plugins.android.library)
alias(deps.plugins.kotlin.android)
id("configuration")
}
android {
namespace = "com.tangem.features.markets.impl"
}
dependencies {
implementation(deps.compose.coil)
implementation(deps.compose.foundation)
implementation(deps.compose.material3)
implementation(deps.compose.ui)
implementation(deps.compose.ui.tooling)
implementation(deps.compose.ui.utils)
implementation(deps.kotlin.immutable.collections)
implementation(projects.core.ui)
implementation(projects.common.ui)
implementation(projects.common.uiCharts)
}

View file

@ -0,0 +1,448 @@
package com.tangem.features.markets.ui
import android.content.res.Configuration
import androidx.compose.animation.Animatable
import androidx.compose.animation.core.*
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.*
import androidx.compose.foundation.interaction.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Button
import androidx.compose.material3.Text
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.ColorFilter
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.vectorResource
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.unit.IntOffset
import com.tangem.common.ui.charts.MarketChartMini
import com.tangem.common.ui.charts.state.MarketChartLook
import com.tangem.common.ui.charts.state.MarketChartRawData
import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.currency.tokenicon.CoinIcon
import com.tangem.core.ui.components.marketprice.PriceChangeInPercent
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.res.LocalHapticManager
import com.tangem.core.ui.res.LocalWindowSize
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.windowsize.WindowSizeType
import com.tangem.features.markets.impl.R
import com.tangem.features.markets.ui.models.MarketsListItemModel
import com.tangem.features.markets.ui.preview.MarketChartListItemPreviewDataProvider
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlin.math.roundToInt
import kotlin.random.Random
internal enum class DragValue { Start, End }
const val SWIPE_THRESHOLD_PERCENT = 0.8f
const val SWIPE_VELOCITY_THRESHOLD = 20f
@Suppress("LongMethod")
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MarketsListItem(
model: MarketsListItemModel,
modifier: Modifier = Modifier,
onClick: () -> Unit = {},
onSwipeToAction: () -> Unit = {},
) {
val actionWidth = TangemTheme.dimens.size68
val actionWidthPx = with(LocalDensity.current) { actionWidth.toPx() }
val hapticManager = LocalHapticManager.current
val anchors = DraggableAnchors {
DragValue.Start at 0f
DragValue.End at -actionWidthPx
}
val state = remember {
AnchoredDraggableState(
initialValue = DragValue.Start,
anchors = anchors,
positionalThreshold = { it * (1 - SWIPE_THRESHOLD_PERCENT) },
velocityThreshold = { SWIPE_VELOCITY_THRESHOLD },
animationSpec = tween(easing = FastOutSlowInEasing),
confirmValueChange = { it == DragValue.Start },
)
}
val dragInteractionSource = remember { MutableInteractionSource() }
val clickInteractionSource = remember { MutableInteractionSource() }
val isInDraggedState by dragInteractionSource.collectIsDraggedAsState()
LaunchedEffect(Unit) {
var actionPerformed = false
var releasePerformed = true
launch {
snapshotFlow { state.offset }
.collect {
val border = -actionWidthPx * SWIPE_THRESHOLD_PERCENT
if (it < border && actionPerformed.not()) {
hapticManager.vibrateLong()
actionPerformed = true
releasePerformed = false
}
if (it > border) {
if (releasePerformed.not()) {
hapticManager.vibrateShort()
releasePerformed = true
}
actionPerformed = false
}
}
}
launch {
snapshotFlow { isInDraggedState }
.collect {
if (it.not() && actionPerformed) {
releasePerformed = true
onSwipeToAction()
}
}
}
}
Box(
modifier = Modifier
.height(intrinsicSize = IntrinsicSize.Min)
.fillMaxWidth(),
) {
Box(
modifier = Modifier
.align(Alignment.TopEnd)
.fillMaxHeight()
.offset {
IntOffset(
x = actionWidthPx.roundToInt() +
state
.requireOffset()
.toInt(),
y = 0,
)
}
.width(actionWidth)
.background(TangemTheme.colors.control.checked),
contentAlignment = Alignment.Center,
) {
Image(
modifier = Modifier.size(TangemTheme.dimens.size28),
imageVector = ImageVector.vectorResource(id = R.drawable.ic_plus_mini_28),
colorFilter = ColorFilter.tint(TangemTheme.colors.icon.primary2),
contentDescription = null,
)
}
Box(
modifier = modifier
.align(Alignment.CenterStart)
.clip(RectangleShape)
.offset {
IntOffset(
x = state
.requireOffset()
.toInt(),
y = 0,
)
}
.anchoredDraggable(
state = state,
orientation = Orientation.Horizontal,
interactionSource = dragInteractionSource,
)
.clickable(
enabled = true,
interactionSource = clickInteractionSource,
indication = rememberRipple(),
onClick = onClick,
),
) {
MarketsListItemContent(model = model)
}
}
}
@Composable
private fun MarketsListItemContent(model: MarketsListItemModel, modifier: Modifier = Modifier) {
val windowSize = LocalWindowSize.current
Row(
modifier = modifier.padding(
horizontal = TangemTheme.dimens.spacing16,
vertical = TangemTheme.dimens.spacing15,
),
verticalAlignment = Alignment.CenterVertically,
) {
CoinIcon(
modifier = Modifier.size(TangemTheme.dimens.size36),
url = model.iconUrl,
alpha = 1f,
colorFilter = null,
fallbackResId = R.drawable.ic_custom_token_44,
)
SpacerW12()
Column(modifier = Modifier.weight(1f)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
) {
TokenTitle(
modifier = Modifier.weight(1f, fill = false),
name = model.name,
currencySymbol = model.currencySymbol,
)
SpacerW8()
TokenPriceText(
modifier = Modifier.alignByBaseline(),
price = model.price.text,
priceChangeType = model.price.changeType,
)
}
SpacerH(height = TangemTheme.dimens.spacing2)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Bottom,
) {
TokenSubtitle(
modifier = Modifier
.weight(1f, fill = false)
.alignByBaseline(),
ratingPosition = model.ratingPosition,
marketCap = model.marketCap,
)
PriceChangeInPercent(
modifier = Modifier.alignByBaseline(),
textStyle = TangemTheme.typography.caption2,
type = model.trendType,
valueInPercent = model.trendPercentText,
)
}
}
if (windowSize.widthAtLeast(WindowSizeType.Small)) {
Spacer(Modifier.width(TangemTheme.dimens.spacing10))
Chart(
chartType = model.chartType,
chartRawData = model.chardData,
)
}
}
}
@Composable
private fun TokenTitle(name: String, currencySymbol: 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,
)
SpacerW4()
Text(
modifier = Modifier.alignByBaseline(),
text = currencySymbol,
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.caption1,
maxLines = 1,
overflow = TextOverflow.Visible,
)
}
}
@Composable
private fun TokenSubtitle(ratingPosition: String?, marketCap: String?, modifier: Modifier = Modifier) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
TokenRatingPlace(ratingPosition = ratingPosition)
SpacerW4()
TokenMarketCapText(text = marketCap ?: "")
}
}
@Composable
private fun RowScope.TokenRatingPlace(ratingPosition: String?) {
Box(
modifier = Modifier
.alignByBaseline()
.heightIn(min = TangemTheme.dimens.size16)
.background(
color = TangemTheme.colors.field.primary,
shape = TangemTheme.shapes.roundedCornersSmall2,
)
.padding(horizontal = TangemTheme.dimens.size5), // TODO check
) {
Text(
text = ratingPosition ?: "-",
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.caption1,
maxLines = 1,
)
}
}
@Composable
private fun RowScope.TokenMarketCapText(text: String) {
Text(
modifier = Modifier.alignByBaseline(),
text = text,
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.caption2,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
@Composable
private fun TokenPriceText(price: String, modifier: Modifier = Modifier, priceChangeType: PriceChangeType? = null) {
val growColor = TangemTheme.colors.text.accent
val fallColor = TangemTheme.colors.text.warning
val generalColor = TangemTheme.colors.text.primary1
val color = remember { Animatable(generalColor) }
LaunchedEffect(price, growColor, fallColor, generalColor) {
snapshotFlow { price }
.drop(1)
.distinctUntilChanged()
.collectLatest {
val nextColor = when (priceChangeType) {
PriceChangeType.NEUTRAL,
PriceChangeType.UP,
-> growColor
PriceChangeType.DOWN -> fallColor
null -> generalColor
}
color.animateTo(nextColor, snap())
color.animateTo(generalColor, tween(durationMillis = 500))
}
}
Text(
modifier = modifier,
text = price,
color = color.value,
maxLines = 1,
style = TangemTheme.typography.body2,
overflow = TextOverflow.Visible,
)
}
@Composable
private fun Chart(chartType: MarketChartLook.Type, chartRawData: MarketChartRawData?) {
val chartWidth = TangemTheme.dimens.size56
Box(
modifier = Modifier
.padding(vertical = TangemTheme.dimens.spacing2)
.size(height = TangemTheme.dimens.size32, width = chartWidth),
) {
if (chartRawData != null) {
MarketChartMini(
rawData = chartRawData,
type = chartType,
)
} else {
RectangleShimmer(
modifier = Modifier
.fillMaxWidth()
.height(TangemTheme.dimens.size15) // TODO check
.align(Alignment.Center),
)
}
}
}
// region preview
@Preview(showBackground = true, widthDp = 360, name = "normal")
@Preview(showBackground = true, widthDp = 360, name = "normal night", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview(showBackground = true, widthDp = 320, name = "small width")
@Composable
private fun Preview(@PreviewParameter(MarketChartListItemPreviewDataProvider::class) state: MarketsListItemModel) {
TangemThemePreview {
var state1 by remember { mutableStateOf(state) }
var state2 by remember { mutableStateOf(state) }
var prices by remember {
mutableStateOf(
listOf(
100 to PriceChangeType.NEUTRAL,
200 to PriceChangeType.NEUTRAL,
),
)
}
Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) {
MarketsListItem(
modifier = Modifier,
model = state1,
)
MarketsListItem(
modifier = Modifier,
model = state2,
)
Row {
Button(
onClick = {
state1 = state1.copy(
trendType = PriceChangeType.entries.random(),
)
state2 = state2.copy(
trendType = PriceChangeType.entries.random(),
)
},
) { Text(text = "trend") }
Button(
onClick = {
prices = prices.map {
if (Random.nextBoolean()) {
it.first.inc() to PriceChangeType.UP
} else {
it.first.dec() to PriceChangeType.DOWN
}
}
state1 = state1.copy(
price = MarketsListItemModel.Price(
text = "0.${prices[0].first}023 $",
changeType = prices[0].second,
),
)
state2 = state2.copy(
price = MarketsListItemModel.Price(
text = "0.${prices[1].first}023 $",
changeType = prices[1].second,
),
)
},
) { Text(text = "price") }
}
}
}
}
// endregion preview

View file

@ -0,0 +1,33 @@
package com.tangem.features.markets.ui.models
import androidx.compose.runtime.Immutable
import com.tangem.common.ui.charts.state.MarketChartLook
import com.tangem.common.ui.charts.state.MarketChartRawData
import com.tangem.core.ui.components.marketprice.PriceChangeType
@Immutable
data class MarketsListItemModel(
val id: String,
val name: String,
val currencySymbol: String,
val iconUrl: String?,
val ratingPosition: String?,
val marketCap: String?,
val price: Price,
val trendPercentText: String,
val trendType: PriceChangeType,
val chardData: MarketChartRawData?,
) {
val chartType: MarketChartLook.Type = when (trendType) {
PriceChangeType.UP,
PriceChangeType.NEUTRAL,
-> MarketChartLook.Type.Growing
PriceChangeType.DOWN -> MarketChartLook.Type.Falling
}
@Immutable
data class Price(
val text: String,
val changeType: PriceChangeType = PriceChangeType.NEUTRAL,
)
}

View file

@ -0,0 +1,94 @@
@file:Suppress("MagicNumber")
package com.tangem.features.markets.ui.preview
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.common.ui.charts.state.MarketChartRawData
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.features.markets.ui.models.MarketsListItemModel
internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParameterProvider<MarketsListItemModel>(
collection = listOf(
MarketsListItemModel(
id = "1",
name = "Bitcoin",
currencySymbol = "BTC",
iconUrl = "",
ratingPosition = "10",
marketCap = "$6.233 B",
price = MarketsListItemModel.Price(text = "31 285.72$"),
trendPercentText = "12.43%",
trendType = PriceChangeType.UP,
chardData = MarketChartRawData(
y = listOf(0.4f, 0.2f, 0.4f, 0.1f, 0.4f, 2f, 5f, 0.1f, 2f, 2f, 3f),
),
),
MarketsListItemModel(
id = "1",
name = "Bitcoin",
currencySymbol = "BTC",
iconUrl = null,
ratingPosition = "10",
marketCap = "$6.233 B",
price = MarketsListItemModel.Price(text = "31 285.72$"),
trendPercentText = "12.43%",
trendType = PriceChangeType.NEUTRAL,
chardData = null,
),
MarketsListItemModel(
id = "1",
name = "Bitcoin Bitcoin Bitcoin Bitcoin Bitcoin Bitcoin Bitcoin",
currencySymbol = "BTC",
iconUrl = null,
ratingPosition = "10",
marketCap = "$6.23348172384781234 B",
price = MarketsListItemModel.Price(text = "31 285.72$"),
trendPercentText = "12.43%",
trendType = PriceChangeType.DOWN,
chardData = MarketChartRawData(
y = listOf(0.4f, 0.2f, 0.4f, 0.1f, 0.4f, 2f, 5f, 0.1f, 2f, 2f, 3f),
),
),
MarketsListItemModel(
id = "1",
name = "Bitcoin",
currencySymbol = "BTC",
iconUrl = null,
ratingPosition = "10",
marketCap = null,
price = MarketsListItemModel.Price(text = "31 285.72$"),
trendPercentText = "12.43%",
trendType = PriceChangeType.UP,
chardData = MarketChartRawData(
y = listOf(0.4f, 0.2f, 0.4f, 0.1f, 0.4f, 2f, 5f, 0.1f, 2f, 2f, 3f),
),
),
MarketsListItemModel(
id = "1",
name = "Bitcoin",
currencySymbol = "BTC",
iconUrl = null,
ratingPosition = null,
marketCap = "$6.233 B",
price = MarketsListItemModel.Price(text = "31 285.72$"),
trendPercentText = "12.43%",
trendType = PriceChangeType.UP,
chardData = MarketChartRawData(
y = listOf(0.4f, 0.2f, 0.4f, 0.1f, 0.4f, 2f, 5f, 0.1f, 2f, 2f, 3f),
),
),
MarketsListItemModel(
id = "1",
name = "Bitcoin",
currencySymbol = "BTC",
iconUrl = null,
ratingPosition = null,
marketCap = null,
price = MarketsListItemModel.Price(text = "31 285.72$"),
trendPercentText = "12.43%",
trendType = PriceChangeType.UP,
chardData = MarketChartRawData(
y = listOf(0.4f, 0.2f, 0.4f, 0.1f, 0.4f, 2f, 5f, 0.1f, 2f, 2f, 3f),
),
),
),
)

View file

@ -90,4 +90,5 @@ dependencies {
implementation(projects.features.manageTokens.api)
implementation(projects.features.details.api)
implementation(projects.features.pushNotifications.api)
implementation(projects.features.markets.api)
}

View file

@ -25,6 +25,7 @@ internal fun BaseExtension.configureCompose(project: Project) {
contains(Regex(pattern = ":presentation\$")) ||
contains(Regex(pattern = ":app\$")) || // TODO: [REDACTED_JIRA]
contains(Regex(pattern = ":features:manage-tokens:api\$")) || // provides Composable function
contains(Regex(pattern = ":features:markets:api\$")) || // provides Composable function
contains(Regex(pattern = ":impl\$"))
}

View file

@ -186,6 +186,9 @@ include(":features:push-notifications:impl")
include(":features:wallet-settings:api")
include(":features:wallet-settings:impl")
include(":features:markets:api")
include(":features:markets:impl")
// endregion Feature modules
// region Domain modules