From b9203c8d5d8a08a854d98f20cd3cdc926f3165d8 Mon Sep 17 00:00:00 2001 From: oliexdev Date: Tue, 12 Aug 2025 08:17:59 +0200 Subject: [PATCH] Add scale and measure unit to user settings --- .../{1.json => 7.json} | 23 ++++- .../com/health/openscale/core/data/User.kt | 6 +- .../openscale/core/database/AppDatabase.kt | 2 +- .../ui/screen/settings/UserDetailScreen.kt | 95 ++++++++++++++++++- .../app/src/main/res/values-de/strings.xml | 3 +- .../app/src/main/res/values/strings.xml | 3 +- 6 files changed, 117 insertions(+), 15 deletions(-) rename android_app/app/schemas/com.health.openscale.core.database.AppDatabase/{1.json => 7.json} (93%) diff --git a/android_app/app/schemas/com.health.openscale.core.database.AppDatabase/1.json b/android_app/app/schemas/com.health.openscale.core.database.AppDatabase/7.json similarity index 93% rename from android_app/app/schemas/com.health.openscale.core.database.AppDatabase/1.json rename to android_app/app/schemas/com.health.openscale.core.database.AppDatabase/7.json index df4097a3..7251c03d 100644 --- a/android_app/app/schemas/com.health.openscale.core.database.AppDatabase/1.json +++ b/android_app/app/schemas/com.health.openscale.core.database.AppDatabase/7.json @@ -1,12 +1,12 @@ { "formatVersion": 1, "database": { - "version": 1, - "identityHash": "e9e1b3a9fbc321cf52bf869c01f5be21", + "version": 7, + "identityHash": "d539026586245a45a135ae5bf3aaf73c", "entities": [ { "tableName": "User", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `birthDate` INTEGER NOT NULL, `gender` TEXT NOT NULL, `heightCm` REAL, `activityLevel` TEXT NOT NULL)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `birthDate` INTEGER NOT NULL, `gender` TEXT NOT NULL, `heightCm` REAL NOT NULL, `activityLevel` TEXT NOT NULL, `scaleUnit` TEXT NOT NULL, `measureUnit` TEXT NOT NULL)", "fields": [ { "fieldPath": "id", @@ -35,13 +35,26 @@ { "fieldPath": "heightCm", "columnName": "heightCm", - "affinity": "REAL" + "affinity": "REAL", + "notNull": true }, { "fieldPath": "activityLevel", "columnName": "activityLevel", "affinity": "TEXT", "notNull": true + }, + { + "fieldPath": "scaleUnit", + "columnName": "scaleUnit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "measureUnit", + "columnName": "measureUnit", + "affinity": "TEXT", + "notNull": true } ], "primaryKey": { @@ -279,7 +292,7 @@ ], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e9e1b3a9fbc321cf52bf869c01f5be21')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd539026586245a45a135ae5bf3aaf73c')" ] } } \ No newline at end of file diff --git a/android_app/app/src/main/java/com/health/openscale/core/data/User.kt b/android_app/app/src/main/java/com/health/openscale/core/data/User.kt index 83cfa587..382f6adb 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/data/User.kt +++ b/android_app/app/src/main/java/com/health/openscale/core/data/User.kt @@ -26,6 +26,8 @@ data class User( val name: String, val birthDate: Long, val gender: GenderType, - val heightCm: Float? = null, - val activityLevel: ActivityLevel + val heightCm: Float, + val activityLevel: ActivityLevel, + var scaleUnit: WeightUnit, + var measureUnit: MeasureUnit ) \ No newline at end of file diff --git a/android_app/app/src/main/java/com/health/openscale/core/database/AppDatabase.kt b/android_app/app/src/main/java/com/health/openscale/core/database/AppDatabase.kt index ce3cee7b..c1f6d250 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/database/AppDatabase.kt +++ b/android_app/app/src/main/java/com/health/openscale/core/database/AppDatabase.kt @@ -39,7 +39,7 @@ import com.health.openscale.core.utils.LogManager MeasurementValue::class, MeasurementType::class ], - version = 1, + version = 7, exportSchema = true ) @TypeConverters(DatabaseConverters::class) diff --git a/android_app/app/src/main/java/com/health/openscale/ui/screen/settings/UserDetailScreen.kt b/android_app/app/src/main/java/com/health/openscale/ui/screen/settings/UserDetailScreen.kt index 4e084ca7..8cd3bb6e 100644 --- a/android_app/app/src/main/java/com/health/openscale/ui/screen/settings/UserDetailScreen.kt +++ b/android_app/app/src/main/java/com/health/openscale/ui/screen/settings/UserDetailScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.add import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -59,10 +60,13 @@ import androidx.navigation.NavController import com.health.openscale.R import com.health.openscale.core.data.ActivityLevel import com.health.openscale.core.data.GenderType +import com.health.openscale.core.data.MeasureUnit import com.health.openscale.core.data.User +import com.health.openscale.core.data.WeightUnit import com.health.openscale.ui.screen.SharedViewModel import kotlinx.coroutines.launch import java.text.SimpleDateFormat +import java.util.Calendar import java.util.Date import java.util.Locale @@ -94,17 +98,29 @@ fun UserDetailScreen( } var name by remember { mutableStateOf(user?.name.orEmpty()) } - var birthDate by remember { mutableStateOf(user?.birthDate ?: System.currentTimeMillis()) } + var birthDate by remember { + val initialBirthDate = user?.birthDate + if (initialBirthDate != null) { + mutableStateOf(initialBirthDate) + } else { + val calendar = Calendar.getInstance() + calendar.add(Calendar.YEAR, -18) + mutableStateOf(calendar.timeInMillis) + } + } var gender by remember { mutableStateOf(user?.gender ?: GenderType.MALE) } var height by remember { mutableStateOf(user?.heightCm?.toString().orEmpty()) } var activityLevel by remember { mutableStateOf(user?.activityLevel ?: ActivityLevel.SEDENTARY) } + var scaleUnit by remember { mutableStateOf(user?.scaleUnit ?: WeightUnit.KG) } + var measureUnit by remember { mutableStateOf(user?.measureUnit ?: MeasureUnit.CM) } val context = LocalContext.current - // Date formatter for displaying the birth date. Consider device locale. val dateFormatter = remember { SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()) } val datePickerState = rememberDatePickerState(initialSelectedDateMillis = birthDate) var showDatePicker by remember { mutableStateOf(false) } var activityLevelExpanded by remember { mutableStateOf(false) } + var scaleUnitExpanded by remember { mutableStateOf(false) } + var measureUnitExpanded by remember { mutableStateOf(false) } if (showDatePicker) { DatePickerDialog( @@ -149,7 +165,9 @@ fun UserDetailScreen( birthDate = birthDate, gender = gender, heightCm = validHeight, - activityLevel = activityLevel + activityLevel = activityLevel, + scaleUnit = scaleUnit, + measureUnit = measureUnit ) settingsViewModel.viewModelScope.launch { if (isEdit) { @@ -216,7 +234,6 @@ fun UserDetailScreen( } } - Text(stringResource(id = R.string.user_detail_label_activity_level)) // "Activity Level" ExposedDropdownMenuBox( expanded = activityLevelExpanded, onExpandedChange = { activityLevelExpanded = !activityLevelExpanded }, @@ -226,7 +243,7 @@ fun UserDetailScreen( value = activityLevel.name.lowercase().replaceFirstChar { it.uppercaseChar().toString() }, onValueChange = {}, // Input is read-only, selection via dropdown readOnly = true, - label = { Text(stringResource(id = R.string.user_detail_label_select_level)) }, // "Select Level" + label = { Text(stringResource(id = R.string.user_detail_label_activity_level)) }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = activityLevelExpanded) }, @@ -252,6 +269,74 @@ fun UserDetailScreen( } } + ExposedDropdownMenuBox( + expanded = scaleUnitExpanded, + onExpandedChange = { scaleUnitExpanded = !scaleUnitExpanded }, + modifier = Modifier.fillMaxWidth() + ) { + OutlinedTextField( + value = scaleUnit.toString(), + onValueChange = {}, + readOnly = true, + label = { Text(stringResource(id = R.string.user_detail_label_scale_unit)) }, + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon(expanded = scaleUnitExpanded) + }, + modifier = Modifier + .menuAnchor(type = MenuAnchorType.PrimaryNotEditable) + .fillMaxWidth() + ) + ExposedDropdownMenu( + expanded = scaleUnitExpanded, + onDismissRequest = { scaleUnitExpanded = false } + ) { + WeightUnit.entries.forEach { selectionOption -> + DropdownMenuItem( + text = { Text(selectionOption.toString()) }, + onClick = { + scaleUnit = selectionOption + scaleUnitExpanded = false + }, + contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, + ) + } + } + } + + ExposedDropdownMenuBox( + expanded = measureUnitExpanded, + onExpandedChange = { measureUnitExpanded = !measureUnitExpanded }, + modifier = Modifier.fillMaxWidth() + ) { + OutlinedTextField( + value = measureUnit.toString(), + onValueChange = {}, + readOnly = true, + label = { Text(stringResource(id = R.string.user_detail_label_measure_unit)) }, + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon(expanded = measureUnitExpanded) + }, + modifier = Modifier + .menuAnchor(type = MenuAnchorType.PrimaryNotEditable) + .fillMaxWidth() + ) + ExposedDropdownMenu( + expanded = measureUnitExpanded, + onDismissRequest = { measureUnitExpanded = false } + ) { + MeasureUnit.entries.forEach { selectionOption -> + DropdownMenuItem( + text = { Text(selectionOption.toString()) }, + onClick = { + measureUnit = selectionOption + measureUnitExpanded = false + }, + contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, + ) + } + } + } + Text(stringResource(id = R.string.user_detail_label_birth_date)) // "Birth Date" OutlinedTextField( value = dateFormatter.format(Date(birthDate)), diff --git a/android_app/app/src/main/res/values-de/strings.xml b/android_app/app/src/main/res/values-de/strings.xml index 40eaae12..55c549e9 100644 --- a/android_app/app/src/main/res/values-de/strings.xml +++ b/android_app/app/src/main/res/values-de/strings.xml @@ -51,9 +51,10 @@ Größe (cm) Geschlecht Aktivitätslevel - Level auswählen Geburtsdatum Bitte geben Sie gültige Daten ein + Gewichtseinheit + Größeneinheit %.1f cm Alter: %1$d, Größe: %2$s Benutzer bearbeiten diff --git a/android_app/app/src/main/res/values/strings.xml b/android_app/app/src/main/res/values/strings.xml index 43d36626..6d036b98 100644 --- a/android_app/app/src/main/res/values/strings.xml +++ b/android_app/app/src/main/res/values/strings.xml @@ -52,9 +52,10 @@ Height (cm) Gender Activity Level - Select Level Birth Date Please enter valid data + Scale Unit + Measure Unit %.1f cm Age: %1$d, Height: %2$s Edit user