mirror of
https://github.com/oliexdev/openScale.git
synced 2025-09-03 05:12:42 +02:00
Add MeasurementType User and dialog to change user
This commit is contained in:
@@ -72,7 +72,8 @@ fun getDefaultMeasurementTypes(): List<MeasurementType> {
|
|||||||
MeasurementType(key = MeasurementTypeKey.CALORIES, unit = UnitType.KCAL, color = 0xFF4CAF50.toInt(), icon = MeasurementTypeIcon.IC_CALORIES, isEnabled = true),
|
MeasurementType(key = MeasurementTypeKey.CALORIES, unit = UnitType.KCAL, color = 0xFF4CAF50.toInt(), icon = MeasurementTypeIcon.IC_CALORIES, isEnabled = true),
|
||||||
MeasurementType(key = MeasurementTypeKey.COMMENT, inputType = InputFieldType.TEXT, unit = UnitType.NONE, color = 0xFFE0E0E0.toInt(), icon = MeasurementTypeIcon.IC_COMMENT, isPinned = true, isEnabled = true),
|
MeasurementType(key = MeasurementTypeKey.COMMENT, inputType = InputFieldType.TEXT, unit = UnitType.NONE, color = 0xFFE0E0E0.toInt(), icon = MeasurementTypeIcon.IC_COMMENT, isPinned = true, isEnabled = true),
|
||||||
MeasurementType(key = MeasurementTypeKey.DATE, inputType = InputFieldType.DATE, unit = UnitType.NONE, color = 0xFF9E9E9E.toInt(), icon = MeasurementTypeIcon.IC_DATE, isEnabled = true),
|
MeasurementType(key = MeasurementTypeKey.DATE, inputType = InputFieldType.DATE, unit = UnitType.NONE, color = 0xFF9E9E9E.toInt(), icon = MeasurementTypeIcon.IC_DATE, isEnabled = true),
|
||||||
MeasurementType(key = MeasurementTypeKey.TIME, inputType = InputFieldType.TIME, unit = UnitType.NONE, color = 0xFF757575.toInt(), icon = MeasurementTypeIcon.IC_TIME, isEnabled = true)
|
MeasurementType(key = MeasurementTypeKey.TIME, inputType = InputFieldType.TIME, unit = UnitType.NONE, color = 0xFF757575.toInt(), icon = MeasurementTypeIcon.IC_TIME, isEnabled = true),
|
||||||
|
MeasurementType(key = MeasurementTypeKey.USER, inputType = InputFieldType.USER, unit = UnitType.NONE, color = 0xFF90A4AE.toInt(), icon = MeasurementTypeIcon.IC_USER, isEnabled = true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -221,6 +221,7 @@ enum class MeasurementTypeIcon(val resource: IconResource) {
|
|||||||
IC_COMMENT(IconResource.PainterResource(R.drawable.ic_comment)),
|
IC_COMMENT(IconResource.PainterResource(R.drawable.ic_comment)),
|
||||||
IC_TIME(IconResource.PainterResource(R.drawable.ic_time)),
|
IC_TIME(IconResource.PainterResource(R.drawable.ic_time)),
|
||||||
IC_DATE(IconResource.PainterResource(R.drawable.ic_date)),
|
IC_DATE(IconResource.PainterResource(R.drawable.ic_date)),
|
||||||
|
IC_USER(IconResource.PainterResource(R.drawable.ic_user)),
|
||||||
|
|
||||||
IC_M_HEIGHT(IconResource.VectorResource(Icons.Filled.Height)),
|
IC_M_HEIGHT(IconResource.VectorResource(Icons.Filled.Height)),
|
||||||
IC_M_HEART_RATE(IconResource.VectorResource(Icons.Filled.Favorite)),
|
IC_M_HEART_RATE(IconResource.VectorResource(Icons.Filled.Favorite)),
|
||||||
@@ -301,6 +302,7 @@ enum class MeasurementTypeKey(
|
|||||||
DATE(24, R.string.measurement_type_date, listOf(UnitType.NONE), listOf(InputFieldType.DATE)),
|
DATE(24, R.string.measurement_type_date, listOf(UnitType.NONE), listOf(InputFieldType.DATE)),
|
||||||
TIME(25, R.string.measurement_type_time, listOf(UnitType.NONE), listOf(InputFieldType.TIME)),
|
TIME(25, R.string.measurement_type_time, listOf(UnitType.NONE), listOf(InputFieldType.TIME)),
|
||||||
COMMENT(26, R.string.measurement_type_comment, listOf(UnitType.NONE), listOf(InputFieldType.TEXT)),
|
COMMENT(26, R.string.measurement_type_comment, listOf(UnitType.NONE), listOf(InputFieldType.TEXT)),
|
||||||
|
USER(27, R.string.measurement_type_user, listOf(UnitType.NONE), listOf(InputFieldType.USER)),
|
||||||
CUSTOM(99, R.string.measurement_type_custom_default_name, UnitType.entries.toList(), listOf(InputFieldType.FLOAT, InputFieldType.INT, InputFieldType.TEXT, InputFieldType.DATE, InputFieldType.TIME));
|
CUSTOM(99, R.string.measurement_type_custom_default_name, UnitType.entries.toList(), listOf(InputFieldType.FLOAT, InputFieldType.INT, InputFieldType.TEXT, InputFieldType.DATE, InputFieldType.TIME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +327,8 @@ enum class InputFieldType {
|
|||||||
INT,
|
INT,
|
||||||
TEXT,
|
TEXT,
|
||||||
DATE,
|
DATE,
|
||||||
TIME
|
TIME,
|
||||||
|
USER
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Trend {
|
enum class Trend {
|
||||||
|
@@ -96,7 +96,9 @@ class ImportExportUseCases @Inject constructor(
|
|||||||
|
|
||||||
val allAppTypes: List<MeasurementType> = repository.getAllMeasurementTypes().first()
|
val allAppTypes: List<MeasurementType> = repository.getAllMeasurementTypes().first()
|
||||||
val exportableValueTypes = allAppTypes.filter {
|
val exportableValueTypes = allAppTypes.filter {
|
||||||
it.key != MeasurementTypeKey.DATE && it.key != MeasurementTypeKey.TIME
|
it.key != MeasurementTypeKey.DATE &&
|
||||||
|
it.key != MeasurementTypeKey.TIME &&
|
||||||
|
it.key != MeasurementTypeKey.USER
|
||||||
}
|
}
|
||||||
val valueColumnKeys = exportableValueTypes.map { it.key.name }.distinct()
|
val valueColumnKeys = exportableValueTypes.map { it.key.name }.distinct()
|
||||||
|
|
||||||
@@ -141,6 +143,7 @@ class ImportExportUseCases @Inject constructor(
|
|||||||
InputFieldType.TIME -> value.dateValue?.let {
|
InputFieldType.TIME -> value.dateValue?.let {
|
||||||
timeFormatter.format(Instant.ofEpochMilli(it).atZone(ZoneId.systemDefault()))
|
timeFormatter.format(Instant.ofEpochMilli(it).atZone(ZoneId.systemDefault()))
|
||||||
}
|
}
|
||||||
|
InputFieldType.USER -> null
|
||||||
}
|
}
|
||||||
row[type.key.name] = s
|
row[type.key.name] = s
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* openScale
|
||||||
|
* Copyright (C) 2025 olie.xdev <olie.xdeveloper@googlemail.com>
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.health.openscale.ui.screen.dialog
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.RadioButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.health.openscale.R
|
||||||
|
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||||
|
import com.health.openscale.core.data.User
|
||||||
|
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UserInputDialog(
|
||||||
|
title: String,
|
||||||
|
users: List<User>,
|
||||||
|
initialSelectedId: Int?,
|
||||||
|
measurementIcon: MeasurementTypeIcon,
|
||||||
|
iconBackgroundColor: Color,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onConfirm: (Int?) -> Unit
|
||||||
|
) {
|
||||||
|
var selectedId by remember(users, initialSelectedId) { mutableStateOf(initialSelectedId) }
|
||||||
|
|
||||||
|
val usersSorted = remember(users) {
|
||||||
|
users.sortedBy { it.name.lowercase(Locale.getDefault()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = { onConfirm(selectedId) }) {
|
||||||
|
Text(stringResource(R.string.dialog_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismiss) {
|
||||||
|
Text(stringResource(R.string.cancel_button))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
RoundMeasurementIcon(
|
||||||
|
icon = measurementIcon,
|
||||||
|
backgroundTint = iconBackgroundColor
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(12.dp))
|
||||||
|
Text(text = title, style = MaterialTheme.typography.titleMedium)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Box(Modifier.heightIn(max = 360.dp)) {
|
||||||
|
LazyColumn {
|
||||||
|
items(usersSorted, key = { it.id }) { user ->
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { selectedId = user.id }
|
||||||
|
.padding(vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
RadioButton(
|
||||||
|
selected = (selectedId == user.id),
|
||||||
|
onClick = { selectedId = user.id }
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(12.dp))
|
||||||
|
Text(
|
||||||
|
text = user.name,
|
||||||
|
style = MaterialTheme.typography.bodyLarge
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@@ -74,6 +74,7 @@ import com.health.openscale.ui.screen.dialog.DateInputDialog
|
|||||||
import com.health.openscale.ui.screen.dialog.NumberInputDialog
|
import com.health.openscale.ui.screen.dialog.NumberInputDialog
|
||||||
import com.health.openscale.ui.screen.dialog.TextInputDialog
|
import com.health.openscale.ui.screen.dialog.TextInputDialog
|
||||||
import com.health.openscale.ui.screen.dialog.TimeInputDialog
|
import com.health.openscale.ui.screen.dialog.TimeInputDialog
|
||||||
|
import com.health.openscale.ui.screen.dialog.UserInputDialog
|
||||||
import com.health.openscale.ui.screen.dialog.decrementValue
|
import com.health.openscale.ui.screen.dialog.decrementValue
|
||||||
import com.health.openscale.ui.screen.dialog.incrementValue
|
import com.health.openscale.ui.screen.dialog.incrementValue
|
||||||
import com.health.openscale.ui.shared.TopBarAction
|
import com.health.openscale.ui.shared.TopBarAction
|
||||||
@@ -122,6 +123,10 @@ fun MeasurementDetailScreen(
|
|||||||
val dateFormat = remember { DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.getDefault()) }
|
val dateFormat = remember { DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.getDefault()) }
|
||||||
val timeFormat = remember { DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()) }
|
val timeFormat = remember { DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()) }
|
||||||
|
|
||||||
|
val allUsers by sharedViewModel.allUsers.collectAsState()
|
||||||
|
var pendingUserId by remember { mutableStateOf<Int?>(null) }
|
||||||
|
var showUserPicker by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
// Show a loading indicator if navigation is pending (e.g., after saving).
|
// Show a loading indicator if navigation is pending (e.g., after saving).
|
||||||
if (isPendingNavigation) {
|
if (isPendingNavigation) {
|
||||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
@@ -146,6 +151,7 @@ fun MeasurementDetailScreen(
|
|||||||
currentMeasurementDbId = data.measurement.id
|
currentMeasurementDbId = data.measurement.id
|
||||||
currentUserIdState = data.measurement.userId // Use UserID from the loaded measurement
|
currentUserIdState = data.measurement.userId // Use UserID from the loaded measurement
|
||||||
measurementTimestampState = data.measurement.timestamp
|
measurementTimestampState = data.measurement.timestamp
|
||||||
|
pendingUserId = null
|
||||||
valuesState.clear()
|
valuesState.clear()
|
||||||
data.values.forEach { mvWithType ->
|
data.values.forEach { mvWithType ->
|
||||||
// Populate valuesState for non-date/time, enabled types.
|
// Populate valuesState for non-date/time, enabled types.
|
||||||
@@ -166,6 +172,7 @@ fun MeasurementDetailScreen(
|
|||||||
currentMeasurementDbId = 0
|
currentMeasurementDbId = 0
|
||||||
currentUserIdState = userId // Use the passed userId for a new measurement
|
currentUserIdState = userId // Use the passed userId for a new measurement
|
||||||
measurementTimestampState = System.currentTimeMillis() // Always use current timestamp for new
|
measurementTimestampState = System.currentTimeMillis() // Always use current timestamp for new
|
||||||
|
pendingUserId = null
|
||||||
valuesState.clear()
|
valuesState.clear()
|
||||||
|
|
||||||
// Preload values from the user's last measurement, if available and types are loaded.
|
// Preload values from the user's last measurement, if available and types are loaded.
|
||||||
@@ -206,29 +213,25 @@ fun MeasurementDetailScreen(
|
|||||||
icon = Icons.Default.Save,
|
icon = Icons.Default.Save,
|
||||||
contentDescription = context.getString(R.string.action_save_measurement),
|
contentDescription = context.getString(R.string.action_save_measurement),
|
||||||
onClick = {
|
onClick = {
|
||||||
if (currentUserIdState == -1) { // Ensure a user is selected.
|
val effectiveUserIdForSave = pendingUserId ?: currentUserIdState
|
||||||
Toast.makeText(context, R.string.toast_no_user_selected, Toast.LENGTH_SHORT)
|
|
||||||
.show()
|
if (effectiveUserIdForSave == -1) {
|
||||||
|
Toast.makeText(context, R.string.toast_no_user_selected, Toast.LENGTH_SHORT).show()
|
||||||
return@TopBarAction
|
return@TopBarAction
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent saving if it's a new measurement with the exact same timestamp as the user's last one.
|
|
||||||
if (currentMeasurementDbId == 0 &&
|
if (currentMeasurementDbId == 0 &&
|
||||||
lastMeasurementToPreloadFrom != null &&
|
lastMeasurementToPreloadFrom != null &&
|
||||||
lastMeasurementToPreloadFrom!!.measurement.userId == currentUserIdState &&
|
lastMeasurementToPreloadFrom!!.measurement.userId == effectiveUserIdForSave &&
|
||||||
measurementTimestampState == lastMeasurementToPreloadFrom!!.measurement.timestamp
|
measurementTimestampState == lastMeasurementToPreloadFrom!!.measurement.timestamp
|
||||||
) {
|
) {
|
||||||
Toast.makeText(
|
Toast.makeText(context, R.string.toast_duplicate_timestamp, Toast.LENGTH_LONG).show()
|
||||||
context,
|
|
||||||
R.string.toast_duplicate_timestamp,
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
).show()
|
|
||||||
return@TopBarAction
|
return@TopBarAction
|
||||||
}
|
}
|
||||||
|
|
||||||
val measurementToSave = Measurement(
|
val measurementToSave = Measurement(
|
||||||
id = currentMeasurementDbId,
|
id = currentMeasurementDbId,
|
||||||
userId = currentUserIdState,
|
userId = effectiveUserIdForSave,
|
||||||
timestamp = measurementTimestampState
|
timestamp = measurementTimestampState
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -310,6 +313,7 @@ fun MeasurementDetailScreen(
|
|||||||
|
|
||||||
if (allConversionsOk) {
|
if (allConversionsOk) {
|
||||||
sharedViewModel.saveMeasurement(measurementToSave, valueList)
|
sharedViewModel.saveMeasurement(measurementToSave, valueList)
|
||||||
|
pendingUserId = null
|
||||||
isPendingNavigation = true // Trigger loading indicator and navigate back.
|
isPendingNavigation = true // Trigger loading indicator and navigate back.
|
||||||
navController.popBackStack()
|
navController.popBackStack()
|
||||||
}
|
}
|
||||||
@@ -346,6 +350,16 @@ fun MeasurementDetailScreen(
|
|||||||
displayValue = timeFormat.format(Date(measurementTimestampState))
|
displayValue = timeFormat.format(Date(measurementTimestampState))
|
||||||
currentValueForIncrementDecrement = null // Not applicable
|
currentValueForIncrementDecrement = null // Not applicable
|
||||||
}
|
}
|
||||||
|
InputFieldType.USER -> {
|
||||||
|
val effectiveUserId = pendingUserId ?: currentUserIdState
|
||||||
|
val selectedUserName = allUsers
|
||||||
|
.firstOrNull { it.id == effectiveUserId }
|
||||||
|
?.name
|
||||||
|
?: stringResource(R.string.placeholder_empty_value)
|
||||||
|
|
||||||
|
displayValue = selectedUserName
|
||||||
|
currentValueForIncrementDecrement = null
|
||||||
|
}
|
||||||
else -> { // For FLOAT, INT, TEXT
|
else -> { // For FLOAT, INT, TEXT
|
||||||
displayValue = valuesState[type.id] ?: ""
|
displayValue = valuesState[type.id] ?: ""
|
||||||
currentValueForIncrementDecrement = valuesState[type.id]
|
currentValueForIncrementDecrement = valuesState[type.id]
|
||||||
@@ -362,6 +376,7 @@ fun MeasurementDetailScreen(
|
|||||||
when (type.inputType) {
|
when (type.inputType) {
|
||||||
InputFieldType.DATE -> showDatePickerForMainTimestamp = true
|
InputFieldType.DATE -> showDatePickerForMainTimestamp = true
|
||||||
InputFieldType.TIME -> showTimePickerForMainTimestamp = true
|
InputFieldType.TIME -> showTimePickerForMainTimestamp = true
|
||||||
|
InputFieldType.USER -> showUserPicker = true
|
||||||
else -> dialogTargetType = type // Show generic dialog
|
else -> dialogTargetType = type // Show generic dialog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -464,7 +479,7 @@ fun MeasurementDetailScreen(
|
|||||||
// --- Dialogs for the main measurement timestamp (measurementTimestampState) ---
|
// --- Dialogs for the main measurement timestamp (measurementTimestampState) ---
|
||||||
if (showDatePickerForMainTimestamp) {
|
if (showDatePickerForMainTimestamp) {
|
||||||
val triggeringType = allMeasurementTypes.find { it.key == MeasurementTypeKey.DATE }
|
val triggeringType = allMeasurementTypes.find { it.key == MeasurementTypeKey.DATE }
|
||||||
val dateDialogTitle = stringResource(R.string.dialog_title_change_date, triggeringType?.getDisplayName(context) ?: stringResource(R.string.label_date))
|
val dateDialogTitle = stringResource(R.string.dialog_title_change_value, triggeringType?.getDisplayName(context) ?: stringResource(R.string.label_date))
|
||||||
DateInputDialog(
|
DateInputDialog(
|
||||||
title = dateDialogTitle,
|
title = dateDialogTitle,
|
||||||
initialTimestamp = measurementTimestampState,
|
initialTimestamp = measurementTimestampState,
|
||||||
@@ -483,7 +498,7 @@ fun MeasurementDetailScreen(
|
|||||||
|
|
||||||
if (showTimePickerForMainTimestamp) {
|
if (showTimePickerForMainTimestamp) {
|
||||||
val triggeringType = allMeasurementTypes.find { it.key == MeasurementTypeKey.TIME }
|
val triggeringType = allMeasurementTypes.find { it.key == MeasurementTypeKey.TIME }
|
||||||
val timeDialogTitle = stringResource(R.string.dialog_title_change_time, triggeringType?.getDisplayName(context) ?: stringResource(R.string.label_time))
|
val timeDialogTitle = stringResource(R.string.dialog_title_change_value, triggeringType?.getDisplayName(context) ?: stringResource(R.string.label_time))
|
||||||
TimeInputDialog(
|
TimeInputDialog(
|
||||||
title = timeDialogTitle,
|
title = timeDialogTitle,
|
||||||
initialTimestamp = measurementTimestampState,
|
initialTimestamp = measurementTimestampState,
|
||||||
@@ -500,6 +515,24 @@ fun MeasurementDetailScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showUserPicker) {
|
||||||
|
val triggeringType = allMeasurementTypes.find { it.key == MeasurementTypeKey.USER }
|
||||||
|
val userDialogTitle = stringResource(R.string.dialog_title_change_value, triggeringType?.getDisplayName(context) ?: stringResource(R.string.measurement_type_user))
|
||||||
|
|
||||||
|
UserInputDialog(
|
||||||
|
title = userDialogTitle,
|
||||||
|
users = allUsers,
|
||||||
|
initialSelectedId = pendingUserId ?: currentUserIdState,
|
||||||
|
measurementIcon = triggeringType?.icon ?: MeasurementTypeIcon.IC_USER,
|
||||||
|
iconBackgroundColor = triggeringType?.let { Color(it.color) } ?: MaterialTheme.colorScheme.primary,
|
||||||
|
onDismiss = { showUserPicker = false },
|
||||||
|
onConfirm = { id ->
|
||||||
|
pendingUserId = id
|
||||||
|
showUserPicker = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -930,6 +930,7 @@ fun MeasurementValueRow(
|
|||||||
InputFieldType.TIME -> originalValue.dateValue?.let {
|
InputFieldType.TIME -> originalValue.dateValue?.let {
|
||||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(Date(it))
|
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(Date(it))
|
||||||
}
|
}
|
||||||
|
InputFieldType.USER -> null
|
||||||
} ?: "-"
|
} ?: "-"
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
@@ -523,8 +523,10 @@ fun MeasurementTypeDetailScreen(
|
|||||||
OutlinedSettingRow(label = stringResource(R.string.measurement_type_label_pinned)) {
|
OutlinedSettingRow(label = stringResource(R.string.measurement_type_label_pinned)) {
|
||||||
Switch(checked = isPinned, onCheckedChange = { isPinned = it })
|
Switch(checked = isPinned, onCheckedChange = { isPinned = it })
|
||||||
}
|
}
|
||||||
OutlinedSettingRow(label = stringResource(R.string.measurement_type_label_on_right_y_axis)) {
|
if (selectedInputType == InputFieldType.FLOAT || selectedInputType == InputFieldType.INT) {
|
||||||
Switch(checked = isOnRightYAxis, onCheckedChange = { isOnRightYAxis = it })
|
OutlinedSettingRow(label = stringResource(R.string.measurement_type_label_on_right_y_axis)) {
|
||||||
|
Switch(checked = isOnRightYAxis, onCheckedChange = { isOnRightYAxis = it })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
android_app/app/src/main/res/drawable/ic_user.xml
Normal file
18
android_app/app/src/main/res/drawable/ic_user.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32dp"
|
||||||
|
android:height="32dp"
|
||||||
|
android:viewportWidth="350"
|
||||||
|
android:viewportHeight="350">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M175,171.173c38.914,0 70.463,-38.318 70.463,-85.586C245.463,38.318 235.105,0 175,0s-70.465,38.318 -70.465,85.587C104.535,132.855 136.084,171.173 175,171.173z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M41.909,301.853C41.897,298.971 41.885,301.041 41.909,301.853L41.909,301.853z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M308.085,304.104C308.123,303.315 308.098,298.63 308.085,304.104L308.085,304.104z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M307.935,298.397c-1.305,-82.342 -12.059,-105.805 -94.352,-120.657c0,0 -11.584,14.761 -38.584,14.761s-38.586,-14.761 -38.586,-14.761c-81.395,14.69 -92.803,37.805 -94.303,117.982c-0.123,6.547 -0.18,6.891 -0.202,6.131c0.005,1.424 0.011,4.058 0.011,8.651c0,0 19.592,39.496 133.08,39.496c113.486,0 133.08,-39.496 133.08,-39.496c0,-2.951 0.002,-5.003 0.005,-6.399C308.062,304.575 308.018,303.664 307.935,298.397z"/>
|
||||||
|
</vector>
|
@@ -102,8 +102,7 @@
|
|||||||
|
|
||||||
<!-- Dialoge (Allgemein & Messwertbearbeitung) -->
|
<!-- Dialoge (Allgemein & Messwertbearbeitung) -->
|
||||||
<string name="dialog_title_edit_value">%1$s bearbeiten</string> <!-- Beispiel: "Gewicht bearbeiten" -->
|
<string name="dialog_title_edit_value">%1$s bearbeiten</string> <!-- Beispiel: "Gewicht bearbeiten" -->
|
||||||
<string name="dialog_title_change_date">%1$s ändern</string> <!-- Beispiel: "Datum ändern" oder "Messdatum ändern" -->
|
<string name="dialog_title_change_value">%1$s ändern</string> <!-- Beispiel: "Datum ändern" oder "Messdatum ändern" -->
|
||||||
<string name="dialog_title_change_time">%1$s ändern</string> <!-- Beispiel: "Zeit ändern" oder "Messzeit ändern" -->
|
|
||||||
<string name="dialog_title_select_color">Farbe auswählen</string>
|
<string name="dialog_title_select_color">Farbe auswählen</string>
|
||||||
<string name="dialog_title_select_icon">Symbol auswählen</string>
|
<string name="dialog_title_select_icon">Symbol auswählen</string>
|
||||||
<string name="dialog_title_input_value">Wert eingeben</string>
|
<string name="dialog_title_input_value">Wert eingeben</string>
|
||||||
@@ -153,6 +152,7 @@
|
|||||||
<string name="measurement_type_comment">Kommentar</string>
|
<string name="measurement_type_comment">Kommentar</string>
|
||||||
<string name="measurement_type_date">Datum</string>
|
<string name="measurement_type_date">Datum</string>
|
||||||
<string name="measurement_type_time">Uhrzeit</string>
|
<string name="measurement_type_time">Uhrzeit</string>
|
||||||
|
<string name="measurement_type_user">Benutzer</string>
|
||||||
<string name="measurement_type_custom_default_name">Benutzerdefinierter Typ</string>
|
<string name="measurement_type_custom_default_name">Benutzerdefinierter Typ</string>
|
||||||
|
|
||||||
<!-- Einstellungen für Messarten -->
|
<!-- Einstellungen für Messarten -->
|
||||||
|
@@ -102,9 +102,8 @@
|
|||||||
<string name="toast_enter_valid_data">Please enter valid data.</string>
|
<string name="toast_enter_valid_data">Please enter valid data.</string>
|
||||||
|
|
||||||
<!-- Dialogs (General & Measurement Edit) -->
|
<!-- Dialogs (General & Measurement Edit) -->
|
||||||
<string name="dialog_title_edit_value">Edit %1$s</string> <!-- Example: "Edit Weight" -->
|
<string name="dialog_title_edit_value">Edit %1$s</string>
|
||||||
<string name="dialog_title_change_date">Change %1$s</string> <!-- Example: "Change Date" or "Change Measurement Date" -->
|
<string name="dialog_title_change_value">Change %1$s</string>
|
||||||
<string name="dialog_title_change_time">Change %1$s</string> <!-- Example: "Change Time" or "Change Measurement Time" -->
|
|
||||||
<string name="dialog_title_select_color">Select color</string>
|
<string name="dialog_title_select_color">Select color</string>
|
||||||
<string name="dialog_title_select_icon">Select icon</string>
|
<string name="dialog_title_select_icon">Select icon</string>
|
||||||
<string name="dialog_title_input_value">Input value</string>
|
<string name="dialog_title_input_value">Input value</string>
|
||||||
@@ -155,6 +154,7 @@
|
|||||||
<string name="measurement_type_comment">Comment</string>
|
<string name="measurement_type_comment">Comment</string>
|
||||||
<string name="measurement_type_date">Date</string>
|
<string name="measurement_type_date">Date</string>
|
||||||
<string name="measurement_type_time">Time</string>
|
<string name="measurement_type_time">Time</string>
|
||||||
|
<string name="measurement_type_user">User</string>
|
||||||
<string name="measurement_type_custom_default_name">Custom Type</string>
|
<string name="measurement_type_custom_default_name">Custom Type</string>
|
||||||
|
|
||||||
<!-- Measurement Type Settings -->
|
<!-- Measurement Type Settings -->
|
||||||
|
Reference in New Issue
Block a user