1
0
mirror of https://github.com/oliexdev/openScale.git synced 2025-08-16 13:44:26 +02:00

Add scale and measure unit to user settings

This commit is contained in:
oliexdev
2025-08-12 08:17:59 +02:00
parent db78109132
commit b9203c8d5d
6 changed files with 117 additions and 15 deletions

View File

@@ -1,12 +1,12 @@
{ {
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 1, "version": 7,
"identityHash": "e9e1b3a9fbc321cf52bf869c01f5be21", "identityHash": "d539026586245a45a135ae5bf3aaf73c",
"entities": [ "entities": [
{ {
"tableName": "User", "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": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@@ -35,13 +35,26 @@
{ {
"fieldPath": "heightCm", "fieldPath": "heightCm",
"columnName": "heightCm", "columnName": "heightCm",
"affinity": "REAL" "affinity": "REAL",
"notNull": true
}, },
{ {
"fieldPath": "activityLevel", "fieldPath": "activityLevel",
"columnName": "activityLevel", "columnName": "activityLevel",
"affinity": "TEXT", "affinity": "TEXT",
"notNull": true "notNull": true
},
{
"fieldPath": "scaleUnit",
"columnName": "scaleUnit",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "measureUnit",
"columnName": "measureUnit",
"affinity": "TEXT",
"notNull": true
} }
], ],
"primaryKey": { "primaryKey": {
@@ -279,7 +292,7 @@
], ],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "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')"
] ]
} }
} }

View File

@@ -26,6 +26,8 @@ data class User(
val name: String, val name: String,
val birthDate: Long, val birthDate: Long,
val gender: GenderType, val gender: GenderType,
val heightCm: Float? = null, val heightCm: Float,
val activityLevel: ActivityLevel val activityLevel: ActivityLevel,
var scaleUnit: WeightUnit,
var measureUnit: MeasureUnit
) )

View File

@@ -39,7 +39,7 @@ import com.health.openscale.core.utils.LogManager
MeasurementValue::class, MeasurementValue::class,
MeasurementType::class MeasurementType::class
], ],
version = 1, version = 7,
exportSchema = true exportSchema = true
) )
@TypeConverters(DatabaseConverters::class) @TypeConverters(DatabaseConverters::class)

View File

