Skip to content

Commit bcf117e

Browse files
committed
style(tokens/info): cleanup market cap diff label transitions
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent c8776a2 commit bcf117e

1 file changed

Lines changed: 77 additions & 54 deletions

File tree

  • apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info

apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/MarketCapSection.kt

Lines changed: 77 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,8 @@ package com.flipcash.app.tokens.internal.components.info
22

33
import android.text.format.DateFormat
44
import androidx.compose.animation.AnimatedContent
5-
import androidx.compose.animation.AnimatedVisibility
6-
import androidx.compose.animation.Crossfade
75
import androidx.compose.animation.SizeTransform
86
import androidx.compose.animation.animateColorAsState
9-
import androidx.compose.animation.animateContentSize
10-
import androidx.compose.animation.core.animateFloatAsState
11-
import androidx.compose.animation.core.snap
127
import androidx.compose.animation.core.tween
138
import androidx.compose.animation.fadeIn
149
import androidx.compose.animation.fadeOut
@@ -18,19 +13,15 @@ import androidx.compose.foundation.layout.Box
1813
import androidx.compose.foundation.layout.Column
1914
import androidx.compose.foundation.layout.IntrinsicSize
2015
import androidx.compose.foundation.layout.PaddingValues
21-
import androidx.compose.foundation.layout.Spacer
22-
import androidx.compose.foundation.layout.fillMaxSize
2316
import androidx.compose.foundation.layout.fillMaxWidth
2417
import androidx.compose.foundation.layout.height
2518
import androidx.compose.foundation.layout.padding
2619
import androidx.compose.foundation.layout.requiredHeight
27-
import androidx.compose.foundation.layout.size
2820
import androidx.compose.material.MaterialTheme
2921
import androidx.compose.material.Text
3022
import androidx.compose.runtime.Composable
3123
import androidx.compose.runtime.derivedStateOf
3224
import androidx.compose.runtime.getValue
33-
import androidx.compose.runtime.key
3425
import androidx.compose.runtime.mutableStateOf
3526
import androidx.compose.runtime.remember
3627
import androidx.compose.runtime.setValue
@@ -43,9 +34,7 @@ import androidx.compose.ui.unit.dp
4334
import com.flipcash.app.core.data.Loadable
4435
import com.flipcash.app.tokens.data.MarketCapPoint
4536
import com.flipcash.app.tokens.data.Period
46-
import com.flipcash.app.tokens.data.collapse
4737
import com.flipcash.app.tokens.internal.components.marketcap.MarketCapChart
48-
import com.flipcash.app.tokens.internal.components.marketcap.TARGET_POINTS
4938
import com.flipcash.features.tokens.R
5039
import com.getcode.opencode.model.financial.Fiat
5140
import com.getcode.opencode.model.financial.minus
@@ -64,6 +53,12 @@ import java.util.Locale
6453
import kotlin.time.Clock
6554
import kotlin.time.Instant
6655

56+
private sealed interface MarketCapLabelState {
57+
data object Hidden : MarketCapLabelState
58+
data class Change(val change: Fiat, val period: Period) : MarketCapLabelState
59+
data class Highlighted(val point: MarketCapPoint, val period: Period) : MarketCapLabelState
60+
}
61+
6762
@Composable
6863
internal fun MarketCapSection(
6964
marketCap: Fiat,
@@ -105,6 +100,28 @@ internal fun MarketCapSection(
105100
}
106101
}
107102

