feat(stats): improve heatmap layout

This commit is contained in:
Nishant Mishra
2025-12-15 11:34:02 +05:30
parent ea36d8d971
commit 1b8773456b

View File

@@ -30,7 +30,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.shapes import androidx.compose.material3.MaterialTheme.shapes
import androidx.compose.material3.MaterialTheme.typography import androidx.compose.material3.MaterialTheme.typography
@@ -199,7 +201,7 @@ fun FocusBreakRatioVisualization(
} }
val HEATMAP_CELL_SIZE = 28.dp val HEATMAP_CELL_SIZE = 28.dp
val HEATMAP_CELL_GAP = 4.dp val HEATMAP_CELL_GAP = 2.dp
/** /**
* A horizontally scrollable heatmap with week labels in the first column * A horizontally scrollable heatmap with week labels in the first column
@@ -224,6 +226,7 @@ fun HeatmapWithWeekLabels(
maxValue: Long = remember { data.fastMaxBy { it?.sum() ?: 0 }?.sum() ?: 0 }, maxValue: Long = remember { data.fastMaxBy { it?.sum() ?: 0 }?.sum() ?: 0 },
) { ) {
val locale = Locale.getDefault() val locale = Locale.getDefault()
val shapes = shapes
val first7 = remember(locale) { val first7 = remember(locale) {
val monday = LocalDate.of(2024, 1, 1) // Monday val monday = LocalDate.of(2024, 1, 1) // Monday
@@ -243,42 +246,66 @@ fun HeatmapWithWeekLabels(
} }
} // Names of the 7 days of the week in the current locale } // Names of the 7 days of the week in the current locale
LazyHorizontalGrid( Row(modifier) {
rows = GridCells.Fixed(7), Column(
modifier = modifier.height(size * 7 + gap * 6), verticalArrangement = Arrangement.spacedBy(gap),
contentPadding = contentPadding, ) {
verticalArrangement = Arrangement.spacedBy(gap), first7.fastForEach {
horizontalArrangement = Arrangement.spacedBy(gap) Box(
) { contentAlignment = Alignment.Center,
items(first7) { modifier = Modifier.size(size)
Box( ) {
contentAlignment = Alignment.CenterStart, Text(
modifier = Modifier.size(size) text = it,
) { style = typography.labelSmall
Text( )
text = it, }
style = typography.labelSmall
)
} }
} }
items(data) { LazyHorizontalGrid(
if (it == null) { rows = GridCells.Fixed(7),
Spacer(Modifier.size(size)) modifier = Modifier
} else { .height(size * 7 + gap * 6)
Spacer( .clip(shapes.small.copy(topEnd = CornerSize(0), bottomEnd = CornerSize(0))),
Modifier contentPadding = contentPadding,
.size(size) verticalArrangement = Arrangement.spacedBy(gap),
.background( horizontalArrangement = Arrangement.spacedBy(gap)
colorScheme.primary.copy( ) {
remember(it) { itemsIndexed(data) { index, it ->
val sum = it.sum().toFloat() if (it == null) {
if (sum > 0) 0.3f + (0.7f * sum / maxValue) Spacer(Modifier.size(size))
else 0f } else {
} val sum = remember { it.sum().toFloat() }
),
shapes.small val shape = remember {
val top = data.getOrNull(index - 1) != null && index % 7 != 0
val end = data.getOrNull(index + 7) != null
val bottom = data.getOrNull(index + 1) != null && index % 7 != 6
val start = data.getOrNull(index - 7) != null
RoundedCornerShape(
topStart = if (top || start) shapes.extraSmall.topStart else shapes.small.topStart,
topEnd = if (top || end) shapes.extraSmall.topEnd else shapes.small.topEnd,
bottomStart = if (bottom || start) shapes.extraSmall.bottomStart else shapes.small.bottomStart,
bottomEnd = if (bottom || end) shapes.extraSmall.bottomEnd else shapes.small.bottomEnd
) )
) }
if (sum > 0)
Spacer(
Modifier
.size(size)
.background(
colorScheme.primary.copy(0.33f + (0.67f * sum / maxValue)),
shape
)
)
else Spacer(
Modifier
.size(size)
.background(colorScheme.surfaceVariant, shape)
)
}
} }
} }
} }