11package com.flipcash.app.tokens.internal.components.info
22
3- import androidx.compose.animation.AnimatedVisibility
43import androidx.compose.animation.animateColorAsState
54import androidx.compose.animation.core.animateFloatAsState
6- import androidx.compose.animation.fadeIn
7- import androidx.compose.animation.fadeOut
85import androidx.compose.foundation.background
6+ import androidx.compose.foundation.layout.Box
97import androidx.compose.foundation.layout.Column
108import androidx.compose.foundation.layout.PaddingValues
119import androidx.compose.foundation.layout.fillMaxWidth
@@ -23,32 +21,45 @@ import androidx.compose.ui.Modifier
2321import androidx.compose.ui.draw.alpha
2422import androidx.compose.ui.res.stringResource
2523import androidx.compose.ui.unit.dp
26- import com.flipcash.app.tokens.Period
24+ import com.flipcash.app.tokens.data.MarketCapPoint
25+ import com.flipcash.app.tokens.data.Period
26+ import com.flipcash.app.tokens.data.collapse
27+ import com.flipcash.app.tokens.internal.components.marketcap.MarketCapChart
2728import com.flipcash.features.tokens.R
2829import com.getcode.opencode.model.financial.Fiat
2930import com.getcode.opencode.model.financial.minus
3031import com.getcode.theme.CodeTheme
3132import com.getcode.theme.extraSmall
32- import com.getcode.ui.components.charts.ChartPoint
3333import com.getcode.ui.components.charts.LineTrend
3434import com.getcode.ui.components.charts.TrendType
3535import com.getcode.ui.components.text.AnimatedNumberText
3636import com.getcode.ui.utils.calculateEndPadding
37- import com.getcode.ui.utils.calculateHorizontalPadding
3837import com.getcode.ui.utils.calculateStartPadding
38+ import com.getcode.util.format
39+ import kotlinx.datetime.TimeZone
40+ import kotlinx.datetime.toLocalDateTime
41+ import kotlin.time.Clock
42+ import kotlin.time.Instant
3943
4044@Composable
4145internal fun MarketCapSection (
4246 marketCap : Fiat ,
4347 chartEnabled : Boolean ,
44- historicalData : List <ChartPoint < Long , Long > >,
48+ rawHistoricalData : List <MarketCapPoint >,
4549 selectedPeriod : Period ,
4650 modifier : Modifier = Modifier ,
4751 contentPadding : PaddingValues = PaddingValues (),
4852 onPeriodSelected : (Period ) -> Unit
4953) {
5054 var highlightedCapPoint by remember {
51- mutableStateOf<ChartPoint <Long , Long >? > (null )
55+ mutableStateOf<MarketCapPoint ?>(null )
56+ }
57+
58+ val startCap by remember(selectedPeriod, rawHistoricalData) {
59+ derivedStateOf {
60+ val startQuarks = rawHistoricalData.collapse(selectedPeriod).firstOrNull()?.y ? : return @derivedStateOf null
61+ Fiat (startQuarks, marketCap.currencyCode)
62+ }
5263 }
5364
5465 val marketCapAtPoint by remember(marketCap, highlightedCapPoint) {
@@ -59,11 +70,10 @@ internal fun MarketCapSection(
5970 }
6071 }
6172
62- val marketCapDiff by remember(marketCap, historicalData ) {
73+ val marketCapDiff by remember(marketCap, startCap ) {
6374 derivedStateOf {
64- val startCapQuarks = historicalData.firstOrNull()?.y ? : return @derivedStateOf null
65- val startCap = Fiat (startCapQuarks, marketCap.currencyCode)
66- marketCap - startCap
75+ val start = startCap ? : return @derivedStateOf null
76+ marketCap - start
6777 }
6878 }
6979
@@ -86,47 +96,23 @@ internal fun MarketCapSection(
8696
8797 if (chartEnabled) {
8898 marketCapDiff?.let { change ->
89- val isPositiveChange = change.decimalValue >= 0
90- val changeColor by animateColorAsState(
91- if (isPositiveChange) LineTrend .Up .color else LineTrend .Down .color
92- )
93-
94- val alpha by animateFloatAsState(
95- if (highlightedCapPoint == null ) 1f else 0f
96- )
97-
98- Text (
99- modifier = Modifier
100- .padding(start = contentPadding.calculateStartPadding())
101- .padding(top = CodeTheme .dimens.grid.x2)
102- .alpha(alpha)
103- .background(
104- color = changeColor.copy(0.20f ),
105- shape = MaterialTheme .shapes.extraSmall,
106- ).padding(
107- vertical = 2 .dp,
108- horizontal = CodeTheme .dimens.grid.x1
109- ),
110- text = change.formatted(
111- extraPrefix = if (change.decimalValue >= 0 ) " +" else " -" ,
112- suffix = when (selectedPeriod) {
113- Period .All -> stringResource(R .string.label_marketCapAllTime)
114- Period .Day -> stringResource(R .string.label_marketCapDay)
115- Period .Week -> stringResource(R .string.label_marketCapWeek)
116- Period .Month -> stringResource(R .string.label_marketCapMonth)
117- Period .Year -> stringResource(R .string.label_marketCapYear)
118- }
119- ),
120- style = CodeTheme .typography.textSmall,
121- color = changeColor,
122- )
123-
124- AnimatedVisibility (
125- visible = highlightedCapPoint == null ,
126- enter = fadeIn(),
127- exit = fadeOut()
99+ Box (modifier = Modifier
100+ .padding(
101+ start = contentPadding.calculateStartPadding(),
102+ top = CodeTheme .dimens.grid.x2,
103+ )
128104 ) {
105+ MarketCapChangeLabel (
106+ change = change,
107+ isVisible = highlightedCapPoint == null ,
108+ period = selectedPeriod,
109+ )
129110
111+ HighlightedPointLabel (
112+ point = highlightedCapPoint,
113+ isVisible = highlightedCapPoint != null ,
114+ period = selectedPeriod,
115+ )
130116 }
131117 }
132118
@@ -136,14 +122,110 @@ internal fun MarketCapSection(
136122 .requiredHeight(240 .dp),
137123 chartPadding = PaddingValues (end = contentPadding.calculateEndPadding()),
138124 periodPadding = PaddingValues (
139- horizontal = contentPadding.calculateHorizontalPadding().times(0.75f )
125+ start = contentPadding.calculateStartPadding(),
126+ end = contentPadding.calculateEndPadding(),
140127 ),
141- data = historicalData ,
128+ data = rawHistoricalData ,
142129 trendType = TrendType .FirstVsLast ,
143130 selectedPeriod = selectedPeriod,
144131 onPointHighlighted = { highlightedCapPoint = it },
145132 onPeriodSelected = onPeriodSelected,
146133 )
147134 }
148135 }
136+ }
137+
138+ @Composable
139+ private fun MarketCapChangeLabel (
140+ change : Fiat ,
141+ isVisible : Boolean ,
142+ period : Period ,
143+ ) {
144+ val isPositiveChange = change.decimalValue >= 0
145+ val changeColor by animateColorAsState(
146+ if (isPositiveChange) LineTrend .Up .color else LineTrend .Down .color
147+ )
148+
149+ val alpha by animateFloatAsState(
150+ if (isVisible) 1f else 0f
151+ )
152+
153+ Text (
154+ modifier = Modifier
155+ .alpha(alpha)
156+ .background(
157+ color = changeColor.copy(0.20f ),
158+ shape = MaterialTheme .shapes.extraSmall,
159+ ).padding(
160+ vertical = 2 .dp,
161+ horizontal = CodeTheme .dimens.grid.x1
162+ ),
163+ text = change.formatted(
164+ extraPrefix = if (change.decimalValue >= 0 ) " +" else " -" ,
165+ suffix = when (period) {
166+ Period .All -> stringResource(R .string.label_marketCapAllTime)
167+ Period .Day -> stringResource(R .string.label_marketCapDay)
168+ Period .Week -> stringResource(R .string.label_marketCapWeek)
169+ Period .Month -> stringResource(R .string.label_marketCapMonth)
170+ Period .Year -> stringResource(R .string.label_marketCapYear)
171+ }
172+ ),
173+ style = CodeTheme .typography.textSmall,
174+ color = changeColor,
175+ )
176+ }
177+
178+ @Composable
179+ private fun HighlightedPointLabel (
180+ point : MarketCapPoint ? ,
181+ period : Period ,
182+ isVisible : Boolean ,
183+ ) {
184+ val alpha by animateFloatAsState(
185+ if (isVisible) 1f else 0f
186+ )
187+
188+ val timeLabel = remember(point, period) {
189+ val epoch = point?.x ? : return @remember null
190+ val instant = Instant .fromEpochMilliseconds(epoch)
191+ val now = Clock .System .now()
192+ val isCurrentYear = instant.toLocalDateTime(TimeZone .currentSystemDefault()).year ==
193+ now.toLocalDateTime(TimeZone .currentSystemDefault()).year
194+
195+ when (period) {
196+ Period .All -> instant.format(" MMMM d, yyyy" )
197+ Period .Day -> instant.format(" hh:mm a" )
198+ Period .Week -> {
199+ if (isCurrentYear) {
200+ instant.format(" MMMM d" )
201+ } else {
202+ instant.format(" MMMM d, yyyy" )
203+ }
204+ }
205+ Period .Month -> {
206+ if (isCurrentYear) {
207+ instant.format(" MMMM d" )
208+ } else {
209+ instant.format(" MMMM d, yyyy" )
210+ }
211+ }
212+ Period .Year -> {
213+ if (isCurrentYear) {
214+ instant.format(" MMMM d" )
215+ } else {
216+ instant.format(" MMMM d, yyyy" )
217+ }
218+ }
219+ }
220+ }
221+
222+ if (timeLabel != null ) {
223+ Text (
224+ modifier = Modifier
225+ .alpha(alpha),
226+ text = timeLabel,
227+ style = CodeTheme .typography.textSmall,
228+ color = CodeTheme .colors.textSecondary,
229+ )
230+ }
149231}
0 commit comments