diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeColumnChart.kt b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeColumnChart.kt index ef5c563..7866783 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeColumnChart.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeColumnChart.kt @@ -1,20 +1,34 @@ /* * Copyright (c) 2025 Nishant Mishra * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * This file is part of Tomato - a minimalist pomodoro timer for Android. + * + * Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Tomato. + * If not, see . */ package org.nsh07.pomodoro.ui.statsScreen import androidx.compose.animation.core.AnimationSpec +import androidx.compose.foundation.layout.height import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.material3.MaterialTheme.motionScheme +import androidx.compose.material3.MaterialTheme.typography import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -37,10 +51,16 @@ import com.patrykandpatrick.vico.core.cartesian.data.CartesianChartModelProducer import com.patrykandpatrick.vico.core.cartesian.data.CartesianValueFormatter import com.patrykandpatrick.vico.core.cartesian.data.columnSeries import com.patrykandpatrick.vico.core.cartesian.layer.ColumnCartesianLayer +import com.patrykandpatrick.vico.core.cartesian.marker.ColumnCartesianLayerMarkerTarget +import com.patrykandpatrick.vico.core.cartesian.marker.DefaultCartesianMarker import com.patrykandpatrick.vico.core.common.Fill +import com.patrykandpatrick.vico.core.common.Insets +import com.patrykandpatrick.vico.core.common.component.ShapeComponent +import com.patrykandpatrick.vico.core.common.component.TextComponent import com.patrykandpatrick.vico.core.common.shape.CorneredShape import org.nsh07.pomodoro.ui.theme.TomatoTheme import org.nsh07.pomodoro.utils.millisecondsToHours +import org.nsh07.pomodoro.utils.millisecondsToHoursMinutes import org.nsh07.pomodoro.utils.millisecondsToMinutes @OptIn(ExperimentalMaterial3ExpressiveApi::class) @@ -58,6 +78,18 @@ fun TimeColumnChart( millisecondsToMinutes(value.toLong()) } }, + markerValueFormatter: DefaultCartesianMarker.ValueFormatter = DefaultCartesianMarker.ValueFormatter { _, targets -> + val first = targets.firstOrNull() + val value = if (first is ColumnCartesianLayerMarkerTarget) { + first.columns.sumOf { it.entry.y.toLong() } + } else 0L + + if (value >= 60 * 60 * 1000) { + millisecondsToHoursMinutes(value) + } else { + millisecondsToMinutes(value) + } + }, animationSpec: AnimationSpec? = motionScheme.slowEffectsSpec() ) { ProvideVicoTheme(rememberM3VicoTheme()) { @@ -88,6 +120,20 @@ fun TimeColumnChart( guideline = rememberLineComponent(Fill.Transparent), valueFormatter = xValueFormatter ), + marker = DefaultCartesianMarker( + TextComponent( + color = colorScheme.surface.toArgb(), + background = ShapeComponent( + fill = fill(colorScheme.onSurface), + shape = CorneredShape.Pill + ), + textSizeSp = typography.labelSmall.fontSize.value, + lineHeightSp = typography.labelSmall.fontSize.value, + padding = Insets(verticalDp = 4f, horizontalDp = 8f), + margins = Insets(bottomDp = 2f) + ), + valueFormatter = markerValueFormatter + ), fadingEdges = FadingEdges() ), modelProducer = modelProducer, @@ -97,7 +143,7 @@ fun TimeColumnChart( minZoom = Zoom.min(Zoom.Content, Zoom.fixed()) ), animationSpec = animationSpec, - modifier = modifier, + modifier = modifier.height(224.dp), ) } } diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeLineChart.kt b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeLineChart.kt index 73485f9..5a5b290 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeLineChart.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeLineChart.kt @@ -1,15 +1,28 @@ /* * Copyright (c) 2025 Nishant Mishra * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * This file is part of Tomato - a minimalist pomodoro timer for Android. + * + * Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Tomato. + * If not, see . */ package org.nsh07.pomodoro.ui.statsScreen import androidx.compose.animation.core.AnimationSpec +import androidx.compose.foundation.layout.height import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.material3.MaterialTheme.motionScheme +import androidx.compose.material3.MaterialTheme.typography import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -41,10 +54,17 @@ import com.patrykandpatrick.vico.core.cartesian.data.CartesianValueFormatter import com.patrykandpatrick.vico.core.cartesian.data.lineSeries import com.patrykandpatrick.vico.core.cartesian.layer.LineCartesianLayer import com.patrykandpatrick.vico.core.cartesian.layer.LineCartesianLayer.LineFill.Companion.single +import com.patrykandpatrick.vico.core.cartesian.marker.DefaultCartesianMarker +import com.patrykandpatrick.vico.core.cartesian.marker.LineCartesianLayerMarkerTarget import com.patrykandpatrick.vico.core.common.Fill +import com.patrykandpatrick.vico.core.common.Insets +import com.patrykandpatrick.vico.core.common.component.ShapeComponent +import com.patrykandpatrick.vico.core.common.component.TextComponent import com.patrykandpatrick.vico.core.common.shader.ShaderProvider +import com.patrykandpatrick.vico.core.common.shape.CorneredShape import org.nsh07.pomodoro.ui.theme.TomatoTheme import org.nsh07.pomodoro.utils.millisecondsToHours +import org.nsh07.pomodoro.utils.millisecondsToHoursMinutes import org.nsh07.pomodoro.utils.millisecondsToMinutes @OptIn(ExperimentalMaterial3ExpressiveApi::class) @@ -62,6 +82,18 @@ fun TimeLineChart( millisecondsToMinutes(value.toLong()) } }, + markerValueFormatter: DefaultCartesianMarker.ValueFormatter = DefaultCartesianMarker.ValueFormatter { _, targets -> + val first = targets.firstOrNull() + val value = if (first is LineCartesianLayerMarkerTarget) { + first.points.sumOf { it.entry.y.toLong() } + } else 0L + + if (value >= 60 * 60 * 1000) { + millisecondsToHoursMinutes(value) + } else { + millisecondsToMinutes(value) + } + }, animationSpec: AnimationSpec? = motionScheme.slowEffectsSpec() ) { ProvideVicoTheme(rememberM3VicoTheme()) { @@ -102,6 +134,20 @@ fun TimeLineChart( guideline = rememberLineComponent(Fill.Transparent), valueFormatter = xValueFormatter ), + marker = DefaultCartesianMarker( + TextComponent( + color = colorScheme.surface.toArgb(), + background = ShapeComponent( + fill = fill(colorScheme.onSurface), + shape = CorneredShape.Pill + ), + textSizeSp = typography.labelSmall.fontSize.value, + lineHeightSp = typography.labelSmall.fontSize.value, + padding = Insets(verticalDp = 4f, horizontalDp = 8f), + margins = Insets(bottomDp = 2f) + ), + valueFormatter = markerValueFormatter + ), fadingEdges = FadingEdges() ), modelProducer = modelProducer, @@ -111,7 +157,7 @@ fun TimeLineChart( minZoom = Zoom.min(Zoom.Content, Zoom.fixed()) ), animationSpec = animationSpec, - modifier = modifier, + modifier = modifier.height(224.dp), ) } }