103+
var lastChange by remember { mutableStateOf<MarketCapLabelState.Change?>(null) }
104+
105+
val labelState by remember(marketCapDiff, highlightedCapPoint, selectedPeriod) {
106+
derivedStateOf {
107+
val highlightedPoint = highlightedCapPoint
108+
val diff = marketCapDiff
109+
when {
110+
highlightedPoint != null -> MarketCapLabelState.Highlighted(highlightedPoint, selectedPeriod)
111+
diff != null && selectedPeriod != Period.All -> {
112+
MarketCapLabelState.Change(diff, selectedPeriod).also { lastChange = it }
113+
}
114+
else ->
115+
if (selectedPeriod == Period.All) {
116+
lastChange = null
117+
MarketCapLabelState.Hidden
118+
} else {
119+
lastChange ?: MarketCapLabelState.Hidden
120+
}
121+
}
122+
}
123+
}
124+
108125
Column(
109126
modifier = modifier,
110127
) {
@@ -123,30 +140,46 @@ internal fun MarketCapSection(
123140
)
124141

125142
if (chartEnabled) {
126-
Box(
143+
AnimatedContent(
127144
modifier = Modifier
128145
.padding(
129146
start = contentPadding.calculateStartPadding(),
130147
top = CodeTheme.dimens.grid.x1,
131-
).height(IntrinsicSize.Min),
132-
) {
133-
Crossfade(marketCapDiff) { diff ->
134-
if (diff != null) {
148+
)
149+
.height(IntrinsicSize.Max),
150+
targetState = labelState,
151+
label = "MarketCapLabel",
152+
transitionSpec = {
153+
fadeIn().togetherWith(fadeOut()).using(SizeTransform(clip = false))
154+
},
155+
contentKey = { state ->
156+
when (state) {
157+
is MarketCapLabelState.Change -> "change"
158+
is MarketCapLabelState.Highlighted -> "highlighted"
159+
MarketCapLabelState.Hidden -> "hidden"
160+
}
161+
}
162+
) { state ->
163+
when (state) {
164+
is MarketCapLabelState.Change -> MarketCapChangeLabel(
165+
change = state.change,
166+
period = state.period,
167+
)
168+
169+
is MarketCapLabelState.Highlighted -> HighlightedPointLabel(
170+
modifier = Modifier.padding(bottom = 4.dp),
171+
point = state.point,
172+
period = state.period,
173+
)
174+
175+
MarketCapLabelState.Hidden -> {
135176
MarketCapChangeLabel(
136-
change = diff,
137-
isVisible = highlightedCapPoint == null,
177+
modifier = Modifier.alpha(0f),
178+
change = Fiat.Zero,
138179
period = selectedPeriod,
139180
)
140-
} else {
141-
Spacer(Modifier.size(CodeTheme.dimens.grid.x3))
142181
}
143182
}
144-
145-
HighlightedPointLabel(
146-
point = highlightedCapPoint,
147-
isVisible = highlightedCapPoint != null,
148-
period = selectedPeriod,
149-
)
150183
}
151184

152185
MarketCapChart(
@@ -169,9 +202,10 @@ internal fun MarketCapSection(
169202
is Loadable.Error -> Unit
170203
is Loadable.Loaded -> Unit
171204
is Loadable.Loading -> {
172-
Box(modifier = Modifier
173-
.fillMaxWidth()
174-
.requiredHeight(240.dp)
205+
Box(
206+
modifier = Modifier
207+
.fillMaxWidth()
208+
.requiredHeight(240.dp)
175209
) {
176210
CodeCircularProgressIndicator(
177211
modifier = Modifier.align(Alignment.Center),
@@ -189,21 +223,17 @@ internal fun MarketCapSection(
189223
@Composable
190224
private fun MarketCapChangeLabel(
191225
change: Fiat,
192-
isVisible: Boolean,
193226
period: Period,
227+
modifier: Modifier = Modifier,
194228
) {
195229
val isPositiveChange = change.decimalValue >= 0
196230
val changeColor by animateColorAsState(
197-
if (isPositiveChange) LineTrend.Up.color else LineTrend.Down.color
198-
)
199-
200-
val alpha by animateFloatAsState(
201-
if (isVisible) 1f else 0f
231+
if (isPositiveChange) LineTrend.Up.color else LineTrend.Down.color,
232+
label = "change color"
202233
)
203234

204235
Text(
205-
modifier = Modifier
206-
.alpha(alpha)
236+
modifier = modifier
207237
.background(
208238
color = changeColor.copy(0.20f),
209239
shape = MaterialTheme.shapes.extraSmall,
@@ -229,18 +259,14 @@ private fun MarketCapChangeLabel(
229259

230260
@Composable
231261
private fun HighlightedPointLabel(
232-
point: MarketCapPoint?,
262+
point: MarketCapPoint,
233263
period: Period,
234-
isVisible: Boolean,
264+
modifier: Modifier = Modifier,
235265
) {
236-
val alpha by animateFloatAsState(
237-
if (isVisible) 1f else 0f
238-
)
239-
240266
val context = LocalContext.current
241267

242268
val timeLabel = remember(point, period) {
243-
val epoch = point?.x ?: return@remember null
269+
val epoch = point.x
244270
val instant = Instant.fromEpochMilliseconds(epoch)
245271
val now = Clock.System.now()
246272
val isCurrentYear = instant.toLocalDateTime(TimeZone.currentSystemDefault()).year ==
@@ -285,13 +311,10 @@ private fun HighlightedPointLabel(
285311
}
286312
}
287313

288-
if (timeLabel != null) {
289-
Text(
290-
modifier = Modifier
291-
.alpha(alpha),
292-
text = timeLabel,
293-
style = CodeTheme.typography.textSmall,
294-
color = CodeTheme.colors.textSecondary,
295-
)
296-
}
297-
}
314+
Text(
315+
modifier = modifier,
316+
text = timeLabel,
317+
style = CodeTheme.typography.textSmall,
318+
color = CodeTheme.colors.textSecondary,
319+
)
320+
}

0 commit comments

Comments
 (0)