Skip to content

Commit bafaa14

Browse files
committed
Update MeasurementChart.kt, PeriodChart.kt, and MeasurementChartLayers.kt to improve X-axis formatting and label placement based on the active aggregation level (Day, Week, Month, Year).
1 parent fcc8054 commit bafaa14

3 files changed

Lines changed: 48 additions & 9 deletions

File tree

android_app/app/src/main/java/com/health/openscale/ui/screen/components/MeasurementChart.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import androidx.compose.ui.text.style.TextAlign
5252
import androidx.compose.ui.unit.dp
5353
import androidx.lifecycle.compose.collectAsStateWithLifecycle
5454
import com.health.openscale.R
55+
import com.health.openscale.core.data.AggregationLevel
5556
import com.health.openscale.core.data.InputFieldType
5657
import com.health.openscale.core.data.MeasurementType
5758
import com.health.openscale.core.data.MeasurementTypeKey
@@ -168,6 +169,7 @@ fun MeasurementChart(
168169
val isSmoothingActive by remember {
169170
sharedViewModel.selectedSmoothingAlgorithm.map { it != SmoothingAlgorithm.NONE }
170171
}.collectAsStateWithLifecycle(initialValue = false)
172+
val activeAggregationLevel by rememberResolvedAggregationLevel(screenContextName, sharedViewModel)
171173

172174
// ── Time range — still needed for the filter title label and period chart ─
173175
// Note: start/end are NOT passed to the data pipeline anymore (that happens
@@ -483,10 +485,24 @@ fun MeasurementChart(
483485

484486
val xAxis = if (targetMeasurementTypeId == null) {
485487
HorizontalAxis.rememberBottom(
486-
valueFormatter = rememberXAxisValueFormatter(chartSeries),
487-
guideline = null,
488+
valueFormatter = rememberXAxisValueFormatter(chartSeries, activeAggregationLevel),
489+
itemPlacer = remember(activeAggregationLevel) {
490+
val spacing = when (activeAggregationLevel) {
491+
AggregationLevel.NONE -> 1
492+
AggregationLevel.DAY -> 1
493+
AggregationLevel.WEEK -> 7
494+
AggregationLevel.MONTH -> 30
495+
AggregationLevel.YEAR -> 365
496+
}
497+
HorizontalAxis.ItemPlacer.aligned(
498+
spacing = { spacing },
499+
addExtremeLabelPadding = true,
500+
)
501+
},
502+
guideline = null,
488503
)
489504
} else null
505+
490506
val startYAxis = if (showYAxis)
491507
VerticalAxis.rememberStart(valueFormatter = CartesianValueFormatter.decimal())
492508
else null

android_app/app/src/main/java/com/health/openscale/ui/screen/components/MeasurementChartLayers.kt

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ import androidx.compose.runtime.LaunchedEffect
2424
import androidx.compose.runtime.mutableStateOf
2525
import androidx.compose.runtime.remember
2626
import androidx.compose.ui.graphics.Color
27+
import androidx.compose.ui.platform.LocalContext
28+
import androidx.compose.ui.res.stringResource
2729
import androidx.compose.ui.text.TextStyle
2830
import androidx.compose.ui.text.style.TextAlign
2931
import androidx.compose.ui.unit.dp
32+
import com.health.openscale.R
33+
import com.health.openscale.core.data.AggregationLevel
3034
import com.health.openscale.core.data.MeasurementType
3135
import com.health.openscale.core.data.UnitType
3236
import com.health.openscale.core.data.UserGoals
@@ -56,6 +60,7 @@ import com.patrykandpatrick.vico.compose.common.data.ExtraStore
5660
import java.time.LocalDate
5761
import java.time.ZoneId
5862
import java.time.format.DateTimeFormatter
63+
import java.time.temporal.ChronoUnit
5964
import kotlin.math.ceil
6065
import kotlin.math.floor
6166

@@ -374,14 +379,30 @@ internal fun rememberMarkerVisibilityListener(
374379

375380
/**
376381
* Remembers a [CartesianValueFormatter] for the X-axis that formats epoch day floats
377-
* back to human-readable date strings.
382+
* back to human-readable date strings. The date format adapts to the current [aggregationLevel]:
378383
*/
379384
@Composable
380-
internal fun rememberXAxisValueFormatter(chartSeries: List<ChartSeries>): CartesianValueFormatter =
381-
remember(chartSeries) {
385+
internal fun rememberXAxisValueFormatter(
386+
chartSeries: List<ChartSeries>,
387+
aggregationLevel: AggregationLevel = AggregationLevel.NONE,
388+
): CartesianValueFormatter {
389+
val weekAbbrev = stringResource(R.string.calendar_week_abbrev)
390+
return remember(chartSeries, aggregationLevel, weekAbbrev) {
382391
val xToDatesMap = chartSeries.flatMap { it.points }.associate { it.x to it.date }
392+
393+
val pattern = when (aggregationLevel) {
394+
AggregationLevel.NONE -> "d MMM"
395+
AggregationLevel.DAY -> "d MMM"
396+
AggregationLevel.WEEK -> "'${weekAbbrev}'w MMM"
397+
AggregationLevel.MONTH -> "MMM yy"
398+
AggregationLevel.YEAR -> "yyyy"
399+
}
400+
401+
val formatter = DateTimeFormatter.ofPattern(pattern)
402+
383403
CartesianValueFormatter { _, value, _ ->
384404
(xToDatesMap[value.toFloat()] ?: LocalDate.ofEpochDay(value.toLong()))
385-
.format(DateTimeFormatter.ofPattern("d MMM"))
405+
.format(formatter)
386406
}
387-
}
407+
}
408+
}

android_app/app/src/main/java/com/health/openscale/ui/screen/components/PeriodChart.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,16 @@ fun PeriodChart(
117117
columnLayer,
118118
startAxis = null,
119119
bottomAxis = HorizontalAxis.rememberBottom(
120-
itemPlacer = HorizontalAxis.ItemPlacer.segmented(),
120+
itemPlacer = HorizontalAxis.ItemPlacer.aligned(
121+
addExtremeLabelPadding = true,
122+
),
121123
valueFormatter = CartesianValueFormatter { context, x, _ ->
122124
val labels = context.model.extraStore[BottomAxisLabelKey]
123125
if (labels.isNotEmpty() && x.toInt() in labels.indices) labels[x.toInt()] else ""
124126
},
125127
guideline = null,
126128
label = rememberAxisLabelComponent(
127-
lineCount = 2, // allow wrapping if needed
129+
lineCount = 1, // no wrap
128130
)
129131
),
130132
marker = rememberMarker(

0 commit comments

Comments
 (0)