@@ -22,6 +22,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.add
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
@@ -59,10 +60,13 @@ import androidx.navigation.NavController
import com.health.openscale.R import com.health.openscale.R
import com.health.openscale.core.data.ActivityLevel import com.health.openscale.core.data.ActivityLevel
import com.health.openscale.core.data.GenderType 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.User
import com.health.openscale.core.data.WeightUnit
import com.health.openscale.ui.screen.SharedViewModel import com.health.openscale.ui.screen.SharedViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@@ -94,17 +98,29 @@ fun UserDetailScreen(
} }
var name by remember { mutableStateOf(user?.name.orEmpty()) } 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 gender by remember { mutableStateOf(user?.gender ?: GenderType.MALE) }
var height by remember { mutableStateOf(user?.heightCm?.toString().orEmpty()) } var height by remember { mutableStateOf(user?.heightCm?.toString().orEmpty()) }
var activityLevel by remember { mutableStateOf(user?.activityLevel ?: ActivityLevel.SEDENTARY) } 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 val context = LocalContext.current
// Date formatter for displaying the birth date. Consider device locale.
val dateFormatter = remember { SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()) } val dateFormatter = remember { SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()) }
val datePickerState = rememberDatePickerState(initialSelectedDateMillis = birthDate) val datePickerState = rememberDatePickerState(initialSelectedDateMillis = birthDate)
var showDatePicker by remember { mutableStateOf(false) } var showDatePicker by remember { mutableStateOf(false) }
var activityLevelExpanded by remember { mutableStateOf(false) } var activityLevelExpanded by remember { mutableStateOf(false) }
var scaleUnitExpanded by remember { mutableStateOf(false) }
var measureUnitExpanded by remember { mutableStateOf(false) }
if (showDatePicker) { if (showDatePicker) {
DatePickerDialog( DatePickerDialog(
@@ -149,7 +165,9 @@ fun UserDetailScreen(
birthDate = birthDate, birthDate = birthDate,
gender = gender, gender = gender,
heightCm = validHeight, heightCm = validHeight,
activityLevel = activityLevel activityLevel = activityLevel,
scaleUnit = scaleUnit,
measureUnit = measureUnit
) )
settingsViewModel.viewModelScope.launch { settingsViewModel.viewModelScope.launch {
if (isEdit) { if (isEdit) {
@@ -216,7 +234,6 @@ fun UserDetailScreen(
} }
} }
Text(stringResource(id = R.string.user_detail_label_activity_level)) // "Activity Level"
ExposedDropdownMenuBox( ExposedDropdownMenuBox(
expanded = activityLevelExpanded, expanded = activityLevelExpanded,
onExpandedChange = { activityLevelExpanded = !activityLevelExpanded }, onExpandedChange = { activityLevelExpanded = !activityLevelExpanded },
@@ -226,7 +243,7 @@ fun UserDetailScreen(
value = activityLevel.name.lowercase().replaceFirstChar { it.uppercaseChar().toString() }, value = activityLevel.name.lowercase().replaceFirstChar { it.uppercaseChar().toString() },
onValueChange = {}, // Input is read-only, selection via dropdown onValueChange = {}, // Input is read-only, selection via dropdown
readOnly = true, 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 = { trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(expanded = activityLevelExpanded) 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" Text(stringResource(id = R.string.user_detail_label_birth_date)) // "Birth Date"
OutlinedTextField( OutlinedTextField(
value = dateFormatter.format(Date(birthDate)), value = dateFormatter.format(Date(birthDate)),

View File

@@ -51,9 +51,10 @@
<string name="user_detail_label_height_cm">Größe (cm)</string> <string name="user_detail_label_height_cm">Größe (cm)</string>
<string name="user_detail_label_gender">Geschlecht</string> <string name="user_detail_label_gender">Geschlecht</string>
<string name="user_detail_label_activity_level">Aktivitätslevel</string> <string name="user_detail_label_activity_level">Aktivitätslevel</string>
<string name="user_detail_label_select_level">Level auswählen</string>
<string name="user_detail_label_birth_date">Geburtsdatum</string> <string name="user_detail_label_birth_date">Geburtsdatum</string>
<string name="user_detail_error_invalid_data">Bitte geben Sie gültige Daten ein</string> <string name="user_detail_error_invalid_data">Bitte geben Sie gültige Daten ein</string>
<string name="user_detail_label_scale_unit">Gewichtseinheit</string>
<string name="user_detail_label_measure_unit">Größeneinheit</string>
<string name="height_value_cm">%.1f cm</string> <string name="height_value_cm">%.1f cm</string>
<string name="user_settings_item_details_conditional">Alter: %1$d, Größe: %2$s</string> <string name="user_settings_item_details_conditional">Alter: %1$d, Größe: %2$s</string>
<string name="user_settings_content_description_edit">Benutzer bearbeiten</string> <string name="user_settings_content_description_edit">Benutzer bearbeiten</string>

View File

@@ -52,9 +52,10 @@
<string name="user_detail_label_height_cm">Height (cm)</string> <string name="user_detail_label_height_cm">Height (cm)</string>
<string name="user_detail_label_gender">Gender</string> <string name="user_detail_label_gender">Gender</string>
<string name="user_detail_label_activity_level">Activity Level</string> <string name="user_detail_label_activity_level">Activity Level</string>
<string name="user_detail_label_select_level">Select Level</string>
<string name="user_detail_label_birth_date">Birth Date</string> <string name="user_detail_label_birth_date">Birth Date</string>
<string name="user_detail_error_invalid_data">Please enter valid data</string> <string name="user_detail_error_invalid_data">Please enter valid data</string>
<string name="user_detail_label_scale_unit">Scale Unit</string>
<string name="user_detail_label_measure_unit">Measure Unit</string>
<string name="height_value_cm">%.1f cm</string> <string name="height_value_cm">%.1f cm</string>
<string name="user_settings_item_details_conditional">Age: %1$d, Height: %2$s</string> <string name="user_settings_item_details_conditional">Age: %1$d, Height: %2$s</string>
<string name="user_settings_content_description_edit">Edit user</string> <string name="user_settings_content_description_edit">Edit user</string>