mirror of
https://github.com/oliexdev/openScale.git
synced 2025-09-08 23:50:40 +02:00
Replace String-based icons with enum and introduce MeasurementIcon composable
This commit is contained in:
@@ -31,6 +31,7 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.health.openscale.core.data.InputFieldType
|
||||
import com.health.openscale.core.data.MeasurementType
|
||||
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||
import com.health.openscale.core.data.MeasurementTypeKey
|
||||
import com.health.openscale.core.data.SupportedLanguage
|
||||
import com.health.openscale.core.data.UnitType
|
||||
@@ -58,34 +59,34 @@ import kotlinx.coroutines.launch
|
||||
* @return A list of [MeasurementType] objects.
|
||||
*/
|
||||
fun getDefaultMeasurementTypes(): List<MeasurementType> {
|
||||
return listOf(
|
||||
MeasurementType(key = MeasurementTypeKey.WEIGHT, unit = UnitType.KG, color = 0xFF7E57C2.toInt(), icon = "ic_weight", isPinned = true, isEnabled = true, isOnRightYAxis = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BMI, unit = UnitType.NONE, color = 0xFFFFCA28.toInt(), icon = "ic_bmi", isDerived = true, isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BODY_FAT, unit = UnitType.PERCENT, color = 0xFFEF5350.toInt(), icon = "ic_fat", isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.WATER, unit = UnitType.PERCENT, color = 0xFF29B6F6.toInt(), icon = "ic_water", isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.MUSCLE, unit = UnitType.PERCENT, color = 0xFF66BB6A.toInt(), icon = "ic_muscle", isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.LBM, unit = UnitType.KG, color = 0xFF4DBAC0.toInt(), icon = "ic_lbm", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BONE, unit = UnitType.KG, color = 0xFFBDBDBD.toInt(), icon = "ic_bone", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.WAIST, unit = UnitType.CM, color = 0xFF78909C.toInt(), icon = "ic_waist", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.WHR, unit = UnitType.NONE, color = 0xFFFFA726.toInt(), icon = "ic_whr", isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.WHTR, unit = UnitType.NONE, color = 0xFFFF7043.toInt(), icon = "ic_whtr", isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.HIPS, unit = UnitType.CM, color = 0xFF5C6BC0.toInt(), icon = "ic_hip", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.VISCERAL_FAT, unit = UnitType.NONE, color = 0xFFD84315.toInt(), icon = "ic_visceral_fat", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CHEST, unit = UnitType.CM, color = 0xFF8E24AA.toInt(), icon = "ic_chest", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.THIGH, unit = UnitType.CM, color = 0xFFA1887F.toInt(), icon = "ic_thigh", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BICEPS, unit = UnitType.CM, color = 0xFFEC407A.toInt(), icon = "ic_biceps", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.NECK, unit = UnitType.CM, color = 0xFFB0BEC5.toInt(), icon = "ic_neck", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALIPER_1, unit = UnitType.CM, color = 0xFFFFF59D.toInt(), icon = "ic_caliper1", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALIPER_2, unit = UnitType.CM, color = 0xFFFFE082.toInt(), icon = "ic_caliper2", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALIPER_3, unit = UnitType.CM, color = 0xFFFFCC80.toInt(), icon = "ic_caliper3", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALIPER, unit = UnitType.PERCENT, color = 0xFFFB8C00.toInt(), icon = "ic_fat_caliper", isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BMR, unit = UnitType.KCAL, color = 0xFFAB47BC.toInt(), icon = "ic_bmr", isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.TDEE, unit = UnitType.KCAL, color = 0xFF26A69A.toInt(), icon = "ic_tdee", isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALORIES, unit = UnitType.KCAL, color = 0xFF4CAF50.toInt(), icon = "ic_calories", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.COMMENT, inputType = InputFieldType.TEXT, unit = UnitType.NONE, color = 0xFFE0E0E0.toInt(), icon = "ic_comment", isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.DATE, inputType = InputFieldType.DATE, unit = UnitType.NONE, color = 0xFF9E9E9E.toInt(), icon = "ic_date", isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.TIME, inputType = InputFieldType.TIME, unit = UnitType.NONE, color = 0xFF757575.toInt(), icon = "ic_time", isEnabled = true)
|
||||
)
|
||||
return listOf(
|
||||
MeasurementType(key = MeasurementTypeKey.WEIGHT, unit = UnitType.KG, color = 0xFF7E57C2.toInt(), icon = MeasurementTypeIcon.IC_WEIGHT, isPinned = true, isEnabled = true, isOnRightYAxis = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BMI, unit = UnitType.NONE, color = 0xFFFFCA28.toInt(), icon = MeasurementTypeIcon.IC_BMI, isDerived = true, isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BODY_FAT, unit = UnitType.PERCENT, color = 0xFFEF5350.toInt(), icon = MeasurementTypeIcon.IC_BODY_FAT, isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.WATER, unit = UnitType.PERCENT, color = 0xFF29B6F6.toInt(), icon = MeasurementTypeIcon.IC_WATER, isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.MUSCLE, unit = UnitType.PERCENT, color = 0xFF66BB6A.toInt(), icon = MeasurementTypeIcon.IC_MUSCLE, isPinned = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.LBM, unit = UnitType.KG, color = 0xFF4DBAC0.toInt(), icon = MeasurementTypeIcon.IC_LBM, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BONE, unit = UnitType.KG, color = 0xFFBDBDBD.toInt(), icon = MeasurementTypeIcon.IC_BONE, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.WAIST, unit = UnitType.CM, color = 0xFF78909C.toInt(), icon = MeasurementTypeIcon.IC_WAIST, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.WHR, unit = UnitType.NONE, color = 0xFFFFA726.toInt(), icon = MeasurementTypeIcon.IC_WHR, isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.WHTR, unit = UnitType.NONE, color = 0xFFFF7043.toInt(), icon = MeasurementTypeIcon.IC_WHTR, isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.HIPS, unit = UnitType.CM, color = 0xFF5C6BC0.toInt(), icon = MeasurementTypeIcon.IC_HIPS, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.VISCERAL_FAT, unit = UnitType.NONE, color = 0xFFD84315.toInt(), icon = MeasurementTypeIcon.IC_VISCERAL_FAT, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CHEST, unit = UnitType.CM, color = 0xFF8E24AA.toInt(), icon = MeasurementTypeIcon.IC_CHEST, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.THIGH, unit = UnitType.CM, color = 0xFFA1887F.toInt(), icon = MeasurementTypeIcon.IC_THIGH, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BICEPS, unit = UnitType.CM, color = 0xFFEC407A.toInt(), icon = MeasurementTypeIcon.IC_BICEPS, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.NECK, unit = UnitType.CM, color = 0xFFB0BEC5.toInt(), icon = MeasurementTypeIcon.IC_NECK, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALIPER_1, unit = UnitType.CM, color = 0xFFFFF59D.toInt(), icon = MeasurementTypeIcon.IC_CALIPER1, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALIPER_2, unit = UnitType.CM, color = 0xFFFFE082.toInt(), icon = MeasurementTypeIcon.IC_CALIPER2, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALIPER_3, unit = UnitType.CM, color = 0xFFFFCC80.toInt(), icon = MeasurementTypeIcon.IC_CALIPER3, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.CALIPER, unit = UnitType.PERCENT, color = 0xFFFB8C00.toInt(), icon = MeasurementTypeIcon.IC_FAT_CALIPER, isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.BMR, unit = UnitType.KCAL, color = 0xFFAB47BC.toInt(), icon = MeasurementTypeIcon.IC_BMR, isDerived = true, isEnabled = true),
|
||||
MeasurementType(key = MeasurementTypeKey.TDEE, unit = UnitType.KCAL, color = 0xFF26A69A.toInt(), icon = MeasurementTypeIcon.IC_TDEE, isDerived = true, 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.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)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -18,7 +18,52 @@
|
||||
package com.health.openscale.core.data
|
||||
|
||||
import android.text.InputType
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.DirectionsWalk
|
||||
import androidx.compose.material.icons.automirrored.filled.HelpOutline
|
||||
import androidx.compose.material.icons.automirrored.filled.Label
|
||||
import androidx.compose.material.icons.automirrored.filled.List
|
||||
import androidx.compose.material.icons.automirrored.filled.ShowChart
|
||||
import androidx.compose.material.icons.automirrored.filled.TrendingDown
|
||||
import androidx.compose.material.icons.automirrored.filled.TrendingFlat
|
||||
import androidx.compose.material.icons.automirrored.filled.TrendingUp
|
||||
import androidx.compose.material.icons.filled.AddCircleOutline
|
||||
import androidx.compose.material.icons.filled.Analytics
|
||||
import androidx.compose.material.icons.filled.Bloodtype
|
||||
import androidx.compose.material.icons.filled.CalendarMonth
|
||||
import androidx.compose.material.icons.filled.CheckCircleOutline
|
||||
import androidx.compose.material.icons.filled.DeviceThermostat
|
||||
import androidx.compose.material.icons.filled.DirectionsWalk
|
||||
import androidx.compose.material.icons.filled.Done
|
||||
import androidx.compose.material.icons.filled.EditNote
|
||||
import androidx.compose.material.icons.filled.Egg
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material.icons.filled.FitnessCenter
|
||||
import androidx.compose.material.icons.filled.Flag
|
||||
import androidx.compose.material.icons.filled.Grain
|
||||
import androidx.compose.material.icons.filled.Height
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material.icons.filled.LocalDining
|
||||
import androidx.compose.material.icons.filled.LocalDrink
|
||||
import androidx.compose.material.icons.filled.Medication
|
||||
import androidx.compose.material.icons.filled.NightsStay
|
||||
import androidx.compose.material.icons.filled.OilBarrel
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.PieChart
|
||||
import androidx.compose.material.icons.filled.RadioButtonUnchecked
|
||||
import androidx.compose.material.icons.filled.RemoveCircleOutline
|
||||
import androidx.compose.material.icons.filled.Schedule
|
||||
import androidx.compose.material.icons.filled.SentimentSatisfiedAlt
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material.icons.filled.ShowChart
|
||||
import androidx.compose.material.icons.filled.Speed
|
||||
import androidx.compose.material.icons.filled.SquareFoot
|
||||
import androidx.compose.material.icons.filled.StackedLineChart
|
||||
import androidx.compose.material.icons.filled.Timer
|
||||
import androidx.compose.material.icons.filled.WarningAmber
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import com.health.openscale.R
|
||||
import java.util.Locale
|
||||
|
||||
@@ -145,6 +190,82 @@ enum class MeasureUnit {
|
||||
}
|
||||
}
|
||||
|
||||
enum class MeasurementTypeIcon(val resource: IconResource) {
|
||||
IC_DEFAULT(IconResource.VectorResource(Icons.Filled.RadioButtonUnchecked)),
|
||||
IC_WEIGHT(IconResource.PainterResource(R.drawable.ic_weight)),
|
||||
IC_BMI(IconResource.PainterResource(R.drawable.ic_bmi)),
|
||||
IC_BODY_FAT(IconResource.PainterResource(R.drawable.ic_fat)),
|
||||
IC_WATER(IconResource.PainterResource(R.drawable.ic_water)),
|
||||
IC_MUSCLE(IconResource.PainterResource(R.drawable.ic_muscle)),
|
||||
IC_LBM(IconResource.PainterResource(R.drawable.ic_lbm)),
|
||||
IC_BONE(IconResource.PainterResource(R.drawable.ic_bone)),
|
||||
IC_WAIST(IconResource.PainterResource(R.drawable.ic_waist)),
|
||||
IC_WHR(IconResource.PainterResource(R.drawable.ic_whr)),
|
||||
IC_WHTR(IconResource.PainterResource(R.drawable.ic_whtr)),
|
||||
IC_HIPS(IconResource.PainterResource(R.drawable.ic_hip)),
|
||||
IC_VISCERAL_FAT(IconResource.PainterResource(R.drawable.ic_visceral_fat)),
|
||||
IC_CHEST(IconResource.PainterResource(R.drawable.ic_chest)),
|
||||
IC_THIGH(IconResource.PainterResource(R.drawable.ic_thigh)),
|
||||
IC_BICEPS(IconResource.PainterResource(R.drawable.ic_biceps)),
|
||||
IC_NECK(IconResource.PainterResource(R.drawable.ic_neck)),
|
||||
IC_CALIPER1(IconResource.PainterResource(R.drawable.ic_caliper1)),
|
||||
IC_CALIPER2(IconResource.PainterResource(R.drawable.ic_caliper2)),
|
||||
IC_CALIPER3(IconResource.PainterResource(R.drawable.ic_caliper3)),
|
||||
IC_FAT_CALIPER(IconResource.PainterResource(R.drawable.ic_fat_caliper)),
|
||||
IC_BMR(IconResource.PainterResource(R.drawable.ic_bmr)),
|
||||
IC_TDEE(IconResource.PainterResource(R.drawable.ic_tdee)),
|
||||
IC_CALORIES(IconResource.PainterResource(R.drawable.ic_calories)),
|
||||
IC_COMMENT(IconResource.PainterResource(R.drawable.ic_comment)),
|
||||
IC_TIME(IconResource.PainterResource(R.drawable.ic_time)),
|
||||
IC_DATE(IconResource.PainterResource(R.drawable.ic_date)),
|
||||
|
||||
IC_M_HEIGHT(IconResource.VectorResource(Icons.Filled.Height)),
|
||||
IC_M_HEART_RATE(IconResource.VectorResource(Icons.Filled.Favorite)),
|
||||
IC_M_STEPS(IconResource.VectorResource(Icons.AutoMirrored.Filled.DirectionsWalk)),
|
||||
IC_M_SLEEP(IconResource.VectorResource(Icons.Filled.NightsStay)),
|
||||
IC_M_WORKOUT(IconResource.VectorResource(Icons.Filled.FitnessCenter)),
|
||||
IC_M_WATER_INTAKE(IconResource.VectorResource(Icons.Filled.LocalDrink)),
|
||||
IC_M_GOAL(IconResource.VectorResource(Icons.Filled.Flag)),
|
||||
IC_M_NOTES(IconResource.VectorResource(Icons.Filled.EditNote)),
|
||||
IC_M_TEMPERATURE(IconResource.VectorResource(Icons.Filled.DeviceThermostat)),
|
||||
IC_M_BLOOD_PRESSURE(IconResource.VectorResource(Icons.Filled.Bloodtype)),
|
||||
IC_M_GLUCOSE(IconResource.VectorResource(Icons.Filled.Bloodtype)),
|
||||
IC_M_TREND_UP(IconResource.VectorResource(Icons.AutoMirrored.Filled.TrendingUp)),
|
||||
IC_M_TREND_DOWN(IconResource.VectorResource(Icons.AutoMirrored.Filled.TrendingDown)),
|
||||
IC_M_TREND_FLAT(IconResource.VectorResource(Icons.AutoMirrored.Filled.TrendingFlat)),
|
||||
IC_M_CALENDAR(IconResource.VectorResource(Icons.Filled.CalendarMonth)),
|
||||
IC_M_CLOCK(IconResource.VectorResource(Icons.Filled.Schedule)),
|
||||
IC_M_TIMER(IconResource.VectorResource(Icons.Filled.Timer)),
|
||||
IC_M_INFO(IconResource.VectorResource(Icons.Filled.Info)),
|
||||
IC_M_HELP(IconResource.VectorResource(Icons.AutoMirrored.Filled.HelpOutline)),
|
||||
IC_M_SETTINGS(IconResource.VectorResource(Icons.Filled.Settings)),
|
||||
IC_M_ADD(IconResource.VectorResource(Icons.Filled.AddCircleOutline)),
|
||||
IC_M_REMOVE(IconResource.VectorResource(Icons.Filled.RemoveCircleOutline)),
|
||||
IC_M_DONE(IconResource.VectorResource(Icons.Filled.Done)),
|
||||
IC_M_CHECK_CIRCLE(IconResource.VectorResource(Icons.Filled.CheckCircleOutline)),
|
||||
IC_M_WARNING(IconResource.VectorResource(Icons.Filled.WarningAmber)),
|
||||
IC_M_ANALYTICS(IconResource.VectorResource(Icons.Filled.Analytics)),
|
||||
IC_M_CHART_BAR(IconResource.VectorResource(Icons.AutoMirrored.Filled.ShowChart)),
|
||||
IC_M_CHART_LINE(IconResource.VectorResource(Icons.Filled.StackedLineChart)),
|
||||
IC_M_CHART_PIE(IconResource.VectorResource(Icons.Filled.PieChart)),
|
||||
IC_M_NUTRITION(IconResource.VectorResource(Icons.Filled.LocalDining)),
|
||||
IC_M_PROTEIN(IconResource.VectorResource(Icons.Filled.Egg)),
|
||||
IC_M_CARBS(IconResource.VectorResource(Icons.Filled.Grain)),
|
||||
IC_M_FAT_FOOD(IconResource.VectorResource(Icons.Filled.OilBarrel)),
|
||||
IC_M_SPEED(IconResource.VectorResource(Icons.Filled.Speed)),
|
||||
IC_M_DISTANCE(IconResource.VectorResource(Icons.Filled.SquareFoot)),
|
||||
IC_M_MOOD(IconResource.VectorResource(Icons.Filled.SentimentSatisfiedAlt)),
|
||||
IC_M_MEDICATION(IconResource.VectorResource(Icons.Filled.Medication)),
|
||||
IC_M_LIST(IconResource.VectorResource(Icons.AutoMirrored.Filled.List)),
|
||||
IC_M_LABEL(IconResource.VectorResource(Icons.AutoMirrored.Filled.Label)),
|
||||
IC_M_PERSON(IconResource.VectorResource(Icons.Filled.Person));
|
||||
|
||||
sealed class IconResource {
|
||||
data class PainterResource(@DrawableRes val id: Int) : IconResource()
|
||||
data class VectorResource(val imageVector: ImageVector) : IconResource()
|
||||
}
|
||||
}
|
||||
|
||||
enum class MeasurementTypeKey(
|
||||
val id: Int,
|
||||
@StringRes val localizedNameResId: Int,
|
||||
|
@@ -28,7 +28,7 @@ data class MeasurementType(
|
||||
val key: MeasurementTypeKey = MeasurementTypeKey.CUSTOM,
|
||||
val name: String? = null,
|
||||
val color: Int = 0,
|
||||
val icon : String = "ic_weight",
|
||||
val icon : MeasurementTypeIcon = MeasurementTypeIcon.IC_DEFAULT,
|
||||
val unit: UnitType = UnitType.NONE,
|
||||
val inputType: InputFieldType = InputFieldType.FLOAT,
|
||||
val displayOrder: Int = 0,
|
||||
|
@@ -0,0 +1,88 @@
|
||||
package com.health.openscale.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||
|
||||
/**
|
||||
* Displays a [MeasurementTypeIcon] directly.
|
||||
* This is the core component for rendering the icon graphic.
|
||||
*
|
||||
* @param icon The [MeasurementTypeIcon] enum constant to display.
|
||||
* @param modifier [Modifier] to be applied to the Icon composable.
|
||||
* @param size The size of the icon graphic.
|
||||
* @param tint The tint color for the icon graphic.
|
||||
*/
|
||||
@Composable
|
||||
fun MeasurementIcon(
|
||||
icon: MeasurementTypeIcon,
|
||||
modifier: Modifier = Modifier,
|
||||
size: Dp = 24.dp,
|
||||
tint: Color = LocalContentColor.current
|
||||
) {
|
||||
when (val resource = icon.resource) {
|
||||
is MeasurementTypeIcon.IconResource.PainterResource -> {
|
||||
Icon(
|
||||
painter = painterResource(id = resource.id),
|
||||
contentDescription = icon.name,
|
||||
modifier = modifier.size(size),
|
||||
tint = tint
|
||||
)
|
||||
}
|
||||
is MeasurementTypeIcon.IconResource.VectorResource -> {
|
||||
Icon(
|
||||
imageVector = resource.imageVector,
|
||||
contentDescription = icon.name,
|
||||
modifier = modifier.size(size),
|
||||
tint = tint
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a [MeasurementTypeIcon] centered within a circular background.
|
||||
*
|
||||
* @param icon The [MeasurementTypeIcon] enum constant to display.
|
||||
* @param modifier [Modifier] to be applied to the outer Box that forms the circle.
|
||||
* @param size The size of the actual icon graphic itself (e.g., 24.dp).
|
||||
* @param backgroundTint The background color of the circle. Defaults to `MaterialTheme.colorScheme.surfaceVariant`.
|
||||
* @param iconTint The tint color for the icon graphic. Defaults to Black.
|
||||
*/
|
||||
@Composable
|
||||
fun RoundMeasurementIcon(
|
||||
icon: MeasurementTypeIcon,
|
||||
modifier: Modifier = Modifier,
|
||||
size: Dp = 28.dp,
|
||||
backgroundTint : Color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
iconTint: Color = Color.Black
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(size + 18.dp)
|
||||
.aspectRatio(1f)
|
||||
.clip(CircleShape)
|
||||
.background(backgroundTint),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
MeasurementIcon(
|
||||
icon = icon,
|
||||
size = size,
|
||||
tint = iconTint
|
||||
)
|
||||
}
|
||||
}
|
@@ -17,19 +17,14 @@
|
||||
*/
|
||||
package com.health.openscale.ui.screen.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -40,15 +35,12 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.health.openscale.R
|
||||
import com.health.openscale.core.data.MeasurementType
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
@@ -194,8 +186,8 @@ fun MeasurementTypeFilterRow(
|
||||
) {
|
||||
selectableTypes.forEach { type ->
|
||||
val isSelected = type.id in displayedSelectedIds
|
||||
val backgroundColor = if (isSelected) Color(type.color) else MaterialTheme.colorScheme.surfaceVariant
|
||||
val contentColor = if (isSelected) Color.Black else MaterialTheme.colorScheme.onSurfaceVariant // Consider MaterialTheme.colorScheme.onPrimary for selected state if type.color is primary-like
|
||||
val iconBackgroundColor = if (isSelected) Color(type.color) else MaterialTheme.colorScheme.surfaceVariant
|
||||
val iconColor = if (isSelected) Color.Black else MaterialTheme.colorScheme.onSurfaceVariant // Consider MaterialTheme.colorScheme.onPrimary for selected state if type.color is primary-like
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
@@ -231,36 +223,11 @@ fun MeasurementTypeFilterRow(
|
||||
}
|
||||
}
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(iconBoxSize)
|
||||
.clip(CircleShape)
|
||||
.background(backgroundColor)
|
||||
.padding((iconBoxSize - iconSize) / 2), // Center icon within the box
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val iconResId = remember(type.icon, context) {
|
||||
if (type.icon.isNotBlank()) {
|
||||
// It's generally safer to handle potential ResourceNotFoundException if icon names might be invalid
|
||||
try {
|
||||
context.resources.getIdentifier(type.icon, "drawable", context.packageName)
|
||||
} catch (e: Exception) {
|
||||
// Log error or handle missing icon gracefully
|
||||
0 // Return 0 if icon not found
|
||||
}
|
||||
} else 0
|
||||
}
|
||||
if (iconResId != 0) {
|
||||
Icon(
|
||||
painter = painterResource(id = iconResId),
|
||||
contentDescription = stringResource(R.string.content_desc_measurement_type_icon, type.getDisplayName(LocalContext.current)),
|
||||
tint = contentColor,
|
||||
modifier = Modifier.size(iconSize)
|
||||
)
|
||||
}
|
||||
}
|
||||
// Optionally, add a Text Composable here to display type.name below the icon
|
||||
// Text(text = type.name, style = MaterialTheme.typography.labelSmall, color = contentColor)
|
||||
RoundMeasurementIcon(
|
||||
icon = type.icon,
|
||||
backgroundTint = iconBackgroundColor,
|
||||
iconTint = iconColor
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -40,21 +40,22 @@ import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import com.health.openscale.R
|
||||
|
||||
val tangoColors = listOf(
|
||||
Color(0xFFEF2929), Color(0xFFF57900), Color(0xFFFFCE44), Color(0xFF8AE234),
|
||||
Color(0xFF729FCF), Color(0xFFAD7FA8), Color(0xFFE9B96E), Color(0xFF888A85),
|
||||
Color(0xFF204A87), Color(0xFF3465A4), Color(0xFF4E9A06), Color(0xFF5C3566),
|
||||
Color(0xFFC17D11), Color(0xFFA40000), Color(0xFFCE5C00), Color(0xFFEDD400),
|
||||
Color(0xFF73D216), Color(0xFF11A879), Color(0xFF555753), Color(0xFFBABDB6),
|
||||
Color(0xFFD3D7CF), Color(0xFFEEEEEC), Color(0xFF2E3436), Color(0xFF000000),
|
||||
Color(0xFFFFC0CB), Color(0xFFFFA07A), Color(0xFF87CEEB), Color(0xFF20B2AA),
|
||||
Color(0xFF9370DB), Color(0xFFFFD700), Color(0xFFFF8C00), Color(0xFFB22222)
|
||||
val colorPickerPalette: List<Color> = listOf(
|
||||
Color(0xFF7E57C2), Color(0xFFFFCA28), Color(0xFFEF5350), Color(0xFF29B6F6),
|
||||
Color(0xFF66BB6A), Color(0xFF4DBAC0), Color(0xFFBDBDBD), Color(0xFF78909C),
|
||||
Color(0xFFFFA726), Color(0xFFFF7043), Color(0xFF5C6BC0), Color(0xFFD84315),
|
||||
Color(0xFF8E24AA), Color(0xFFA1887F), Color(0xFFEC407A), Color(0xFFB0BEC5),
|
||||
Color(0xFFFFF59D), Color(0xFFFFE082), Color(0xFFFFCC80), Color(0xFFFB8C00),
|
||||
Color(0xFFAB47BC), Color(0xFF26A69A), Color(0xFF4CAF50), Color(0xFFE0E0E0),
|
||||
Color(0xFF9E9E9E), Color(0xFF757575), Color(0xFFF57900), Color(0xFF8AE234),
|
||||
Color(0xFF729FCF), Color(0xFFAD7FA8), Color(0xFF000000), Color(0xFFFFFFFF)
|
||||
)
|
||||
|
||||
@Composable
|
||||
@@ -83,16 +84,16 @@ fun ColorPickerDialog(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
items(tangoColors) { color ->
|
||||
items(colorPickerPalette) { color ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.aspectRatio(1f) // stellt sicher, dass Höhe = Breite = Kreis
|
||||
.aspectRatio(1f)
|
||||
.padding(4.dp)
|
||||
.clip(CircleShape)
|
||||
.background(color)
|
||||
.border(
|
||||
width = if (color == currentColor) 3.dp else 1.dp,
|
||||
color = if (color == currentColor) Color.Black else Color.Gray,
|
||||
color = if (color == currentColor) MaterialTheme.colorScheme.onSurface else MaterialTheme.colorScheme.outlineVariant,
|
||||
shape = CircleShape
|
||||
)
|
||||
.clickable {
|
||||
|
@@ -41,14 +41,17 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.health.openscale.R
|
||||
import com.health.openscale.core.data.MeasurementType
|
||||
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun DateInputDialog(
|
||||
title: String,
|
||||
initialTimestamp: Long,
|
||||
iconRes: Int,
|
||||
color: Color,
|
||||
measurementIcon: MeasurementTypeIcon,
|
||||
iconBackgroundColor: Color,
|
||||
onDismiss: () -> Unit,
|
||||
onConfirm: (Long) -> Unit
|
||||
) {
|
||||
@@ -78,20 +81,10 @@ fun DateInputDialog(
|
||||
},
|
||||
title = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.clip(CircleShape)
|
||||
.background(color),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = iconRes),
|
||||
contentDescription = null,
|
||||
tint = Color.Black,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
RoundMeasurementIcon(
|
||||
icon = measurementIcon,
|
||||
backgroundTint = iconBackgroundColor,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(title, style = MaterialTheme.typography.titleMedium)
|
||||
}
|
||||
|
@@ -1,111 +1,54 @@
|
||||
/*
|
||||
* 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.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.health.openscale.R
|
||||
|
||||
fun getIconResIdByName(name: String): Int {
|
||||
return when (name) {
|
||||
"ic_weight" -> R.drawable.ic_weight
|
||||
"ic_bmi" -> R.drawable.ic_bmi
|
||||
"ic_body_fat" -> R.drawable.ic_fat
|
||||
"ic_water" -> R.drawable.ic_water
|
||||
"ic_muscle" -> R.drawable.ic_muscle
|
||||
"ic_lbm" -> R.drawable.ic_lbm
|
||||
"ic_bone" -> R.drawable.ic_bone
|
||||
"ic_waist" -> R.drawable.ic_waist
|
||||
"ic_whr" -> R.drawable.ic_whr
|
||||
"ic_hips" -> R.drawable.ic_hip
|
||||
"ic_visceral_fat" -> R.drawable.ic_visceral_fat
|
||||
"ic_chest" -> R.drawable.ic_chest
|
||||
"ic_thigh" -> R.drawable.ic_thigh
|
||||
"ic_biceps" -> R.drawable.ic_biceps
|
||||
"ic_neck" -> R.drawable.ic_neck
|
||||
"ic_caliper1" -> R.drawable.ic_caliper1
|
||||
"ic_caliper2" -> R.drawable.ic_caliper2
|
||||
"ic_caliper3" -> R.drawable.ic_caliper3
|
||||
"ic_fat_caliper" -> R.drawable.ic_fat_caliper
|
||||
"ic_bmr" -> R.drawable.ic_bmr
|
||||
"ic_tdee" -> R.drawable.ic_tdee
|
||||
"ic_calories" -> R.drawable.ic_calories
|
||||
"ic_comment" -> R.drawable.ic_comment
|
||||
"ic_time" -> R.drawable.ic_time
|
||||
"ic_date" -> R.drawable.ic_date
|
||||
else -> R.drawable.ic_weight // Fallback
|
||||
}
|
||||
}
|
||||
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
|
||||
|
||||
@Composable
|
||||
fun IconPickerDialog(
|
||||
onIconSelected: (String) -> Unit,
|
||||
iconBackgroundColor: Color,
|
||||
onIconSelected: (MeasurementTypeIcon) -> Unit,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val icons = listOf(
|
||||
"ic_weight", "ic_bmi", "ic_body_fat", "ic_water", "ic_muscle", "ic_lbm", "ic_bone",
|
||||
"ic_waist", "ic_whr", "ic_hips", "ic_visceral_fat", "ic_chest", "ic_thigh", "ic_biceps",
|
||||
"ic_neck", "ic_caliper", "ic_bmr", "ic_tdee", "ic_calories", "ic_comment", "ic_time", "ic_date"
|
||||
)
|
||||
val availableIcons = remember {
|
||||
MeasurementTypeIcon.values().filter { it != MeasurementTypeIcon.IC_DEFAULT }
|
||||
}
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text(stringResource(R.string.dialog_title_select_icon))},
|
||||
title = { Text(stringResource(R.string.dialog_title_select_icon)) },
|
||||
text = {
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(4),
|
||||
modifier = Modifier.height(200.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
items(icons) { iconName ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.clip(CircleShape)
|
||||
.clickable { onIconSelected(iconName) },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = getIconResIdByName(iconName)),
|
||||
contentDescription = iconName,
|
||||
modifier = Modifier.size(28.dp)
|
||||
)
|
||||
}
|
||||
items(availableIcons) { iconEnum ->
|
||||
RoundMeasurementIcon(
|
||||
icon = iconEnum,
|
||||
backgroundTint = iconBackgroundColor,
|
||||
size = 28.dp,
|
||||
modifier = Modifier.clickable { onIconSelected(iconEnum) }
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@@ -56,7 +56,9 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.health.openscale.R
|
||||
import com.health.openscale.core.data.InputFieldType
|
||||
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||
import com.health.openscale.core.data.UnitType
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
|
||||
@Composable
|
||||
fun NumberInputDialog(
|
||||
@@ -64,8 +66,8 @@ fun NumberInputDialog(
|
||||
initialValue: String,
|
||||
inputType: InputFieldType,
|
||||
unit: UnitType,
|
||||
iconRes: Int,
|
||||
color: Color,
|
||||
measurementIcon: MeasurementTypeIcon,
|
||||
iconBackgroundColor: Color,
|
||||
onDismiss: () -> Unit,
|
||||
onConfirm: (String) -> Unit
|
||||
) {
|
||||
@@ -88,20 +90,10 @@ fun NumberInputDialog(
|
||||
},
|
||||
title = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.clip(CircleShape)
|
||||
.background(color),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = iconRes),
|
||||
contentDescription = null,
|
||||
tint = Color.Black,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
RoundMeasurementIcon(
|
||||
icon = measurementIcon,
|
||||
backgroundTint = iconBackgroundColor,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(title)
|
||||
}
|
||||
|
@@ -44,13 +44,15 @@ import androidx.compose.ui.res.painterResource
|
||||
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.ui.components.RoundMeasurementIcon
|
||||
|
||||
@Composable
|
||||
fun TextInputDialog(
|
||||
title: String,
|
||||
initialValue: String,
|
||||
iconRes: Int,
|
||||
color: Color,
|
||||
measurementIcon: MeasurementTypeIcon,
|
||||
iconBackgroundColor: Color,
|
||||
onDismiss: () -> Unit,
|
||||
onConfirm: (String) -> Unit
|
||||
) {
|
||||
@@ -69,20 +71,10 @@ fun TextInputDialog(
|
||||
},
|
||||
title = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.clip(CircleShape)
|
||||
.background(color),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = iconRes),
|
||||
contentDescription = null,
|
||||
tint = Color.Black,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
RoundMeasurementIcon(
|
||||
icon = measurementIcon,
|
||||
backgroundTint = iconBackgroundColor,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(text = title, style = MaterialTheme.typography.titleMedium)
|
||||
}
|
||||
|
@@ -52,14 +52,16 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.health.openscale.R
|
||||
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
import java.util.Calendar
|
||||
|
||||
@Composable
|
||||
fun TimeInputDialog(
|
||||
title: String,
|
||||
initialTimestamp: Long,
|
||||
iconRes: Int,
|
||||
color: Color,
|
||||
measurementIcon: MeasurementTypeIcon,
|
||||
iconBackgroundColor: Color,
|
||||
onDismiss: () -> Unit,
|
||||
onConfirm: (Long) -> Unit
|
||||
) {
|
||||
@@ -90,20 +92,10 @@ fun TimeInputDialog(
|
||||
},
|
||||
title = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.clip(CircleShape)
|
||||
.background(color),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = iconRes),
|
||||
contentDescription = null,
|
||||
tint = Color.Black,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
RoundMeasurementIcon(
|
||||
icon = measurementIcon,
|
||||
backgroundTint = iconBackgroundColor,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(title, style = MaterialTheme.typography.titleMedium)
|
||||
}
|
||||
|
@@ -64,15 +64,17 @@ import com.health.openscale.R
|
||||
import com.health.openscale.core.data.InputFieldType
|
||||
import com.health.openscale.core.data.Measurement
|
||||
import com.health.openscale.core.data.MeasurementType
|
||||
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||
import com.health.openscale.core.data.MeasurementTypeKey
|
||||
import com.health.openscale.core.data.MeasurementValue
|
||||
import com.health.openscale.core.data.UnitType
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
import com.health.openscale.ui.screen.SharedViewModel
|
||||
import com.health.openscale.ui.screen.dialog.DateInputDialog
|
||||
import com.health.openscale.ui.screen.dialog.NumberInputDialog
|
||||
import com.health.openscale.ui.screen.dialog.TextInputDialog
|
||||
import com.health.openscale.ui.screen.dialog.TimeInputDialog
|
||||
import com.health.openscale.ui.screen.dialog.decrementValue
|
||||
import com.health.openscale.ui.screen.dialog.getIconResIdByName
|
||||
import com.health.openscale.ui.screen.dialog.incrementValue
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
@@ -357,7 +359,7 @@ fun MeasurementDetailScreen(
|
||||
|
||||
// --- Dialogs for FLOAT, INT, TEXT based on dialogTargetType ---
|
||||
dialogTargetType?.let { currentType ->
|
||||
val typeIconRes = remember(currentType.icon) { getIconResIdByName(currentType.icon) }
|
||||
val measurementTypeIcon = remember(currentType.icon) { currentType.icon }
|
||||
val typeColor = remember(currentType.color) { Color(currentType.color) }
|
||||
val initialDialogValue = valuesState[currentType.id] ?: when (currentType.inputType) {
|
||||
InputFieldType.FLOAT -> "0.0" // Default for empty float
|
||||
@@ -373,8 +375,8 @@ fun MeasurementDetailScreen(
|
||||
initialValue = initialDialogValue,
|
||||
inputType = currentType.inputType,
|
||||
unit = currentType.unit,
|
||||
iconRes = typeIconRes,
|
||||
color = typeColor,
|
||||
measurementIcon = measurementTypeIcon,
|
||||
iconBackgroundColor = typeColor,
|
||||
onDismiss = { dialogTargetType = null },
|
||||
onConfirm = { confirmedValue ->
|
||||
val trimmedValue = confirmedValue.trim()
|
||||
@@ -411,8 +413,8 @@ fun MeasurementDetailScreen(
|
||||
TextInputDialog(
|
||||
title = dialogTitle,
|
||||
initialValue = initialDialogValue,
|
||||
iconRes = typeIconRes,
|
||||
color = typeColor,
|
||||
measurementIcon = measurementTypeIcon,
|
||||
iconBackgroundColor = typeColor,
|
||||
onDismiss = { dialogTargetType = null },
|
||||
onConfirm = { confirmedValue ->
|
||||
val finalValue = confirmedValue.trim()
|
||||
@@ -433,13 +435,13 @@ fun MeasurementDetailScreen(
|
||||
|
||||
// --- Dialogs for the main measurement timestamp (measurementTimestampState) ---
|
||||
if (showDatePickerForMainTimestamp) {
|
||||
val triggeringType = allMeasurementTypes.find { it.inputType == InputFieldType.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))
|
||||
DateInputDialog(
|
||||
title = dateDialogTitle,
|
||||
initialTimestamp = measurementTimestampState,
|
||||
iconRes = getIconResIdByName(triggeringType?.icon ?: "ic_calendar"),
|
||||
color = triggeringType?.let { Color(it.color) } ?: MaterialTheme.colorScheme.primary,
|
||||
measurementIcon = triggeringType?.icon ?: MeasurementTypeIcon.IC_DATE,
|
||||
iconBackgroundColor = triggeringType?.let { Color(it.color) } ?: MaterialTheme.colorScheme.primary,
|
||||
onDismiss = { showDatePickerForMainTimestamp = false },
|
||||
onConfirm = { newDateMillis ->
|
||||
val newCal = Calendar.getInstance().apply { timeInMillis = newDateMillis }
|
||||
@@ -452,13 +454,13 @@ fun MeasurementDetailScreen(
|
||||
}
|
||||
|
||||
if (showTimePickerForMainTimestamp) {
|
||||
val triggeringType = allMeasurementTypes.find { it.inputType == InputFieldType.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))
|
||||
TimeInputDialog(
|
||||
title = timeDialogTitle,
|
||||
initialTimestamp = measurementTimestampState,
|
||||
iconRes = getIconResIdByName(triggeringType?.icon ?: "ic_time"),
|
||||
color = triggeringType?.let { Color(it.color) } ?: MaterialTheme.colorScheme.primary,
|
||||
measurementIcon = triggeringType?.icon ?: MeasurementTypeIcon.IC_TIME,
|
||||
iconBackgroundColor = triggeringType?.let { Color(it.color) } ?: MaterialTheme.colorScheme.primary,
|
||||
onDismiss = { showTimePickerForMainTimestamp = false },
|
||||
onConfirm = { newTimeMillis ->
|
||||
val newCal = Calendar.getInstance().apply { timeInMillis = newTimeMillis }
|
||||
@@ -501,23 +503,10 @@ fun MeasurementValueEditRow(
|
||||
.padding(vertical = 8.dp)
|
||||
.clickable(onClick = onEditClick, enabled = !type.isDerived) // Clicking row triggers edit, disabled for derived
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.clip(CircleShape)
|
||||
.background(Color(type.color)), // Uses the type's specific color
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val iconId = remember(type.icon) { getIconResIdByName( type.icon) }
|
||||
if (iconId != 0) {
|
||||
Icon(
|
||||
painter = painterResource(id = iconId),
|
||||
contentDescription = type.getDisplayName(context), // Type name serves as base content description
|
||||
tint = Color.Black, // Consider a more adaptive tint based on background color for accessibility
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
RoundMeasurementIcon(
|
||||
icon = type.icon,
|
||||
backgroundTint = Color(type.color),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(text = type.getDisplayName(context), style = MaterialTheme.typography.bodyLarge)
|
||||
|
@@ -89,6 +89,7 @@ import com.health.openscale.core.data.InputFieldType
|
||||
import com.health.openscale.core.data.Trend
|
||||
import com.health.openscale.core.model.MeasurementWithValues
|
||||
import com.health.openscale.core.database.UserPreferenceKeys
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
import com.health.openscale.ui.navigation.Routes
|
||||
import com.health.openscale.ui.screen.SharedViewModel
|
||||
import com.health.openscale.ui.screen.ValueWithDifference
|
||||
@@ -775,11 +776,7 @@ fun MeasurementValueRow(valueWithTrend: ValueWithDifference) {
|
||||
} ?: "-" // Default to dash if value is null
|
||||
|
||||
val context = LocalContext.current
|
||||
val iconId = remember(type.icon) {
|
||||
// Attempt to get the drawable resource ID for the type's icon name
|
||||
// This relies on the icon name string matching a drawable resource name
|
||||
context.resources.getIdentifier(type.icon, "drawable", context.packageName)
|
||||
}
|
||||
val iconMeasurementType = remember(type.icon) {type.icon }
|
||||
// Dynamic content description for the icon based on type name
|
||||
val iconContentDescription = stringResource(R.string.measurement_type_icon_desc, type.getDisplayName(context))
|
||||
// Fallback content description if the icon is not found (e.g. shows question mark)
|
||||
@@ -795,30 +792,10 @@ fun MeasurementValueRow(valueWithTrend: ValueWithDifference) {
|
||||
modifier = Modifier.weight(1f), // Takes available space, pushing value & trend to the right
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(36.dp) // Standardized size for the icon container
|
||||
.clip(CircleShape)
|
||||
.background(Color(type.color)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (iconId != 0) { // Check if the resource ID is valid
|
||||
Icon(
|
||||
painter = painterResource(id = iconId),
|
||||
contentDescription = type.getDisplayName(context),
|
||||
tint = Color.Black,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
} else {
|
||||
// Fallback icon if the specified icon resource is not found
|
||||
Icon(
|
||||
imageVector = Icons.Filled.QuestionMark,
|
||||
contentDescription = unknownTypeContentDescription,
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = Color.Black
|
||||
)
|
||||
}
|
||||
}
|
||||
RoundMeasurementIcon(
|
||||
icon = iconMeasurementType,
|
||||
backgroundTint = Color(type.color),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Column(verticalArrangement = Arrangement.Center) {
|
||||
Text(
|
||||
|
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
package com.health.openscale.ui.screen.settings
|
||||
|
||||
import android.R.attr.enabled
|
||||
import android.R.attr.label
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
@@ -25,12 +27,14 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.QuestionMark
|
||||
@@ -73,12 +77,13 @@ import androidx.navigation.NavController
|
||||
import com.health.openscale.R
|
||||
import com.health.openscale.core.data.InputFieldType
|
||||
import com.health.openscale.core.data.MeasurementType
|
||||
import com.health.openscale.core.data.MeasurementTypeIcon
|
||||
import com.health.openscale.core.data.MeasurementTypeKey
|
||||
import com.health.openscale.core.data.UnitType
|
||||
import com.health.openscale.ui.components.MeasurementIcon
|
||||
import com.health.openscale.ui.screen.SharedViewModel
|
||||
import com.health.openscale.ui.screen.dialog.ColorPickerDialog
|
||||
import com.health.openscale.ui.screen.dialog.IconPickerDialog
|
||||
import com.health.openscale.ui.screen.dialog.getIconResIdByName
|
||||
import kotlin.text.lowercase
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@@ -137,7 +142,7 @@ fun MeasurementTypeDetailScreen(
|
||||
}
|
||||
}
|
||||
var selectedColor by remember { mutableStateOf(originalExistingType?.color ?: 0xFF6200EE.toInt()) }
|
||||
var selectedIcon by remember { mutableStateOf(originalExistingType?.icon ?: "ic_weight") }
|
||||
var selectedIcon by remember { mutableStateOf(originalExistingType?.icon ?: MeasurementTypeIcon.IC_WEIGHT) }
|
||||
var isEnabled by remember { mutableStateOf(originalExistingType?.isEnabled ?: true) }
|
||||
var isPinned by remember { mutableStateOf(originalExistingType?.isPinned ?: false) }
|
||||
var isOnRightYAxis by remember { mutableStateOf(originalExistingType?.isOnRightYAxis ?: false) }
|
||||
@@ -286,7 +291,7 @@ fun MeasurementTypeDetailScreen(
|
||||
}
|
||||
|
||||
OutlinedTextField(
|
||||
value = String.format("#%06X", 0xFFFFFF and selectedColor),
|
||||
value = "",
|
||||
onValueChange = {}, // Read-only
|
||||
label = { Text(stringResource(R.string.measurement_type_label_color)) },
|
||||
modifier = Modifier
|
||||
@@ -300,7 +305,6 @@ fun MeasurementTypeDetailScreen(
|
||||
.size(24.dp)
|
||||
.clip(CircleShape)
|
||||
.background(Color(selectedColor))
|
||||
.border(1.dp, Color.Gray, CircleShape)
|
||||
)
|
||||
},
|
||||
colors = TextFieldDefaults.colors(
|
||||
@@ -313,7 +317,7 @@ fun MeasurementTypeDetailScreen(
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
value = selectedIcon,
|
||||
value = "",
|
||||
onValueChange = {}, // Read-only
|
||||
label = { Text(stringResource(R.string.measurement_type_label_icon)) },
|
||||
modifier = Modifier
|
||||
@@ -322,14 +326,8 @@ fun MeasurementTypeDetailScreen(
|
||||
readOnly = true,
|
||||
enabled = false, // To make it look like a display field
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
painter = runCatching {
|
||||
painterResource(id = getIconResIdByName(selectedIcon))
|
||||
}.getOrElse {
|
||||
Icons.Filled.QuestionMark // Fallback icon
|
||||
} as Painter,
|
||||
contentDescription = stringResource(R.string.content_desc_selected_icon_preview),
|
||||
modifier = Modifier.size(24.dp)
|
||||
MeasurementIcon(
|
||||
icon = selectedIcon,
|
||||
)
|
||||
},
|
||||
colors = TextFieldDefaults.colors(
|
||||
@@ -342,50 +340,55 @@ fun MeasurementTypeDetailScreen(
|
||||
)
|
||||
|
||||
if (unitDropdownEnabled) {
|
||||
// UnitType Dropdown
|
||||
ExposedDropdownMenuBox(
|
||||
expanded = expandedUnit && unitDropdownEnabled,
|
||||
onExpandedChange = {
|
||||
if (unitDropdownEnabled) expandedUnit = !expandedUnit
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
OutlinedTextField(
|
||||
readOnly = true,
|
||||
value = selectedUnit.displayName.lowercase()
|
||||
.replaceFirstChar { it.uppercase() },
|
||||
onValueChange = {},
|
||||
label = { Text(stringResource(R.string.measurement_type_label_unit)) },
|
||||
trailingIcon = {
|
||||
if (unitDropdownEnabled) {
|
||||
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expandedUnit)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
OutlinedSettingRow(
|
||||
label = stringResource(R.string.measurement_type_label_unit),
|
||||
surfaceModifier = Modifier
|
||||
.menuAnchor(
|
||||
type = MenuAnchorType.PrimaryNotEditable,
|
||||
enabled = unitDropdownEnabled
|
||||
)
|
||||
.fillMaxWidth(),
|
||||
colors = if (!unitDropdownEnabled) OutlinedTextFieldDefaults.colors(
|
||||
disabledTextColor = MaterialTheme.colorScheme.onSurface,
|
||||
disabledBorderColor = MaterialTheme.colorScheme.outline,
|
||||
disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
disabledTrailingIconColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(
|
||||
alpha = 0.38f
|
||||
)
|
||||
) else OutlinedTextFieldDefaults.colors()
|
||||
.clickable(enabled = unitDropdownEnabled) {
|
||||
if (unitDropdownEnabled) expandedUnit = true
|
||||
},
|
||||
controlContent = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = selectedUnit.displayName,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = if (unitDropdownEnabled) MaterialTheme.colorScheme.onSurface else MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f)
|
||||
)
|
||||
if (unitDropdownEnabled) {
|
||||
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expandedUnit)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (unitDropdownEnabled) {
|
||||
ExposedDropdownMenu(
|
||||
expanded = expandedUnit,
|
||||
onDismissRequest = { expandedUnit = false }
|
||||
onDismissRequest = { expandedUnit = false },
|
||||
modifier = Modifier.exposedDropdownSize(matchTextFieldWidth = true)
|
||||
) {
|
||||
allowedUnitsForKey.forEach { unit ->
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
unit.displayName.lowercase()
|
||||
.replaceFirstChar { it.uppercase() })
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
contentAlignment = Alignment.CenterEnd
|
||||
) {
|
||||
Text(
|
||||
text = unit.displayName,
|
||||
modifier = Modifier.padding(end = 32.dp)
|
||||
)
|
||||
}
|
||||
},
|
||||
onClick = {
|
||||
selectedUnit = unit
|
||||
@@ -459,6 +462,7 @@ fun MeasurementTypeDetailScreen(
|
||||
|
||||
if (showIconPicker) {
|
||||
IconPickerDialog(
|
||||
iconBackgroundColor = Color(selectedColor),
|
||||
onIconSelected = {
|
||||
selectedIcon = it
|
||||
showIconPicker = false
|
||||
@@ -472,12 +476,14 @@ fun MeasurementTypeDetailScreen(
|
||||
private fun OutlinedSettingRow(
|
||||
label: String,
|
||||
modifier: Modifier = Modifier,
|
||||
surfaceModifier: Modifier = Modifier,
|
||||
controlContent: @Composable () -> Unit
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = OutlinedTextFieldDefaults.MinHeight),
|
||||
.heightIn(min = OutlinedTextFieldDefaults.MinHeight)
|
||||
.then(surfaceModifier),
|
||||
shape = OutlinedTextFieldDefaults.shape,
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
border = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.outline)
|
||||
|
@@ -58,6 +58,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.health.openscale.R
|
||||
import com.health.openscale.core.data.MeasurementTypeKey
|
||||
import com.health.openscale.ui.components.MeasurementIcon
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
import com.health.openscale.ui.screen.SharedViewModel
|
||||
import sh.calvin.reorderable.ReorderableItem
|
||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||
@@ -145,30 +147,15 @@ fun MeasurementTypeSettingsScreen(
|
||||
.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// Display colored circle with icon
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.background(
|
||||
Color(type.color).copy(alpha = iconBackgroundAlpha),
|
||||
shape = CircleShape
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
// Remember the icon resource ID to avoid repeated lookups
|
||||
val iconId = remember(type.icon) {
|
||||
context.resources.getIdentifier(type.icon, "drawable", context.packageName)
|
||||
}
|
||||
if (iconId != 0) { // Check if icon resource was found
|
||||
Icon(
|
||||
painter = painterResource(id = iconId),
|
||||
contentDescription = null, // Decorative icon
|
||||
tint = Color.Black.copy(alpha = iconTintAlpha), // Consider a more theme-aware tint
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
val iconMeasurementType = remember(type.icon) {type.icon }
|
||||
|
||||
RoundMeasurementIcon(
|
||||
icon = iconMeasurementType,
|
||||
iconTint = Color.Black.copy(alpha = iconTintAlpha),
|
||||
backgroundTint = Color(type.color).copy(alpha = iconBackgroundAlpha),
|
||||
modifier = Modifier.size(48.dp)
|
||||
)
|
||||
|
||||
Spacer(Modifier.size(16.dp))
|
||||
|
||||
// Display measurement type name
|
||||
|
@@ -61,12 +61,12 @@ import com.health.openscale.R
|
||||
import com.health.openscale.core.data.InputFieldType
|
||||
import com.health.openscale.core.data.MeasurementType
|
||||
import com.health.openscale.core.database.UserPreferenceKeys
|
||||
import com.health.openscale.ui.components.RoundMeasurementIcon
|
||||
import com.health.openscale.ui.screen.EnrichedMeasurement
|
||||
import com.health.openscale.ui.screen.SharedViewModel
|
||||
import com.health.openscale.ui.screen.components.LineChart
|
||||
import com.health.openscale.ui.screen.components.provideFilterTopBarAction
|
||||
import com.health.openscale.ui.screen.components.rememberContextualTimeRangeFilter
|
||||
import com.health.openscale.ui.screen.dialog.getIconResIdByName
|
||||
import java.text.DecimalFormat
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
@@ -337,23 +337,12 @@ fun StatisticCard(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.clip(CircleShape)
|
||||
.background(Color(measurementType.color)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val iconId = remember(measurementType.icon) { getIconResIdByName(measurementType.icon) }
|
||||
if (iconId != 0) {
|
||||
Icon(
|
||||
painter = painterResource(id = iconId),
|
||||
contentDescription = measurementType.getDisplayName(LocalContext.current), // Icon related to measurement type
|
||||
tint = Color.Black, // Assuming black provides good contrast on the colored background
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
val iconMeasurementType = remember(measurementType.icon) { measurementType.icon }
|
||||
|
||||
RoundMeasurementIcon(
|
||||
icon = iconMeasurementType,
|
||||
backgroundTint = Color(measurementType.color),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = measurementType.getDisplayName(LocalContext.current),
|
||||
|
@@ -256,7 +256,6 @@
|
||||
<string name="line_chart_no_data_or_types_to_select">Keine Daten zum Anzeigen oder Typen zur Auswahl.</string>
|
||||
<string name="line_chart_no_data_for_selected_types">Keine Daten für die ausgewählten Typen verfügbar.</string>
|
||||
<string name="menu_item_measurement_filter">Messfilter ein-/ausblenden</string>
|
||||
<string name="content_desc_measurement_type_icon">Nach %1$s filtern</string>
|
||||
|
||||
<!-- Tabellen-Bildschirm -->
|
||||
<string name="table_header_date">Datum</string>
|
||||
|
@@ -258,7 +258,6 @@
|
||||
<string name="line_chart_no_data_or_types_to_select">No data to display or types to select.</string>
|
||||
<string name="line_chart_no_data_for_selected_types">No data available for the selected types.</string>
|
||||
<string name="menu_item_measurement_filter">Show/Hide Measurement Filter</string>
|
||||
<string name="content_desc_measurement_type_icon">Filter by %1$s</string>
|
||||
|
||||
<!-- Table Screen -->
|
||||
<string name="table_header_date">Date</string>
|
||||
|
Reference in New Issue
Block a user