mirror of
https://github.com/oliexdev/openScale.git
synced 2025-08-19 23:12:12 +02:00
Introduces a new "Chart Settings" screen accessible from the main settings menu.
This commit is contained in:
@@ -57,6 +57,9 @@ object UserPreferenceKeys {
|
||||
val SAVED_BLUETOOTH_SCALE_ADDRESS = stringPreferencesKey("saved_bluetooth_scale_address")
|
||||
val SAVED_BLUETOOTH_SCALE_NAME = stringPreferencesKey("saved_bluetooth_scale_name")
|
||||
|
||||
// Settings for chart
|
||||
val SHOW_CHART_DATA_POINTS = booleanPreferencesKey("show_chart_data_points")
|
||||
|
||||
// Context strings for screen-specific settings (can be used as prefixes for dynamic keys)
|
||||
const val OVERVIEW_SCREEN_CONTEXT = "overview_screen"
|
||||
const val GRAPH_SCREEN_CONTEXT = "graph_screen"
|
||||
@@ -90,6 +93,9 @@ interface UserSettingsRepository {
|
||||
suspend fun saveBluetoothScale(address: String, name: String?)
|
||||
suspend fun clearSavedBluetoothScale()
|
||||
|
||||
val showChartDataPoints: Flow<Boolean>
|
||||
suspend fun setShowChartDataPoints(show: Boolean)
|
||||
|
||||
// Generic Settings Accessors
|
||||
/**
|
||||
* Observes a setting with the given key name and default value.
|
||||
@@ -248,6 +254,19 @@ class UserSettingsRepositoryImpl(context: Context) : UserSettingsRepository {
|
||||
}
|
||||
}
|
||||
|
||||
override val showChartDataPoints: Flow<Boolean> = observeSetting(
|
||||
UserPreferenceKeys.SHOW_CHART_DATA_POINTS.name,
|
||||
true
|
||||
).catch { exception ->
|
||||
LogManager.e(TAG, "Error observing showChartDataPoints", exception)
|
||||
emit(true)
|
||||
}
|
||||
|
||||
override suspend fun setShowChartDataPoints(show: Boolean) {
|
||||
LogManager.d(TAG, "Setting showChartDataPoints to: $show")
|
||||
saveSetting(UserPreferenceKeys.SHOW_CHART_DATA_POINTS.name, show)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T> observeSetting(keyName: String, defaultValue: T): Flow<T> {
|
||||
LogManager.v(TAG, "Observing setting: key='$keyName', type='${defaultValue!!::class.simpleName}'")
|
||||
|
@@ -121,6 +121,7 @@ import com.health.openscale.ui.screen.overview.MeasurementDetailScreen
|
||||
import com.health.openscale.ui.screen.overview.OverviewScreen
|
||||
import com.health.openscale.ui.screen.settings.AboutScreen
|
||||
import com.health.openscale.ui.screen.settings.BluetoothScreen
|
||||
import com.health.openscale.ui.screen.settings.ChartSettingsScreen
|
||||
import com.health.openscale.ui.screen.settings.DataManagementSettingsScreen
|
||||
import com.health.openscale.ui.screen.settings.GeneralSettingsScreen
|
||||
import com.health.openscale.ui.screen.settings.MeasurementTypeDetailScreen
|
||||
@@ -683,6 +684,13 @@ fun AppNavigation(sharedViewModel: SharedViewModel) {
|
||||
bluetoothViewModel = bluetoothViewModel
|
||||
)
|
||||
}
|
||||
composable(Routes.CHART_SETTINGS) {
|
||||
ChartSettingsScreen(
|
||||
navController = navController,
|
||||
sharedViewModel = sharedViewModel,
|
||||
settingsViewModel = settingsViewModel
|
||||
)
|
||||
}
|
||||
composable(Routes.DATA_MANAGEMENT_SETTINGS) {
|
||||
DataManagementSettingsScreen(
|
||||
navController = navController,
|
||||
|
@@ -46,6 +46,7 @@ object Routes {
|
||||
const val MEASUREMENT_TYPES = "settings/types"
|
||||
const val MEASUREMENT_TYPE_DETAIL = "settings/typeDetail"
|
||||
const val BLUETOOTH_SETTINGS = "settings/bluetooth"
|
||||
const val CHART_SETTINGS = "settings/chart"
|
||||
const val DATA_MANAGEMENT_SETTINGS = "settings/dataManagement"
|
||||
const val ABOUT_SETTINGS = "settings/about"
|
||||
|
||||
|
@@ -63,6 +63,7 @@ import com.health.openscale.core.data.MeasurementTypeKey
|
||||
import com.health.openscale.core.data.TimeRangeFilter
|
||||
import com.health.openscale.core.database.UserPreferenceKeys
|
||||
import com.health.openscale.core.database.UserSettingsRepository
|
||||
import com.health.openscale.core.database.UserSettingsRepositoryImpl
|
||||
import com.health.openscale.ui.screen.SharedViewModel
|
||||
import com.patrykandpatrick.vico.compose.cartesian.CartesianChartHost
|
||||
import com.patrykandpatrick.vico.compose.cartesian.axis.rememberAxisGuidelineComponent
|
||||
@@ -142,6 +143,8 @@ fun LineChart(
|
||||
val scope = rememberCoroutineScope()
|
||||
val userSettingsRepository = sharedViewModel.userSettingRepository
|
||||
|
||||
val showDataPointsSetting by userSettingsRepository.showChartDataPoints.collectAsState(initial = true)
|
||||
|
||||
val uiSelectedTimeRange by rememberContextualTimeRangeFilter(
|
||||
screenContextName = screenContextName,
|
||||
userSettingsRepository = userSettingsRepository
|
||||
@@ -503,7 +506,11 @@ fun LineChart(
|
||||
LineCartesianLayer.LineProvider.series(
|
||||
seriesEntriesForStartAxis.mapIndexedNotNull { index, _ ->
|
||||
if (index < typeColorsForStartAxis.size) {
|
||||
createLineSpec(typeColorsForStartAxis[index], statisticsMode = targetMeasurementTypeId != null)
|
||||
createLineSpec(
|
||||
color = typeColorsForStartAxis[index],
|
||||
statisticsMode = targetMeasurementTypeId != null,
|
||||
showPoints = showDataPointsSetting
|
||||
)
|
||||
} else null
|
||||
}
|
||||
)
|
||||
@@ -522,7 +529,11 @@ fun LineChart(
|
||||
LineCartesianLayer.LineProvider.series(
|
||||
seriesEntriesForEndAxis.mapIndexedNotNull { index, _ ->
|
||||
if (index < typeColorsForEndAxis.size) {
|
||||
createLineSpec(typeColorsForEndAxis[index], statisticsMode = targetMeasurementTypeId != null)
|
||||
createLineSpec(
|
||||
color = typeColorsForEndAxis[index],
|
||||
statisticsMode = targetMeasurementTypeId != null,
|
||||
showPoints = showDataPointsSetting
|
||||
)
|
||||
} else null
|
||||
}
|
||||
)
|
||||
@@ -702,9 +713,10 @@ private fun rememberXAxisValueFormatter(
|
||||
* @param color The color of the line and points.
|
||||
* @param statisticsMode If true, an area fill is added below the line, and points are hidden.
|
||||
* This is typically used when `targetMeasurementTypeId` is set.
|
||||
* @param showPoints If true, points are displayed on the line (unless in statisticsMode).
|
||||
* @return A configured [LineCartesianLayer.Line].
|
||||
*/
|
||||
private fun createLineSpec(color: Color, statisticsMode : Boolean): LineCartesianLayer.Line {
|
||||
private fun createLineSpec(color: Color, statisticsMode : Boolean, showPoints: Boolean): LineCartesianLayer.Line {
|
||||
val lineStroke = LineCartesianLayer.LineStroke.Continuous(
|
||||
thicknessDp = 2f,
|
||||
)
|
||||
@@ -719,10 +731,11 @@ private fun createLineSpec(color: Color, statisticsMode : Boolean): LineCartesia
|
||||
// Area fill is shown in statistics mode (e.g., when a single type is focused)
|
||||
areaFill = if (statisticsMode) LineCartesianLayer.AreaFill.single(Fill(color.copy(alpha = 0.2f).toArgb())) else null,
|
||||
// Points on the line are shown unless in statistics mode
|
||||
pointProvider = if (!statisticsMode) {
|
||||
pointProvider = if (showPoints && !statisticsMode) {
|
||||
LineCartesianLayer.PointProvider.single(
|
||||
LineCartesianLayer.point(ShapeComponent(fill(color.copy(alpha = 0.7f)), CorneredShape.Pill), 6.dp)
|
||||
) } else null,
|
||||
)
|
||||
} else null,
|
||||
// dataLabel = null, // No data labels on points
|
||||
pointConnector = LineCartesianLayer.PointConnector.cubic()
|
||||
)
|
||||
|
@@ -0,0 +1,58 @@
|
||||
package com.health.openscale.ui.screen.settings
|
||||
|
||||
import androidx.activity.result.launch
|
||||
import androidx.navigation.NavController
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.health.openscale.R
|
||||
import com.health.openscale.ui.screen.SharedViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun ChartSettingsScreen(
|
||||
navController: NavController,
|
||||
sharedViewModel: SharedViewModel,
|
||||
settingsViewModel: SettingsViewModel
|
||||
) {
|
||||
val chartSettingsScreenTitle = stringResource(R.string.settings_item_chart)
|
||||
LaunchedEffect(Unit) {
|
||||
sharedViewModel.setTopBarTitle(chartSettingsScreenTitle)
|
||||
}
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val showDataPoints by sharedViewModel.userSettingRepository.showChartDataPoints.collectAsState(true)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.setting_show_chart_points),
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
Switch(
|
||||
checked = showDataPoints,
|
||||
onCheckedChange = { newValue ->
|
||||
coroutineScope.launch {
|
||||
sharedViewModel.userSettingRepository.setShowChartDataPoints(newValue)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@@ -23,10 +23,12 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ShowChart
|
||||
import androidx.compose.material.icons.filled.Bluetooth
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.ShowChart
|
||||
import androidx.compose.material.icons.filled.Storage
|
||||
import androidx.compose.material.icons.filled.Tune
|
||||
import androidx.compose.material3.Card
|
||||
@@ -79,6 +81,7 @@ fun SettingsScreen(
|
||||
val userSettingsLabel = stringResource(R.string.settings_item_user)
|
||||
val measurementTypesLabel = stringResource(R.string.settings_item_measurement_types)
|
||||
val bluetoothLabel = stringResource(R.string.settings_item_bluetooth)
|
||||
val chartSettingsLabel = stringResource(R.string.settings_item_chart)
|
||||
val dataManagementLabel = stringResource(R.string.settings_item_data_management)
|
||||
val aboutLabel = stringResource(R.string.settings_item_about)
|
||||
|
||||
@@ -107,6 +110,12 @@ fun SettingsScreen(
|
||||
route = Routes.BLUETOOTH_SETTINGS,
|
||||
contentDescription = bluetoothLabel
|
||||
),
|
||||
SettingsItem(
|
||||
label = chartSettingsLabel,
|
||||
icon = Icons.AutoMirrored.Filled.ShowChart,
|
||||
route = Routes.CHART_SETTINGS,
|
||||
contentDescription = chartSettingsLabel
|
||||
),
|
||||
SettingsItem(
|
||||
label = dataManagementLabel,
|
||||
icon = Icons.Filled.Storage,
|
||||
|
@@ -281,6 +281,7 @@
|
||||
<string name="settings_item_user">Benutzer</string>
|
||||
<string name="settings_item_measurement_types">Messarten</string>
|
||||
<string name="settings_item_bluetooth">Bluetooth</string>
|
||||
<string name="settings_item_chart">Diagramm</string>
|
||||
<string name="settings_item_data_management">Datenverwaltung</string>
|
||||
<string name="settings_item_about">Über</string>
|
||||
|
||||
@@ -288,6 +289,9 @@
|
||||
<string name="settings_general_title">Allgemeine Einstellungen</string>
|
||||
<string name="settings_language_label">Sprache</string>
|
||||
|
||||
<!-- Diagramm Einstellungen -->
|
||||
<string name="setting_show_chart_points">Datenpunkte anzeigen</string>
|
||||
|
||||
<!-- Über-Bildschirm & Diagnose -->
|
||||
<string name="version_info">Version: %1$s (%2$s)</string>
|
||||
<string name="project_information_title">Projektinformationen</string>
|
||||
|
@@ -283,6 +283,7 @@
|
||||
<string name="settings_item_user">User</string>
|
||||
<string name="settings_item_measurement_types">Measurement Types</string>
|
||||
<string name="settings_item_bluetooth">Bluetooth</string>
|
||||
<string name="settings_item_chart">Chart</string>
|
||||
<string name="settings_item_data_management">Data Management</string>
|
||||
<string name="settings_item_about">About</string>
|
||||
|
||||
@@ -290,6 +291,9 @@
|
||||
<string name="settings_general_title">General Settings</string>
|
||||
<string name="settings_language_label">Language</string>
|
||||
|
||||
<!-- Chart Settings Screen -->
|
||||
<string name="setting_show_chart_points">Show data points</string>
|
||||
|
||||
<!-- About Screen & Diagnostics -->
|
||||
<string name="version_info">Version: %1$s (%2$s)</string>
|
||||
<string name="project_information_title">Project Information</string>
|
||||
|
Reference in New Issue
Block a user