From a2792223a37e9b1304f895e0ae5c7b8c11cfaa80 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Jun 2024 20:57:05 +0300 Subject: [PATCH] Updated on 2026-08-14 --- common/ui-charts/.gitignore | 1 + common/ui-charts/build.gradle.kts | 24 ++ .../tangem/common/ui/charts/MarketChart.kt | 8 + .../ui/charts/layer/MarketChartLayer.kt | 269 ++++++++++++++++++ .../common/ui/charts/marker/ChartMarker.kt | 135 +++++++++ .../common/ui/charts/preview/PreviewData.kt | 77 +++++ gradle/dependencies.toml | 6 + .../extension/BaseExtensionConfigurations.kt | 1 + settings.gradle.kts | 13 + 9 files changed, 534 insertions(+) create mode 100644 common/ui-charts/.gitignore create mode 100644 common/ui-charts/build.gradle.kts create mode 100644 common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt create mode 100644 common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/layer/MarketChartLayer.kt create mode 100644 common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/marker/ChartMarker.kt create mode 100644 common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/preview/PreviewData.kt diff --git a/common/ui-charts/.gitignore b/common/ui-charts/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/common/ui-charts/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/common/ui-charts/build.gradle.kts b/common/ui-charts/build.gradle.kts new file mode 100644 index 0000000000..62c6c0de87 --- /dev/null +++ b/common/ui-charts/build.gradle.kts @@ -0,0 +1,24 @@ +plugins { + alias(deps.plugins.android.library) + alias(deps.plugins.kotlin.android) + id("configuration") +} + +android { + namespace = "com.tangem.common.ui.charts" +} + +dependencies { + /** Project - Core */ + implementation(projects.core.ui) + + /** Compose */ + implementation(deps.tangem.vico.core) + implementation(deps.tangem.vico.compose) + implementation(deps.tangem.vico.compose.m3) + + implementation(deps.compose.foundation) + implementation(deps.compose.material3) + implementation(deps.compose.ui.tooling) + implementation(deps.compose.ui.utils) +} \ No newline at end of file diff --git a/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt new file mode 100644 index 0000000000..31f0f55f2b --- /dev/null +++ b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt @@ -0,0 +1,8 @@ +package com.tangem.common.ui.charts + +import androidx.compose.runtime.Composable + +@Composable +fun MarketChart() { + TODO() +} \ No newline at end of file diff --git a/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/layer/MarketChartLayer.kt b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/layer/MarketChartLayer.kt new file mode 100644 index 0000000000..239f0f0665 --- /dev/null +++ b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/layer/MarketChartLayer.kt @@ -0,0 +1,269 @@ +package com.tangem.common.ui.charts.layer + +import android.content.res.Configuration +import androidx.annotation.FloatRange +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.animate +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.patrykandpatrick.vico.compose.cartesian.CartesianChartHost +import com.patrykandpatrick.vico.compose.cartesian.fullWidth +import com.patrykandpatrick.vico.compose.cartesian.layer.rememberLineCartesianLayer +import com.patrykandpatrick.vico.compose.cartesian.layer.rememberLineSpec +import com.patrykandpatrick.vico.compose.cartesian.layer.rememberSplitLineSpec +import com.patrykandpatrick.vico.compose.cartesian.rememberCartesianChart +import com.patrykandpatrick.vico.compose.cartesian.rememberVicoZoomState +import com.patrykandpatrick.vico.compose.common.shader.BrushShader +import com.patrykandpatrick.vico.core.cartesian.HorizontalLayout +import com.patrykandpatrick.vico.core.cartesian.Zoom +import com.patrykandpatrick.vico.core.cartesian.data.AxisValueOverrider +import com.patrykandpatrick.vico.core.cartesian.layer.LineCartesianLayer +import com.patrykandpatrick.vico.core.common.data.ExtraStore +import com.patrykandpatrick.vico.core.common.shader.ColorShader +import com.patrykandpatrick.vico.core.common.shader.DynamicShader +import com.tangem.common.ui.charts.preview.getPreviewBigCartData +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview + +/** + * Creates and remembers a LineCartesianLayer for a chart with specific characteristics. + * + * @param lineColor The color of the main line in the chart. + * @param backgroundLineColor The color of the line's background. + * @param secondLineColor The color of the line for the second part of the chart. + * @param backgroundSecondLineColor The color of the line's background for the second part of the chart. + * @param startDrawingAnimation A mutable state that triggers the start of the drawing animation when set to true. + * @param axisValueOverrider An AxisValueOverrider that provides custom values for the axis. + * @param secondColorOnTheRightSide A boolean that determines if the second color should be on the right side of the chart. Default is false. + * @param markerFraction A float between 0.0 and 1.0 that represents the fraction of the chart where the marker is located. Default is null. + * + * @return A LineCartesianLayer that represents a layer in a chart with the specified characteristics. + */ +@Suppress("LongParameterList") +@Composable +fun rememberMarketChartLayer( + lineColor: Color, + backgroundLineColor: Color, + secondLineColor: Color, + backgroundSecondLineColor: Color, + startDrawingAnimation: MutableState, + axisValueOverrider: AxisValueOverrider, + secondColorOnTheRightSide: Boolean = false, + @FloatRange(from = 0.0, to = 1.0) markerFraction: Float? = null, +): LineCartesianLayer { + var animationFraction: Float? by remember { mutableStateOf(null) } + + LaunchedEffect(startDrawingAnimation.value) { + if (startDrawingAnimation.value) { + animate( + initialValue = 0f, + targetValue = 1f, + animationSpec = tween(easing = LinearEasing, durationMillis = 1000), + ) { start, _ -> + if (start == 1f) { + animationFraction = null + startDrawingAnimation.value = false + } else { + animationFraction = start + } + } + } + } + + return rememberRawMarketChartLayer( + lineColor = lineColor, + backgroundLineColor = backgroundLineColor, + secondLineColor = secondLineColor, + backgroundSecondLineColor = backgroundSecondLineColor, + axisValueOverrider = axisValueOverrider, + secondColorOnTheRightSide = secondColorOnTheRightSide, + markerFraction = markerFraction, + animationFraction = animationFraction, + ) +} + +@Composable +private fun rememberRawMarketChartLayer( + lineColor: Color, + backgroundLineColor: Color, + secondLineColor: Color, + backgroundSecondLineColor: Color, + axisValueOverrider: AxisValueOverrider, + secondColorOnTheRightSide: Boolean = false, + @FloatRange(from = 0.0, to = 1.0) markerFraction: Float? = null, + @FloatRange(from = 0.0, to = 1.0) animationFraction: Float? = null, +): LineCartesianLayer { + val backgroundColorLineGradient = listOf(backgroundLineColor, Color.Transparent) + val backgroundSecondLineColorGradient = listOf(backgroundSecondLineColor, Color.Transparent) + + val markerSet = markerFraction != null + val animationRunning = animationFraction != null && animationFraction != 1f + + val layerColors = remember(animationRunning, markerSet, secondColorOnTheRightSide) { + when { + !animationRunning && markerSet && secondColorOnTheRightSide -> { + LayerColors( + lineColor = lineColor, + backLineColor = backgroundColorLineGradient, + lineColorRight = secondLineColor, + backLineColorRight = backgroundSecondLineColorGradient, + ) + } + !animationRunning && markerSet && !secondColorOnTheRightSide -> { + LayerColors( + lineColor = secondLineColor, + backLineColor = backgroundSecondLineColorGradient, + lineColorRight = lineColor, + backLineColorRight = backgroundColorLineGradient, + ) + } + animationRunning -> { + LayerColors( + lineColor = lineColor, + backLineColor = backgroundColorLineGradient, + lineColorRight = Color.Transparent, + backLineColorRight = listOf(Color.Transparent, Color.Transparent), + ) + } + else -> { + LayerColors( + lineColor = lineColor, + backLineColor = backgroundColorLineGradient, + ) + } + } + } + + return rememberLayer( + fractionValue = animationFraction ?: markerFraction, + axisValueOverrider = axisValueOverrider, + layerColors = layerColors, + ) +} + +private data class LayerColors( + val lineColor: Color, + val backLineColor: List, + val lineColorRight: Color? = null, + val backLineColorRight: List? = null, +) + +@Composable +private fun rememberLayer( + fractionValue: Float?, + axisValueOverrider: AxisValueOverrider, + layerColors: LayerColors, +): LineCartesianLayer { + return rememberLineCartesianLayer( + listOf( + if (layerColors.lineColorRight == null || layerColors.backLineColorRight == null || fractionValue == null) { + rememberLineSpec( + shader = remember(layerColors.lineColor) { ColorShader(color = layerColors.lineColor.toArgb()) }, + backgroundShader = remember(layerColors.backLineColor) { + BrushShader(brush = Brush.verticalGradient(layerColors.backLineColor)) + }, + ) + } else { + rememberSplitLineSpec( + shader = remember(layerColors.lineColor, layerColors.lineColorRight, fractionValue) { + DynamicShader.Companion.horizontalGradient( + colors = intArrayOf(layerColors.lineColor.toArgb(), layerColors.lineColorRight.toArgb()), + positions = floatArrayOf(fractionValue, fractionValue), + ) + }, + backgroundShaderFirst = remember(layerColors.backLineColor) { + BrushShader(brush = Brush.verticalGradient(layerColors.backLineColor)) + }, + backgroundShaderSecond = remember(layerColors.backLineColorRight) { + BrushShader(brush = Brush.verticalGradient(layerColors.backLineColorRight)) + }, + xSplitFraction = fractionValue, + ) + }, + ), + axisValueOverrider = axisValueOverrider, + ) +} + +// region Preview + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun LayerChartPreview() { + val xListKey = ExtraStore.Key>() + val model = getPreviewBigCartData(xListKey) + + TangemThemePreview { + Column( + modifier = Modifier.background(TangemTheme.colors.background.primary), + verticalArrangement = Arrangement.spacedBy(48.dp), + ) { + CartesianChartHost( + modifier = Modifier.fillMaxWidth(), + chart = rememberCartesianChart( + rememberRawMarketChartLayer( + lineColor = Color.Blue, + backgroundLineColor = Color.Blue.copy(alpha = 0.24f), + secondLineColor = Color.Gray, + backgroundSecondLineColor = Color.Gray.copy(alpha = 0.24f), + secondColorOnTheRightSide = true, + axisValueOverrider = AxisValueOverrider.fixed(minY = model.models[0].minY), + ), + ), + zoomState = rememberVicoZoomState(initialZoom = Zoom.Content, zoomEnabled = false), + horizontalLayout = HorizontalLayout.fullWidth(), + model = model, + ) + + CartesianChartHost( + modifier = Modifier.fillMaxWidth(), + chart = rememberCartesianChart( + rememberRawMarketChartLayer( + lineColor = Color.Blue, + backgroundLineColor = Color.Blue.copy(alpha = 0.24f), + secondLineColor = Color.Gray, + backgroundSecondLineColor = Color.Gray.copy(alpha = 0.24f), + markerFraction = 0.35f, + secondColorOnTheRightSide = true, + axisValueOverrider = AxisValueOverrider.fixed(minY = model.models[0].minY), + ), + ), + zoomState = rememberVicoZoomState(initialZoom = Zoom.Content, zoomEnabled = false), + horizontalLayout = HorizontalLayout.fullWidth(), + model = model, + ) + + CartesianChartHost( + modifier = Modifier.fillMaxWidth(), + chart = rememberCartesianChart( + rememberRawMarketChartLayer( + lineColor = Color.Blue, + backgroundLineColor = Color.Blue.copy(alpha = 0.24f), + secondLineColor = Color.Blue, + backgroundSecondLineColor = Color.Blue.copy(alpha = 0.24f), + markerFraction = 0.35f, + secondColorOnTheRightSide = true, + animationFraction = 0.7f, + axisValueOverrider = AxisValueOverrider.fixed(minY = model.models[0].minY), + ), + ), + zoomState = rememberVicoZoomState(initialZoom = Zoom.Content, zoomEnabled = false), + horizontalLayout = HorizontalLayout.fullWidth(), + model = model, + ) + } + } +} + +// endregion Preview \ No newline at end of file diff --git a/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/marker/ChartMarker.kt b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/marker/ChartMarker.kt new file mode 100644 index 0000000000..4675085e2a --- /dev/null +++ b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/marker/ChartMarker.kt @@ -0,0 +1,135 @@ +package com.tangem.common.ui.charts.marker + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.patrykandpatrick.vico.compose.cartesian.CartesianChartHost +import com.patrykandpatrick.vico.compose.cartesian.fullWidth +import com.patrykandpatrick.vico.compose.cartesian.layer.rememberLineCartesianLayer +import com.patrykandpatrick.vico.compose.cartesian.layer.rememberLineSpec +import com.patrykandpatrick.vico.compose.cartesian.rememberCartesianChart +import com.patrykandpatrick.vico.compose.cartesian.rememberVicoZoomState +import com.patrykandpatrick.vico.compose.common.component.rememberLayeredComponent +import com.patrykandpatrick.vico.compose.common.component.rememberShapeComponent +import com.patrykandpatrick.vico.compose.common.component.rememberUnboundedLineComponent +import com.patrykandpatrick.vico.compose.common.of +import com.patrykandpatrick.vico.compose.common.shader.color +import com.patrykandpatrick.vico.compose.common.shape.dashed +import com.patrykandpatrick.vico.core.cartesian.* +import com.patrykandpatrick.vico.core.cartesian.data.AxisValueOverrider +import com.patrykandpatrick.vico.core.cartesian.marker.CartesianMarker +import com.patrykandpatrick.vico.core.cartesian.marker.DefaultCartesianMarker +import com.patrykandpatrick.vico.core.common.Dimensions +import com.patrykandpatrick.vico.core.common.component.TextComponent +import com.patrykandpatrick.vico.core.common.data.ExtraStore +import com.patrykandpatrick.vico.core.common.shader.DynamicShader +import com.patrykandpatrick.vico.core.common.shape.Shape +import com.tangem.common.ui.charts.preview.getPreviewBigCartData +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview + +/** + * @param color The color of the indicator and guideline. + * @param innerCircleColor The color of the inner circle of the indicator. + * + * @return A [CartesianMarker] that consists of a dashed guideline and a layered indicator with a shadow effect. + */ +@Composable +internal fun rememberTangemChartMarker(color: Color, innerCircleColor: Color): CartesianMarker { + val indicatorFrontComponent = rememberShapeComponent( + shape = Shape.Pill, + color = innerCircleColor, + ) + val indicatorCenterComponent = rememberShapeComponent( + shape = Shape.Pill, + color = color, + ) + val indicatorRearComponent = rememberShapeComponent( + shape = Shape.Pill, + color = color.copy(alpha = INDICATOR_REAR_COLOR_ALPHA), + ) + val indicator = rememberLayeredComponent( + rear = indicatorRearComponent, + front = rememberLayeredComponent( + rear = indicatorCenterComponent, + front = indicatorFrontComponent, + padding = indicatorPadding, + ), + padding = indicatorPadding, + ) + val guideline = rememberUnboundedLineComponent( + color = color, + verticalAddDrawSpace = TangemTheme.dimens.spacing24, + shape = remember { Shape.dashed(Shape.Rectangle, 4.dp, 4.dp) }, + ) + return remember(indicator, guideline) { + object : DefaultCartesianMarker( + label = TextComponent.build { textSizeSp = 0f }, + indicator = indicator, + indicatorSizeDp = INDICATOR_SIZE_DP, + guideline = guideline, + ) { + override fun getInsets( + context: CartesianMeasureContext, + outInsets: Insets, + horizontalDimensions: HorizontalDimensions, + ) { + with(context) { + super.getInsets(context, outInsets, horizontalDimensions) + val baseShadowInsetDp = + CLIPPING_FREE_SHADOW_RADIUS_MULTIPLIER * LABEL_BACKGROUND_SHADOW_RADIUS_DP + outInsets.top += (baseShadowInsetDp - LABEL_BACKGROUND_SHADOW_DY_DP).pixels + outInsets.bottom += (baseShadowInsetDp + LABEL_BACKGROUND_SHADOW_DY_DP).pixels + } + } + } + } +} + +private val indicatorPadding = Dimensions.of(3.dp) +private const val LABEL_BACKGROUND_SHADOW_RADIUS_DP = 4f +private const val LABEL_BACKGROUND_SHADOW_DY_DP = 2f +private const val CLIPPING_FREE_SHADOW_RADIUS_MULTIPLIER = 1.4f +private const val INDICATOR_SIZE_DP = 16f +private const val INDICATOR_REAR_COLOR_ALPHA = .24f + +// region Preview + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun TangemChartMarkerPreview() { + val marker = rememberTangemChartMarker(Color.Red, Color.White) + val xListKey = ExtraStore.Key>() + val model = getPreviewBigCartData(xListKey) + val centerAprx = (model.models[0].minX + model.models[0].maxX) / 2f + val center = model.models[0].getXDeltaGcd().let { centerAprx - centerAprx % it } + + TangemThemePreview { + Box(modifier = Modifier.background(TangemTheme.colors.background.primary)) { + CartesianChartHost( + modifier = Modifier.fillMaxWidth(), + chart = rememberCartesianChart( + rememberLineCartesianLayer( + listOf(rememberLineSpec(shader = DynamicShader.color(Color.Blue))), + axisValueOverrider = AxisValueOverrider.fixed(minY = model.models[0].minY), + ), + persistentMarkers = mapOf(center to marker), + ), + model = model, + marker = marker, + zoomState = rememberVicoZoomState(initialZoom = Zoom.Content, zoomEnabled = false), + horizontalLayout = HorizontalLayout.fullWidth(), + ) + } + } +} + +// endregion Preview \ No newline at end of file diff --git a/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/preview/PreviewData.kt b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/preview/PreviewData.kt new file mode 100644 index 0000000000..0b90226888 --- /dev/null +++ b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/preview/PreviewData.kt @@ -0,0 +1,77 @@ +@file:Suppress("MagicNumber", "LongMethod") + +package com.tangem.common.ui.charts.preview + +import com.patrykandpatrick.vico.core.cartesian.data.CartesianChartModel +import com.patrykandpatrick.vico.core.cartesian.data.LineCartesianLayerModel +import com.patrykandpatrick.vico.core.common.data.ExtraStore +import com.patrykandpatrick.vico.core.common.data.MutableExtraStore + +internal fun getPreviewBigCartData(xListKey: ExtraStore.Key>): CartesianChartModel { + val y = listOf( + 59270, 61748, 61941, 62889, 62740, 62989, 63858, 63608, 63951, 63917, + 63253, 63765, 63862, 64502, 63876, 64028, 63875, 64531, 64249, 63680, + 63228, 63159, 63249, 63664, 63469, 63711, 63003, 62333, 62882, 62183, + 62231, 62244, 62200, 61188, 61683, 61199, 61036, 62116, 62436, 63065, + 62908, 63067, 63294, 60904, 60677, 60790, 60705, 61041, 60667, 61158, + 61112, 60795, 60900, 60771, 61124, 61343, 61371, 61484, 61133, 62372, + 62704, 63007, 63092, 62905, 62470, 62019, 61756, 61776, 61557, 61540, + 61904, 62151, 62419, 64663, 65955, 66229, 65991, 66176, 66517, 65838, + 65210, 65216, 65611, 66467, 66209, 67247, 66913, 67059, 66978, 66845, + 67240, 66874, 66993, 66940, 67185, 67330, 67340, 66845, 66062, 66273, + 66645, 66865, 67005, 67382, 70049, 71464, 71293, 70875, 71137, 69720, + 69323, 70139, 69964, 69716, 69855, 70442, 69774, 69125, 69404, 69714, + 69967, 68042, 67077, 67938, 67833, 67182, 67306, 68327, 69093, 68517, + 68726, 68759, 69061, 68880, 69148, 69305, 69044, 69313, 69122, 68821, + 68854, 68506, 68823, 68613, 68420, 70356, 69241, 69401, 68004, 67630, + 68311, 68311, 68291, 68302, 68717, 67926, 67690, 67314, 67285, 67567, + 68026, 67552, 67740, 68519, 68611, 68363, 68503, 68171, 68326, 67121, + 67626, 67481, 67657, 67567, 67608, 67607, 67683, 67729, 67733, 67709, + ) + val timestamps: List = listOf( + 1714752000000, 1714766400000, 1714780800000, 1714795200000, 1714809600000, + 1714824000000, 1714838400000, 1714852800000, 1714867200000, 1714881600000, + 1714896000000, 1714910400000, 1714924800000, 1714939200000, 1714953600000, + 1714968000000, 1714982400000, 1714996800000, 1715011200000, 1715025600000, + 1715040000000, 1715054400000, 1715068800000, 1715083200000, 1715097600000, + 1715112000000, 1715126400000, 1715140800000, 1715155200000, 1715169600000, + 1715184000000, 1715198400000, 1715212800000, 1715227200000, 1715241600000, + 1715256000000, 1715270400000, 1715284800000, 1715299200000, 1715313600000, + 1715328000000, 1715342400000, 1715356800000, 1715371200000, 1715385600000, + 1715400000000, 1715414400000, 1715428800000, 1715443200000, 1715457600000, + 1715472000000, 1715486400000, 1715500800000, 1715515200000, 1715529600000, + 1715544000000, 1715558400000, 1715572800000, 1715587200000, 1715601600000, + 1715616000000, 1715630400000, 1715644800000, 1715659200000, 1715673600000, + 1715688000000, 1715702400000, 1715716800000, 1715731200000, 1715745600000, + 1715760000000, 1715774400000, 1715788800000, 1715803200000, 1715817600000, + 1715832000000, 1715846400000, 1715860800000, 1715875200000, 1715889600000, + 1715904000000, 1715918400000, 1715932800000, 1715947200000, 1715961600000, + 1715976000000, 1715990400000, 1716004800000, 1716019200000, 1716033600000, + 1716048000000, 1716062400000, 1716076800000, 1716091200000, 1716105600000, + 1716120000000, 1716134400000, 1716148800000, 1716163200000, 1716177600000, + 1716192000000, 1716206400000, 1716220800000, 1716235200000, 1716249600000, + 1716264000000, 1716278400000, 1716292800000, 1716307200000, 1716321600000, + 1716336000000, 1716350400000, 1716364800000, 1716379200000, 1716393600000, + 1716408000000, 1716422400000, 1716436800000, 1716451200000, 1716465600000, + 1716480000000, 1716494400000, 1716508800000, 1716523200000, 1716537600000, + 1716552000000, 1716566400000, 1716580800000, 1716595200000, 1716609600000, + 1716624000000, 1716638400000, 1716652800000, 1716667200000, 1716681600000, + 1716696000000, 1716710400000, 1716724800000, 1716739200000, 1716753600000, + 1716768000000, 1716782400000, 1716796800000, 1716811200000, 1716825600000, + 1716840000000, 1716854400000, 1716868800000, 1716883200000, 1716897600000, + 1716912000000, 1716926400000, 1716940800000, 1716955200000, 1716969600000, + 1716984000000, 1716998400000, 1717012800000, 1717027200000, 1717041600000, + 1717056000000, 1717070400000, 1717084800000, 1717099200000, 1717113600000, + 1717128000000, 1717142400000, 1717156800000, 1717171200000, 1717185600000, + 1717200000000, 1717214400000, 1717228800000, 1717243200000, 1717257600000, + 1717272000000, 1717286400000, 1717300800000, 1717315200000, 1717329600000, + ) + + val x = List(y.size) { index -> index } + + return CartesianChartModel(LineCartesianLayerModel.build { series(x, y) }).copy( + extraStore = MutableExtraStore().apply { + set(xListKey, timestamps) + }, + ) +} \ No newline at end of file diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 8a1c580d07..3992a40b54 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -91,6 +91,8 @@ tangemBlockchainSdk = "develop-654" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-360" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ +tangemVico = "2.0.0-alpha.21-tangem13" +#tangemVico = "0.0.1" # Keep it! - used for local builds ^ # endregion Tangem # region Tools @@ -180,6 +182,10 @@ firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" tangem-blockchain = { module = "com.tangem:blockchain", version.ref = "tangemBlockchainSdk" } tangem-card-android = { module = "com.tangem.tangem-sdk-kotlin:android", version.ref = "tangemCardSdk" } tangem-card-core = { module = "com.tangem.tangem-sdk-kotlin:core", version.ref = "tangemCardSdk" } + +tangem-vico-compose = { group = "com.tangem.vico", name = "compose", version.ref = "tangemVico" } +tangem-vico-compose-m3 = { group = "com.tangem.vico", name = "compose-m3", version.ref = "tangemVico" } +tangem-vico-core = { group = "com.tangem.vico", name = "core", version.ref = "tangemVico" } # endregion Tangem # region Detekt diff --git a/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/extension/BaseExtensionConfigurations.kt b/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/extension/BaseExtensionConfigurations.kt index c47360c0fc..67de36d6df 100644 --- a/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/extension/BaseExtensionConfigurations.kt +++ b/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/extension/BaseExtensionConfigurations.kt @@ -20,6 +20,7 @@ internal fun BaseExtension.configureCompilerOptions() { internal fun BaseExtension.configureCompose(project: Project) { val useCompose = with(project.path) { contains(":ui") || + contains(":common:ui-charts") || contains(":features:onboarding") || // TODO: divide on api/impl after migrating all onboarding to module contains(Regex(pattern = ":presentation\$")) || contains(Regex(pattern = ":app\$")) || // TODO: [REDACTED_JIRA] diff --git a/settings.gradle.kts b/settings.gradle.kts index 9f9643c29f..0b65a0a105 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,6 +39,7 @@ dependencyResolutionManagement { includeModule("com.tangem", "blockchain") includeModule("com.tangem", "wallet-core-proto") includeModule("com.tangem", "wallet-core") + includeModule("com.tangem", "vico") } } maven { @@ -80,6 +81,17 @@ dependencyResolutionManagement { includeModule("com.tangem", "wallet-core") } } + maven { + // setting any repository from tangem project allows maven search all packages in the project + url = uri("https://maven.pkg.github.com/tangem/vico") + credentials { + username = properties.getProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = properties.getProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + content { + includeGroupAndSubgroups("com.tangem.vico") + } + } jcenter { // unable to replace with mavenCentral() due to rekotlin content { includeModule("org.rekotlin", "rekotlin") @@ -100,6 +112,7 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") include(":app") include(":common") +include(":common:ui-charts") // region Core modules include(":core:analytics")