From 8d77333fec328e053e45a9bd59614c3b1184116f Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sat, 29 Nov 2025 15:53:32 +0530 Subject: [PATCH] refactor(utils): use time formats from resources to enable localization Closes: #151 --- .../ui/statsScreen/ProductivityGraph.kt | 7 ++-- .../pomodoro/ui/statsScreen/StatsScreen.kt | 38 ++++++++++++++---- .../ui/statsScreen/TimeColumnChart.kt | 19 ++++++--- .../pomodoro/ui/statsScreen/TimeLineChart.kt | 18 ++++++--- app/src/main/res/values/strings.xml | 39 ++++++++++--------- 5 files changed, 81 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/ProductivityGraph.kt b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/ProductivityGraph.kt index 70c928d..5b53ac1 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/ProductivityGraph.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/ProductivityGraph.kt @@ -32,7 +32,6 @@ import androidx.compose.ui.unit.dp import com.patrykandpatrick.vico.core.cartesian.data.CartesianChartModelProducer import com.patrykandpatrick.vico.core.cartesian.data.CartesianValueFormatter import org.nsh07.pomodoro.R -import org.nsh07.pomodoro.utils.millisecondsToHoursMinutes @Composable fun ColumnScope.ProductivityGraph( @@ -53,6 +52,9 @@ fun ColumnScope.ProductivityGraph( Spacer(Modifier.height(8.dp)) TimeColumnChart( modelProducer, + hoursFormat = stringResource(R.string.hours_format), + hoursMinutesFormat = stringResource(R.string.hours_and_minutes_format), + minutesFormat = stringResource(R.string.minutes_format), axisTypeface = axisTypeface, markerTypeface = markerTypeface, xValueFormatter = CartesianValueFormatter { _, value, _ -> @@ -63,9 +65,6 @@ fun ColumnScope.ProductivityGraph( 3.0 -> "18 - 24" else -> "" } - }, - yValueFormatter = CartesianValueFormatter { _, value, _ -> - millisecondsToHoursMinutes(value.toLong()) } ) } diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/StatsScreen.kt b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/StatsScreen.kt index 66c3957..42ad7e3 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/StatsScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/StatsScreen.kt @@ -130,6 +130,10 @@ fun StatsScreen( ) { val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() + val hoursFormat = stringResource(R.string.hours_format) + val hoursMinutesFormat = stringResource(R.string.hours_and_minutes_format) + val minutesFormat = stringResource(R.string.minutes_format) + var lastWeekStatExpanded by rememberSaveable { mutableStateOf(false) } var lastMonthStatExpanded by rememberSaveable { mutableStateOf(false) } @@ -223,7 +227,10 @@ fun StatsScreen( ) Text( remember(todayStat) { - millisecondsToHoursMinutes(todayStat?.totalFocusTime() ?: 0) + millisecondsToHoursMinutes( + todayStat?.totalFocusTime() ?: 0, + hoursMinutesFormat + ) }, style = typography.displaySmall, color = colorScheme.onPrimaryContainer, @@ -249,7 +256,10 @@ fun StatsScreen( ) Text( remember(todayStat) { - millisecondsToHoursMinutes(todayStat?.breakTime ?: 0) + millisecondsToHoursMinutes( + todayStat?.breakTime ?: 0, + hoursMinutesFormat + ) }, style = typography.displaySmall, color = colorScheme.onTertiaryContainer, @@ -282,7 +292,8 @@ fun StatsScreen( millisecondsToHoursMinutes( remember(lastWeekAverageFocusTimes) { lastWeekAverageFocusTimes.sum().toLong() - } + }, + hoursMinutesFormat ), style = typography.displaySmall ) @@ -295,7 +306,10 @@ fun StatsScreen( } item { TimeColumnChart( - lastWeekSummaryChartData.first, + modelProducer = lastWeekSummaryChartData.first, + hoursFormat = hoursFormat, + hoursMinutesFormat = hoursMinutesFormat, + minutesFormat = minutesFormat, modifier = Modifier.padding(start = 16.dp), axisTypeface = axisTypeface, markerTypeface = markerTypeface, @@ -361,7 +375,8 @@ fun StatsScreen( millisecondsToHoursMinutes( remember(lastMonthAverageFocusTimes) { lastMonthAverageFocusTimes.sum().toLong() - } + }, + hoursMinutesFormat ), style = typography.displaySmall ) @@ -374,7 +389,10 @@ fun StatsScreen( } item { TimeColumnChart( - lastMonthSummaryChartData.first, + modelProducer = lastMonthSummaryChartData.first, + hoursFormat = hoursFormat, + hoursMinutesFormat = hoursMinutesFormat, + minutesFormat = minutesFormat, modifier = Modifier.padding(start = 16.dp), axisTypeface = axisTypeface, markerTypeface = markerTypeface, @@ -441,7 +459,8 @@ fun StatsScreen( millisecondsToHoursMinutes( remember(lastYearAverageFocusTimes) { lastYearAverageFocusTimes.sum().toLong() - } + }, + hoursMinutesFormat ), style = typography.displaySmall ) @@ -454,7 +473,10 @@ fun StatsScreen( } item { TimeLineChart( - lastYearSummaryChartData.first, + modelProducer = lastYearSummaryChartData.first, + hoursFormat = hoursFormat, + hoursMinutesFormat = hoursMinutesFormat, + minutesFormat = minutesFormat, modifier = Modifier.padding(start = 16.dp), axisTypeface = axisTypeface, markerTypeface = markerTypeface, 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 41585c0..ced5ff4 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 @@ -68,6 +68,9 @@ import org.nsh07.pomodoro.utils.millisecondsToMinutes @Composable fun TimeColumnChart( modelProducer: CartesianChartModelProducer, + hoursFormat: String, + hoursMinutesFormat: String, + minutesFormat: String, modifier: Modifier = Modifier, axisTypeface: Typeface = Typeface.DEFAULT, markerTypeface: Typeface = Typeface.DEFAULT, @@ -76,9 +79,9 @@ fun TimeColumnChart( xValueFormatter: CartesianValueFormatter = CartesianValueFormatter.Default, yValueFormatter: CartesianValueFormatter = CartesianValueFormatter { _, value, _ -> if (value >= 60 * 60 * 1000) { - millisecondsToHours(value.toLong()) + millisecondsToHours(value.toLong(), hoursFormat) } else { - millisecondsToMinutes(value.toLong()) + millisecondsToMinutes(value.toLong(), minutesFormat) } }, markerValueFormatter: DefaultCartesianMarker.ValueFormatter = DefaultCartesianMarker.ValueFormatter { _, targets -> @@ -88,9 +91,9 @@ fun TimeColumnChart( } else 0L if (value >= 60 * 60 * 1000) { - millisecondsToHoursMinutes(value) + millisecondsToHoursMinutes(value, hoursMinutesFormat) } else { - millisecondsToMinutes(value) + millisecondsToMinutes(value, minutesFormat) } }, animationSpec: AnimationSpec? = null @@ -179,7 +182,13 @@ private fun TimeColumnChartPreview() { } TomatoTheme { Surface { - TimeColumnChart(thickness = 8.dp, modelProducer = modelProducer) + TimeColumnChart( + thickness = 8.dp, + modelProducer = modelProducer, + hoursFormat = "%dh", + hoursMinutesFormat = "%dh %dm", + minutesFormat = "%dm" + ) } } } 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 29f6e69..5083b14 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 @@ -74,6 +74,9 @@ import org.nsh07.pomodoro.utils.millisecondsToMinutes @Composable fun TimeLineChart( modelProducer: CartesianChartModelProducer, + hoursFormat: String, + hoursMinutesFormat: String, + minutesFormat: String, modifier: Modifier = Modifier, axisTypeface: Typeface = Typeface.DEFAULT, markerTypeface: Typeface = Typeface.DEFAULT, @@ -82,9 +85,9 @@ fun TimeLineChart( xValueFormatter: CartesianValueFormatter = CartesianValueFormatter.Default, yValueFormatter: CartesianValueFormatter = CartesianValueFormatter { _, value, _ -> if (value >= 60 * 60 * 1000) { - millisecondsToHours(value.toLong()) + millisecondsToHours(value.toLong(), hoursFormat) } else { - millisecondsToMinutes(value.toLong()) + millisecondsToMinutes(value.toLong(), minutesFormat) } }, markerValueFormatter: DefaultCartesianMarker.ValueFormatter = DefaultCartesianMarker.ValueFormatter { _, targets -> @@ -94,9 +97,9 @@ fun TimeLineChart( } else 0L if (value >= 60 * 60 * 1000) { - millisecondsToHoursMinutes(value) + millisecondsToHoursMinutes(value, hoursMinutesFormat) } else { - millisecondsToMinutes(value) + millisecondsToMinutes(value, minutesFormat) } }, animationSpec: AnimationSpec? = null @@ -203,7 +206,12 @@ private fun TimeLineChartPreview() { } TomatoTheme { Surface { - TimeLineChart(modelProducer = modelProducer) + TimeLineChart( + modelProducer = modelProducer, + hoursFormat = "%dh", + hoursMinutesFormat = "%dh %dm", + minutesFormat = "%dm" + ) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 433cd72..341610a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -22,25 +22,40 @@ Always On Display Tap anywhere when viewing the timer to switch to AOD mode Tomato + Tomato+ + Appearance Black theme Use a pure black dark theme + BuyMeACoffee Break Choose color scheme + Choose language Choose theme Color Color scheme Completed Dark + Do Not Disturb + Turn on DND when running a Focus timer + Durations Dynamic + Dynamic color + Adapt theme colors from your wallpaper Exit Focus focus per day (avg) + Get Tomato+ + Help with translation + %dh %dm + %dh + Language Last month Last week Last year Light Long break %1$s min remaining + %dm Monthly productivity analysis More More info @@ -51,13 +66,16 @@ A \"session\" is a sequence of pomodoro intervals that contain focus intervals, short break intervals, and a long break interval. The last break of a session is always a long break. Productivity analysis Focus durations at different times of the day + Rate on Google Play Restart + Selected Session length Focus intervals in one session: %1$d Settings Short break Skip Skip to next + Sound Start Start next Stats @@ -70,28 +88,13 @@ Timer Timer progress %1$d of %2$d + Reset the timer to change settings Today + Tomato FOSS + All features are unlocked in this version. If my app made a difference in your life, please consider supporting me by donating on %1$s. Up next Up next: %1$s (%2$s) Vibration Vibrate when a timer completes Weekly productivity analysis - Appearance - Durations - Sound - Do Not Disturb - Turn on DND when running a Focus timer - Tomato+ - Get Tomato+ - Dynamic color - Adapt theme colors from your wallpaper - Tomato FOSS - All features are unlocked in this version. If my app made a difference in your life, please consider supporting me by donating on %1$s. - Language - Choose language - Rate on Google Play - BuyMeACoffee - Selected - Help with translation - Reset the timer to change settings \ No newline at end of file