mirror of
https://github.com/dzeiocom/OpenHealth.git
synced 2025-04-23 19:32:11 +00:00
fix: Allow to use other volumes units than Milliliter (#156)
This commit is contained in:
parent
fa56970fb6
commit
497cc58057
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@ -40,6 +40,7 @@ jobs:
|
|||||||
- name: Zip artifacts
|
- name: Zip artifacts
|
||||||
run: zip -r assemble.zip . -i '**/build/*.apk' '**/build/*.aab' '**/build/*.aar' '**/build/*.so'
|
run: zip -r assemble.zip . -i '**/build/*.apk' '**/build/*.aab' '**/build/*.aar' '**/build/*.so'
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
|
continue-on-error: true
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: assemble
|
name: assemble
|
||||||
|
@ -40,6 +40,13 @@ object Settings {
|
|||||||
*/
|
*/
|
||||||
const val WATER_INTAKE_SIZE = "com.dzeio.open-health.water.size"
|
const val WATER_INTAKE_SIZE = "com.dzeio.open-health.water.size"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* volume unit used
|
||||||
|
*/
|
||||||
|
const val VOLUME_UNIT = "com.dzeio.open-health.volume-unit"
|
||||||
|
|
||||||
|
const val WATER_INTAKE_DAILY_GOAL = "com.dzeio.open-health.water.daily"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the default value for the setting above
|
* the default value for the setting above
|
||||||
*/
|
*/
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.dzeio.openhealth.ui.home
|
package com.dzeio.openhealth.ui.home
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
@ -10,21 +9,22 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import com.dzeio.charts.Entry
|
import com.dzeio.charts.Entry
|
||||||
import com.dzeio.charts.axis.Line
|
import com.dzeio.charts.axis.Line
|
||||||
import com.dzeio.charts.series.LineSerie
|
import com.dzeio.charts.series.LineSerie
|
||||||
import com.dzeio.openhealth.BuildConfig
|
import com.dzeio.openhealth.BuildConfig
|
||||||
|
import com.dzeio.openhealth.R
|
||||||
import com.dzeio.openhealth.core.BaseFragment
|
import com.dzeio.openhealth.core.BaseFragment
|
||||||
import com.dzeio.openhealth.data.water.Water
|
import com.dzeio.openhealth.data.water.Water
|
||||||
import com.dzeio.openhealth.data.weight.Weight
|
|
||||||
import com.dzeio.openhealth.databinding.FragmentHomeBinding
|
import com.dzeio.openhealth.databinding.FragmentHomeBinding
|
||||||
import com.dzeio.openhealth.ui.weight.WeightDialog
|
import com.dzeio.openhealth.ui.weight.WeightDialog
|
||||||
import com.dzeio.openhealth.units.Units
|
|
||||||
import com.dzeio.openhealth.utils.ChartUtils
|
import com.dzeio.openhealth.utils.ChartUtils
|
||||||
import com.dzeio.openhealth.utils.DrawUtils
|
import com.dzeio.openhealth.utils.DrawUtils
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@ -34,10 +34,6 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
|||||||
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHomeBinding
|
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHomeBinding
|
||||||
get() = FragmentHomeBinding::inflate
|
get() = FragmentHomeBinding::inflate
|
||||||
|
|
||||||
private val settings: SharedPreferences by lazy {
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
// Bindings
|
// Bindings
|
||||||
@ -63,14 +59,14 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
|||||||
viewModel.updateWater(water)
|
viewModel.updateWater(water)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val waterUnit =
|
|
||||||
Units.Volume.find(settings.getString("water_unit", "milliliter") ?: "Milliliter")
|
|
||||||
|
|
||||||
binding.fragmentHomeWaterTotal.text =
|
viewModel.waterUnit.observe(viewLifecycleOwner) {
|
||||||
String.format(
|
updateWaterTotal()
|
||||||
resources.getString(waterUnit.unit),
|
}
|
||||||
viewModel.dailyWaterIntake
|
|
||||||
)
|
viewModel.dailyWaterIntake.observe(viewLifecycleOwner) {
|
||||||
|
updateWaterTotal()
|
||||||
|
}
|
||||||
|
|
||||||
binding.fragmentHomeWaterRemove.setOnClickListener {
|
binding.fragmentHomeWaterRemove.setOnClickListener {
|
||||||
val water = viewModel.water.value
|
val water = viewModel.water.value
|
||||||
@ -95,12 +91,21 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.weightGraph.apply {
|
binding.weightGraph.apply {
|
||||||
val serie = LineSerie(this)
|
LineSerie(this)
|
||||||
animator.enabled = false
|
animator.enabled = false
|
||||||
xAxis.dataWidth = 2.4192e+9
|
xAxis.apply {
|
||||||
xAxis.scrollEnabled = true
|
dataWidth = 2.4192e+9
|
||||||
|
scrollEnabled = true
|
||||||
|
onValueFormat = onValueFormat@{
|
||||||
|
val formatter = DateFormat.getDateTimeInstance(
|
||||||
|
DateFormat.SHORT,
|
||||||
|
DateFormat.SHORT,
|
||||||
|
Locale.getDefault()
|
||||||
|
)
|
||||||
|
return@onValueFormat formatter.format(Date(it.toLong()))
|
||||||
|
}
|
||||||
|
}
|
||||||
ChartUtils.materielTheme(this, requireView())
|
ChartUtils.materielTheme(this, requireView())
|
||||||
series = arrayListOf(serie)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
@ -116,75 +121,84 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
|||||||
|
|
||||||
// Update the water intake Graph when the water intake changes
|
// Update the water intake Graph when the water intake changes
|
||||||
viewModel.water.observe(viewLifecycleOwner) {
|
viewModel.water.observe(viewLifecycleOwner) {
|
||||||
if (it != null) {
|
updateWaterGraph()
|
||||||
updateWater(it.value)
|
|
||||||
} else {
|
|
||||||
updateWater(0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the steps Graph when the steps count changes
|
// Update the steps Graph when the steps count changes
|
||||||
viewModel.steps.observe(viewLifecycleOwner) {
|
viewModel.steps.observe(viewLifecycleOwner) {
|
||||||
binding.stepsCurrent.text = it.toString()
|
binding.stepsCurrent.text = getString(
|
||||||
|
R.string.steps_count,
|
||||||
|
it
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the steps Graph when the goal changes
|
// Update the steps Graph when the goal changes
|
||||||
viewModel.stepsGoal.observe(viewLifecycleOwner) {
|
viewModel.stepsGoal.observe(viewLifecycleOwner) {
|
||||||
if (it == null) {
|
if (it == null) {
|
||||||
binding.stepsTotal.text = ""
|
binding.stepsTotal.visibility = View.GONE
|
||||||
return@observe
|
return@observe
|
||||||
}
|
}
|
||||||
binding.stepsTotal.text = it.toString()
|
binding.stepsTotal.visibility = View.VISIBLE
|
||||||
|
binding.stepsTotal.text = getString(
|
||||||
|
R.string.steps_count,
|
||||||
|
it
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the graph when the weight changes
|
// update the graph when the weight changes
|
||||||
viewModel.weights.observe(viewLifecycleOwner) {
|
viewModel.weights.observe(viewLifecycleOwner) {
|
||||||
if (it != null) {
|
updateWeightGraph()
|
||||||
updateGraph(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the graph when the goal weight change
|
// update the graph when the goal weight change
|
||||||
viewModel.goalWeight.observe(viewLifecycleOwner) {
|
viewModel.goalWeight.observe(viewLifecycleOwner) {
|
||||||
if (viewModel.weights.value != null) updateGraph(viewModel.weights.value!!)
|
updateWeightGraph()
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the graph when the weight unit change
|
// update the graph when the weight unit change
|
||||||
viewModel.massUnit.observe(viewLifecycleOwner) {
|
viewModel.massUnit.observe(viewLifecycleOwner) {
|
||||||
if (viewModel.weights.value != null) updateGraph(viewModel.weights.value!!)
|
updateWeightGraph()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that update the graph for the weight
|
* Function that update the graph for the weight
|
||||||
*/
|
*/
|
||||||
private fun updateGraph(list: List<Weight>) {
|
private fun updateWeightGraph() {
|
||||||
val chart = binding.weightGraph
|
val values = viewModel.weights.value ?: arrayListOf()
|
||||||
|
val goal = viewModel.goalWeight.value
|
||||||
|
val unit = viewModel.massUnit.value
|
||||||
|
|
||||||
|
if (unit == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val chart = binding.weightGraph.apply {
|
||||||
|
yAxis.onValueFormat = { getString(unit.unit, unit.fromKilogram(it)) }
|
||||||
|
}
|
||||||
val serie = chart.series[0] as LineSerie
|
val serie = chart.series[0] as LineSerie
|
||||||
|
|
||||||
val entries: ArrayList<Entry> = arrayListOf()
|
val entries: ArrayList<Entry> = values.map {
|
||||||
|
|
||||||
list.forEach {
|
|
||||||
entries.add(
|
|
||||||
Entry(
|
Entry(
|
||||||
it.timestamp.toDouble(),
|
it.timestamp.toDouble(),
|
||||||
it.weight
|
it.weight * unit.modifier
|
||||||
)
|
)
|
||||||
)
|
} as ArrayList<Entry>
|
||||||
}
|
|
||||||
serie.entries = entries
|
serie.entries = entries
|
||||||
|
|
||||||
if (viewModel.goalWeight.value != null) {
|
chart.yAxis.clearLines()
|
||||||
|
if (goal != null) {
|
||||||
chart.yAxis.addLine(
|
chart.yAxis.addLine(
|
||||||
viewModel.goalWeight.value!!,
|
goal,
|
||||||
Line(true, Paint(chart.yAxis.linePaint).apply { strokeWidth = 4f })
|
Line(true, Paint(chart.yAxis.linePaint).apply { strokeWidth = 4f })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (entries.isEmpty()) {
|
||||||
chart.xAxis.x = 0.0
|
chart.xAxis.x = 0.0
|
||||||
} else {
|
} else {
|
||||||
chart.xAxis.x = list.last().timestamp - chart.xAxis.dataWidth!!
|
chart.xAxis.x = entries.last().x - chart.xAxis.dataWidth!!
|
||||||
}
|
}
|
||||||
|
|
||||||
chart.refresh()
|
chart.refresh()
|
||||||
@ -193,29 +207,30 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
|||||||
/**
|
/**
|
||||||
* the waterintake old value to keep for value update
|
* the waterintake old value to keep for value update
|
||||||
*/
|
*/
|
||||||
private var oldValue = 0f
|
private var oldValue = 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function that update the water count in the home page
|
* function that update the water count in the home page
|
||||||
*/
|
*/
|
||||||
private fun updateWater(newValue: Int) {
|
private fun updateWaterGraph() {
|
||||||
// get the current Unit
|
val newValue = viewModel.water.value?.value ?: 0
|
||||||
val waterUnit =
|
val daily = viewModel.dailyWaterIntake.value
|
||||||
Units.Volume.find(settings.getString("water_unit", "milliliter") ?: "Milliliter")
|
val unit = viewModel.waterUnit.value
|
||||||
|
|
||||||
|
if (unit == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Update the count
|
// Update the count
|
||||||
binding.fragmentHomeWaterCurrent.text =
|
binding.fragmentHomeWaterCurrent.text =
|
||||||
String.format(
|
getString(
|
||||||
resources.getString(waterUnit.unit),
|
unit.unit,
|
||||||
(newValue * waterUnit.modifier).toInt()
|
(newValue * unit.modifier).toInt()
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: move it elsewhere
|
if (daily == null) {
|
||||||
binding.fragmentHomeWaterTotal.text =
|
return
|
||||||
String.format(
|
}
|
||||||
resources.getString(waterUnit.unit),
|
|
||||||
viewModel.dailyWaterIntake
|
|
||||||
)
|
|
||||||
|
|
||||||
// get the with/height of the ImageView
|
// get the with/height of the ImageView
|
||||||
var width = 1500
|
var width = 1500
|
||||||
@ -228,7 +243,7 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
|||||||
|
|
||||||
// Prepare the update animation
|
// Prepare the update animation
|
||||||
val animator = ValueAnimator.ofInt(
|
val animator = ValueAnimator.ofInt(
|
||||||
this.oldValue.toInt(),
|
this.oldValue,
|
||||||
newValue
|
newValue
|
||||||
)
|
)
|
||||||
animator.duration = 300 // ms
|
animator.duration = 300 // ms
|
||||||
@ -237,8 +252,8 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
|||||||
if (localView == null) {
|
if (localView == null) {
|
||||||
return@addUpdateListener
|
return@addUpdateListener
|
||||||
}
|
}
|
||||||
this.oldValue = (it.animatedValue as Int).toFloat()
|
this.oldValue = (it.animatedValue as Int)
|
||||||
val value = 100 * it.animatedValue as Int / viewModel.dailyWaterIntake
|
val value = 100 * it.animatedValue as Int / daily.toFloat()
|
||||||
|
|
||||||
val graph = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
val graph = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||||
val canvas = Canvas(graph)
|
val canvas = Canvas(graph)
|
||||||
@ -283,4 +298,23 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
|||||||
// start the animation
|
// start the animation
|
||||||
animator.start()
|
animator.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateWaterTotal() {
|
||||||
|
val unit = viewModel.waterUnit.value
|
||||||
|
val value = viewModel.dailyWaterIntake.value
|
||||||
|
if (unit == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
binding.fragmentHomeWaterTotal.visibility = View.GONE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.fragmentHomeWaterTotal.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
binding.fragmentHomeWaterTotal.text = getString(
|
||||||
|
unit.unit,
|
||||||
|
unit.fromMilliliter(value)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,8 @@ import com.dzeio.openhealth.data.water.Water
|
|||||||
import com.dzeio.openhealth.data.water.WaterRepository
|
import com.dzeio.openhealth.data.water.WaterRepository
|
||||||
import com.dzeio.openhealth.data.weight.Weight
|
import com.dzeio.openhealth.data.weight.Weight
|
||||||
import com.dzeio.openhealth.data.weight.WeightRepository
|
import com.dzeio.openhealth.data.weight.WeightRepository
|
||||||
import com.dzeio.openhealth.units.Units
|
import com.dzeio.openhealth.units.Mass
|
||||||
|
import com.dzeio.openhealth.units.Volume
|
||||||
import com.dzeio.openhealth.utils.Configuration
|
import com.dzeio.openhealth.utils.Configuration
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -54,26 +55,25 @@ class HomeViewModel @Inject internal constructor(
|
|||||||
/**
|
/**
|
||||||
* The size of a cup for the quick water intake add
|
* The size of a cup for the quick water intake add
|
||||||
*/
|
*/
|
||||||
var waterCupSize = config.getInt("water_cup_size").toLiveData()
|
var waterCupSize = config.getInt(Settings.WATER_INTAKE_SIZE).toLiveData()
|
||||||
|
|
||||||
/**
|
private val _waterUnit = MutableLiveData(Volume.MILLILITER)
|
||||||
* The unit used to display the water intake of the user
|
val waterUnit: LiveData<Volume> = _waterUnit
|
||||||
*/
|
|
||||||
var waterUnit = Units.Volume.find(config.getString("water_unit").value ?: "ml")
|
|
||||||
|
|
||||||
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
|
private val _massUnit = MutableLiveData(Mass.KILOGRAM)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Mass unit used by the user
|
* The Mass unit used by the user
|
||||||
*/
|
*/
|
||||||
val massUnit: LiveData<Units.Mass> = _massUnit
|
val massUnit: LiveData<Mass> = _massUnit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the User weight goal
|
* the User weight goal
|
||||||
*/
|
*/
|
||||||
val goalWeight = config.getFloat(Settings.WEIGHT_GOAL).toLiveData()
|
val goalWeight = config.getFloat(Settings.WEIGHT_GOAL).toLiveData()
|
||||||
|
|
||||||
val dailyWaterIntake: Float = (config.getFloat("water_intake").value ?: 1200f) * waterUnit.modifier
|
private val _dailyWaterIntake = MutableLiveData<Int?>(null)
|
||||||
|
val dailyWaterIntake: LiveData<Int?> = _dailyWaterIntake
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Fetch today's water intake
|
// Fetch today's water intake
|
||||||
@ -95,15 +95,31 @@ class HomeViewModel @Inject internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config.getString(Settings.MASS_UNIT).apply {
|
config.getInt(Settings.MASS_UNIT).apply {
|
||||||
addObserver {
|
addObserver {
|
||||||
if (it == null) return@addObserver
|
if (it == null) return@addObserver
|
||||||
_massUnit.postValue(Units.Mass.find(it))
|
_massUnit.postValue(Mass.find(it))
|
||||||
}
|
}
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
_massUnit.postValue(Units.Mass.find(value!!))
|
_massUnit.postValue(Mass.find(value!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.getInt((Settings.VOLUME_UNIT)).apply {
|
||||||
|
addObserver {
|
||||||
|
if (it === null) return@addObserver
|
||||||
|
_waterUnit.postValue(Volume.find(it))
|
||||||
|
}
|
||||||
|
if (value != null) _waterUnit.postValue(Volume.find(value!!))
|
||||||
|
}
|
||||||
|
|
||||||
|
config.getInt(Settings.WATER_INTAKE_DAILY_GOAL).apply {
|
||||||
|
addObserver {
|
||||||
|
if (it === null) return@addObserver
|
||||||
|
_dailyWaterIntake.postValue((it * (_waterUnit.value?.modifier ?: 0f)).toInt())
|
||||||
|
}
|
||||||
|
if (value != null) _dailyWaterIntake.postValue((value!! * (_waterUnit.value?.modifier ?: 0f)).toInt())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateWater(water: Water) {
|
fun updateWater(water: Water) {
|
||||||
|
@ -13,9 +13,11 @@ import com.dzeio.openhealth.Application
|
|||||||
import com.dzeio.openhealth.BuildConfig
|
import com.dzeio.openhealth.BuildConfig
|
||||||
import com.dzeio.openhealth.R
|
import com.dzeio.openhealth.R
|
||||||
import com.dzeio.openhealth.Settings
|
import com.dzeio.openhealth.Settings
|
||||||
import com.dzeio.openhealth.units.Units
|
import com.dzeio.openhealth.units.Mass
|
||||||
|
import com.dzeio.openhealth.units.Volume
|
||||||
import com.dzeio.openhealth.utils.Configuration
|
import com.dzeio.openhealth.utils.Configuration
|
||||||
import com.dzeio.openhealth.utils.LocaleUtils
|
import com.dzeio.openhealth.utils.LocaleUtils
|
||||||
|
import com.dzeio.openhealth.utils.fields.IntEditTextPreference
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -48,11 +50,11 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||||||
val value = config.getFloat(Settings.WEIGHT_GOAL)
|
val value = config.getFloat(Settings.WEIGHT_GOAL)
|
||||||
setOnPreferenceClickListener {
|
setOnPreferenceClickListener {
|
||||||
if (value.value != null) {
|
if (value.value != null) {
|
||||||
val unit = config.getString(Settings.MASS_UNIT).value
|
val unit = config.getInt(Settings.MASS_UNIT).value
|
||||||
text = if (unit == null) {
|
text = if (unit == null) {
|
||||||
value.value!!.toString()
|
value.value!!.toString()
|
||||||
} else {
|
} else {
|
||||||
val modifier = Units.Mass.find(unit).modifier
|
val modifier = Mass.find(unit).modifier
|
||||||
(value.value!! * modifier).toString()
|
(value.value!! * modifier).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,10 +62,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
val unit = config.getString(Settings.MASS_UNIT).value
|
val unit = config.getInt(Settings.MASS_UNIT).value
|
||||||
var modifier = Units.Mass.KILOGRAM.modifier
|
var modifier = Mass.KILOGRAM.modifier
|
||||||
if (unit != null) {
|
if (unit != null) {
|
||||||
modifier = Units.Mass.find(unit).modifier
|
modifier = Mass.find(unit).modifier
|
||||||
}
|
}
|
||||||
|
|
||||||
value.value = ((newValue as String).toFloat() / modifier)
|
value.value = ((newValue as String).toFloat() / modifier)
|
||||||
@ -132,6 +134,52 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||||||
setDefaultValue(Locale.getDefault().language)
|
setDefaultValue(Locale.getDefault().language)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findPreference<ListPreference>("tmp." + Settings.VOLUME_UNIT)?.apply {
|
||||||
|
entries = Volume.values().map { getString(it.singular) }.toTypedArray()
|
||||||
|
entryValues = Volume.values().map { it.ordinal.toString() }.toTypedArray()
|
||||||
|
val unit = config.getInt(Settings.VOLUME_UNIT)
|
||||||
|
|
||||||
|
setOnPreferenceClickListener {
|
||||||
|
if (unit.value != null) setValueIndex(unit.value!!)
|
||||||
|
return@setOnPreferenceClickListener true
|
||||||
|
}
|
||||||
|
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
val nv = (newValue as String).toIntOrNull()
|
||||||
|
unit.value = nv
|
||||||
|
return@setOnPreferenceChangeListener false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<IntEditTextPreference>("tmp." + Settings.WATER_INTAKE_DAILY_GOAL)?.apply {
|
||||||
|
val value = config.getInt(Settings.WATER_INTAKE_DAILY_GOAL)
|
||||||
|
val unit = config.getInt(Settings.VOLUME_UNIT)
|
||||||
|
|
||||||
|
setOnPreferenceClickListener {
|
||||||
|
if (value.value == null) {
|
||||||
|
return@setOnPreferenceClickListener true
|
||||||
|
}
|
||||||
|
text = if (unit.value == null) {
|
||||||
|
value.value!!.toString()
|
||||||
|
} else {
|
||||||
|
Volume.find(unit.value!!).fromMilliliter(value.value!!).toString()
|
||||||
|
}
|
||||||
|
return@setOnPreferenceClickListener true
|
||||||
|
}
|
||||||
|
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
val nv = (newValue as String).toIntOrNull()
|
||||||
|
|
||||||
|
value.value = if (unit.value == null || nv == null) {
|
||||||
|
nv
|
||||||
|
} else {
|
||||||
|
Volume.find(unit.value!!).toMilliliter(nv)
|
||||||
|
}
|
||||||
|
|
||||||
|
return@setOnPreferenceChangeListener false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update App Locale
|
// Update App Locale
|
||||||
languagesPreference?.setOnPreferenceChangeListener { _, newValue ->
|
languagesPreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
LocaleUtils.setLanguage(requireContext(), newValue as String)
|
LocaleUtils.setLanguage(requireContext(), newValue as String)
|
||||||
|
@ -13,7 +13,6 @@ import com.dzeio.openhealth.adapters.ItemAdapter
|
|||||||
import com.dzeio.openhealth.core.BaseFragment
|
import com.dzeio.openhealth.core.BaseFragment
|
||||||
import com.dzeio.openhealth.data.water.Water
|
import com.dzeio.openhealth.data.water.Water
|
||||||
import com.dzeio.openhealth.databinding.FragmentMainWaterHomeBinding
|
import com.dzeio.openhealth.databinding.FragmentMainWaterHomeBinding
|
||||||
import com.dzeio.openhealth.units.Units
|
|
||||||
import com.dzeio.openhealth.utils.ChartUtils
|
import com.dzeio.openhealth.utils.ChartUtils
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@ -27,17 +26,18 @@ class WaterHomeFragment :
|
|||||||
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentMainWaterHomeBinding =
|
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentMainWaterHomeBinding =
|
||||||
FragmentMainWaterHomeBinding::inflate
|
FragmentMainWaterHomeBinding::inflate
|
||||||
|
|
||||||
|
private val adapter = ItemAdapter<Water>()
|
||||||
|
|
||||||
|
private val serie by lazy { BarSerie(binding.chart) }
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
viewModel.init()
|
|
||||||
|
|
||||||
val recycler = binding.list
|
val recycler = binding.list
|
||||||
|
|
||||||
val manager = LinearLayoutManager(requireContext())
|
recycler.layoutManager = LinearLayoutManager(requireContext())
|
||||||
recycler.layoutManager = manager
|
|
||||||
|
|
||||||
val adapter = ItemAdapter<Water>().apply {
|
adapter.apply {
|
||||||
onItemClick = {
|
onItemClick = {
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
WaterHomeFragmentDirections.actionNavWaterHomeToNavWaterEdit(
|
WaterHomeFragmentDirections.actionNavWaterHomeToNavWaterEdit(
|
||||||
@ -48,20 +48,16 @@ class WaterHomeFragment :
|
|||||||
recycler.adapter = this
|
recycler.adapter = this
|
||||||
}
|
}
|
||||||
|
|
||||||
val chart = binding.chart
|
binding.chart.apply {
|
||||||
|
serie
|
||||||
val serie = BarSerie(chart)
|
ChartUtils.materielTheme(this, requireView())
|
||||||
|
|
||||||
chart.apply {
|
|
||||||
ChartUtils.materielTheme(chart, requireView())
|
|
||||||
|
|
||||||
yAxis.apply {
|
yAxis.apply {
|
||||||
// onValueFormat
|
setYMin(0f)
|
||||||
}
|
}
|
||||||
|
|
||||||
xAxis.apply {
|
xAxis.apply {
|
||||||
dataWidth = 604800000.0
|
dataWidth = 604800000.0
|
||||||
textPaint.textSize = 32f
|
|
||||||
scrollEnabled = true
|
scrollEnabled = true
|
||||||
onValueFormat = onValueFormat@{
|
onValueFormat = onValueFormat@{
|
||||||
return@onValueFormat SimpleDateFormat(
|
return@onValueFormat SimpleDateFormat(
|
||||||
@ -79,14 +75,33 @@ class WaterHomeFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.items.observe(viewLifecycleOwner) { list ->
|
viewModel.items.observe(viewLifecycleOwner) { list ->
|
||||||
val unit = Units.Volume.MILLILITER
|
updateData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateData() {
|
||||||
|
val data = viewModel.items.value
|
||||||
|
val unit = viewModel.unit.value
|
||||||
|
|
||||||
|
if (unit == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.isNullOrEmpty()) {
|
||||||
|
adapter.clear()
|
||||||
|
serie.entries = arrayListOf()
|
||||||
|
binding.chart.refresh()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update adapter
|
||||||
adapter.set(
|
adapter.set(
|
||||||
list.map {
|
data.map {
|
||||||
ItemAdapter.Item(
|
ItemAdapter.Item(
|
||||||
it,
|
it,
|
||||||
getString(
|
getString(
|
||||||
unit.unit,
|
unit.unit,
|
||||||
unit.formatToString(it.value)
|
unit.fromMilliliter(it.value)
|
||||||
),
|
),
|
||||||
it.formatTimestamp(),
|
it.formatTimestamp(),
|
||||||
icon = R.drawable.ic_outline_edit_24
|
icon = R.drawable.ic_outline_edit_24
|
||||||
@ -94,22 +109,16 @@ class WaterHomeFragment :
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
// update graph
|
||||||
return@observe
|
val dataset = data.map {
|
||||||
}
|
|
||||||
|
|
||||||
val dataset = list.map {
|
|
||||||
return@map Entry(
|
return@map Entry(
|
||||||
it.timestamp.toDouble(),
|
it.timestamp.toDouble(),
|
||||||
it.value.toFloat()
|
unit.fromMilliliter(it.value).toFloat()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
serie.entries = dataset as ArrayList<Entry>
|
serie.entries = dataset as ArrayList<Entry>
|
||||||
chart.xAxis.x = chart.xAxis.getXMin()
|
binding.chart.xAxis.x = 0.0
|
||||||
chart.xAxis.x =
|
binding.chart.refresh()
|
||||||
chart.xAxis.getXMax() - chart.xAxis.dataWidth!! + chart.xAxis.dataWidth!! / 7
|
|
||||||
chart.refresh()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
package com.dzeio.openhealth.ui.water
|
package com.dzeio.openhealth.ui.water
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.dzeio.openhealth.Settings
|
||||||
import com.dzeio.openhealth.core.BaseViewModel
|
import com.dzeio.openhealth.core.BaseViewModel
|
||||||
import com.dzeio.openhealth.data.water.Water
|
import com.dzeio.openhealth.data.water.Water
|
||||||
import com.dzeio.openhealth.data.water.WaterRepository
|
import com.dzeio.openhealth.data.water.WaterRepository
|
||||||
|
import com.dzeio.openhealth.units.Volume
|
||||||
|
import com.dzeio.openhealth.utils.Configuration
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
@ -12,15 +16,25 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class WaterHomeViewModel@Inject internal constructor(
|
class WaterHomeViewModel@Inject internal constructor(
|
||||||
private val waterRepository: WaterRepository
|
private val waterRepository: WaterRepository,
|
||||||
|
config: Configuration
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
val items: MutableLiveData<List<Water>> = MutableLiveData()
|
val items: MutableLiveData<List<Water>> = MutableLiveData()
|
||||||
|
|
||||||
fun init() {
|
private val _unit = MutableLiveData<Volume?>()
|
||||||
|
val unit: LiveData<Volume?> = _unit
|
||||||
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
waterRepository.getWaters().collectLatest {
|
waterRepository.getWaters().collectLatest {
|
||||||
items.postValue(it)
|
items.postValue(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
config.getInt((Settings.VOLUME_UNIT)).apply {
|
||||||
|
addObserver {
|
||||||
|
if (it === null) return@addObserver
|
||||||
|
_unit.postValue(Volume.find(it))
|
||||||
|
}
|
||||||
|
if (value != null) _unit.postValue(Volume.find(value!!))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import com.dzeio.openhealth.R
|
|||||||
import com.dzeio.openhealth.Settings
|
import com.dzeio.openhealth.Settings
|
||||||
import com.dzeio.openhealth.core.BaseDialog
|
import com.dzeio.openhealth.core.BaseDialog
|
||||||
import com.dzeio.openhealth.databinding.DialogWaterSizeSelectorBinding
|
import com.dzeio.openhealth.databinding.DialogWaterSizeSelectorBinding
|
||||||
|
import com.dzeio.openhealth.units.Volume
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -30,14 +31,30 @@ class WaterSizeSelectorDialog :
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.cupSize.observe(this) {
|
viewModel.cupSize.observe(this) {
|
||||||
var real = it ?: Settings.WATER_INTAKE_SIZE_DEFAULT
|
setCustomSizeText()
|
||||||
binding.customSize.text = String.format(
|
|
||||||
getString(R.string.custom_amount),
|
|
||||||
"${real}ml"
|
|
||||||
)
|
|
||||||
if (binding.inputParent.visibility == View.GONE) {
|
|
||||||
binding.input.setText(real.toString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.unit.observe(this) {
|
||||||
|
if (it == null) {
|
||||||
|
return@observe
|
||||||
|
}
|
||||||
|
setCustomSizeText()
|
||||||
|
binding.size1000ml.text = getString(
|
||||||
|
it.unit,
|
||||||
|
it.fromMilliliter(1000)
|
||||||
|
)
|
||||||
|
binding.size100ml.text = getString(
|
||||||
|
it.unit,
|
||||||
|
it.fromMilliliter(100)
|
||||||
|
)
|
||||||
|
binding.size250ml.text = getString(
|
||||||
|
it.unit,
|
||||||
|
it.fromMilliliter(250)
|
||||||
|
)
|
||||||
|
binding.size500ml.text = getString(
|
||||||
|
it.unit,
|
||||||
|
it.fromMilliliter(500)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.size100ml.setOnClickListener {
|
binding.size100ml.setOnClickListener {
|
||||||
@ -61,10 +78,11 @@ class WaterSizeSelectorDialog :
|
|||||||
setTextFieldStatus(true)
|
setTextFieldStatus(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.input.doOnTextChanged { text, start, before, count ->
|
binding.input.doOnTextChanged { text, _, _, _ ->
|
||||||
val newSize = text.toString().toIntOrNull()
|
val newSize = text.toString().toIntOrNull()
|
||||||
if (newSize != null) {
|
if (newSize != null && binding.inputParent.visibility == View.VISIBLE) {
|
||||||
viewModel.setCupSize(newSize)
|
val unit = viewModel.unit.value ?: Volume.MILLILITER
|
||||||
|
viewModel.setCupSize(unit.toMilliliter(newSize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,4 +91,22 @@ class WaterSizeSelectorDialog :
|
|||||||
binding.inputParent.visibility = if (displayed) View.VISIBLE else View.GONE
|
binding.inputParent.visibility = if (displayed) View.VISIBLE else View.GONE
|
||||||
binding.customSize.visibility = if (displayed) View.GONE else View.VISIBLE
|
binding.customSize.visibility = if (displayed) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setCustomSizeText() {
|
||||||
|
val size = viewModel.cupSize.value ?: Settings.WATER_INTAKE_SIZE_DEFAULT
|
||||||
|
val unit = viewModel.unit.value ?: Volume.MILLILITER
|
||||||
|
|
||||||
|
val modified = unit.fromMilliliter(size)
|
||||||
|
|
||||||
|
binding.customSize.text = String.format(
|
||||||
|
getString(
|
||||||
|
R.string.custom_amount,
|
||||||
|
getString(unit.unit, modified)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (binding.inputParent.visibility == View.GONE) {
|
||||||
|
binding.input.setText(modified.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package com.dzeio.openhealth.ui.water
|
package com.dzeio.openhealth.ui.water
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import com.dzeio.openhealth.Settings
|
import com.dzeio.openhealth.Settings
|
||||||
import com.dzeio.openhealth.core.BaseViewModel
|
import com.dzeio.openhealth.core.BaseViewModel
|
||||||
|
import com.dzeio.openhealth.units.Volume
|
||||||
import com.dzeio.openhealth.utils.Configuration
|
import com.dzeio.openhealth.utils.Configuration
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -12,8 +15,20 @@ class WaterSizeSelectorViewModel @Inject constructor(
|
|||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
val cupSize = settings.getInt(Settings.WATER_INTAKE_SIZE).toLiveData()
|
val cupSize = settings.getInt(Settings.WATER_INTAKE_SIZE).toLiveData()
|
||||||
|
private val _unit = MutableLiveData<Volume?>()
|
||||||
|
val unit: LiveData<Volume?> = _unit
|
||||||
|
|
||||||
fun setCupSize(value: Int) {
|
fun setCupSize(value: Int) {
|
||||||
settings.getInt(Settings.WATER_INTAKE_SIZE).value = value
|
settings.getInt(Settings.WATER_INTAKE_SIZE).value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
settings.getInt(Settings.VOLUME_UNIT).apply {
|
||||||
|
addObserver {
|
||||||
|
if (it === null) return@addObserver
|
||||||
|
_unit.postValue(Volume.find(it))
|
||||||
|
}
|
||||||
|
if (value != null) _unit.postValue(Volume.find(value!!))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import com.dzeio.openhealth.core.BaseViewModel
|
|||||||
import com.dzeio.openhealth.data.water.Water
|
import com.dzeio.openhealth.data.water.Water
|
||||||
import com.dzeio.openhealth.data.weight.Weight
|
import com.dzeio.openhealth.data.weight.Weight
|
||||||
import com.dzeio.openhealth.data.weight.WeightRepository
|
import com.dzeio.openhealth.data.weight.WeightRepository
|
||||||
import com.dzeio.openhealth.units.Units
|
import com.dzeio.openhealth.units.Mass
|
||||||
import com.dzeio.openhealth.utils.Configuration
|
import com.dzeio.openhealth.utils.Configuration
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -30,7 +30,7 @@ class EditWeightDialogViewModel @Inject internal constructor(
|
|||||||
|
|
||||||
private val _weights = MutableLiveData<List<Weight>?>(null)
|
private val _weights = MutableLiveData<List<Weight>?>(null)
|
||||||
|
|
||||||
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
|
private val _massUnit = MutableLiveData(Mass.KILOGRAM)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
@ -41,13 +41,13 @@ class EditWeightDialogViewModel @Inject internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config.getString(Settings.MASS_UNIT).apply {
|
config.getInt(Settings.MASS_UNIT).apply {
|
||||||
addObserver {
|
addObserver {
|
||||||
if (it == null) return@addObserver
|
if (it == null) return@addObserver
|
||||||
_massUnit.postValue(Units.Mass.find(it))
|
_massUnit.postValue(Mass.find(it))
|
||||||
}
|
}
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
_massUnit.postValue(Units.Mass.find(value!!))
|
_massUnit.postValue(Mass.find(value!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.dzeio.openhealth.ui.weight
|
|||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
@ -25,7 +26,7 @@ import com.dzeio.openhealth.adapters.ItemAdapter
|
|||||||
import com.dzeio.openhealth.core.BaseFragment
|
import com.dzeio.openhealth.core.BaseFragment
|
||||||
import com.dzeio.openhealth.data.weight.Weight
|
import com.dzeio.openhealth.data.weight.Weight
|
||||||
import com.dzeio.openhealth.databinding.FragmentListWeightBinding
|
import com.dzeio.openhealth.databinding.FragmentListWeightBinding
|
||||||
import com.dzeio.openhealth.units.Units
|
import com.dzeio.openhealth.units.Mass
|
||||||
import com.dzeio.openhealth.utils.ChartUtils
|
import com.dzeio.openhealth.utils.ChartUtils
|
||||||
import com.dzeio.openhealth.utils.PermissionsUtils
|
import com.dzeio.openhealth.utils.PermissionsUtils
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
@ -99,16 +100,22 @@ class ListWeightFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.bluetoothButton.setOnClickListener {
|
binding.bluetoothButton.setOnClickListener {
|
||||||
val permissions = arrayOf(
|
val permissions = arrayListOf(
|
||||||
Manifest.permission.BLUETOOTH,
|
Manifest.permission.BLUETOOTH,
|
||||||
Manifest.permission.BLUETOOTH_CONNECT,
|
|
||||||
Manifest.permission.BLUETOOTH_SCAN,
|
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION
|
Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
)
|
)
|
||||||
val hasPermission = PermissionsUtils.hasPermission(requireContext(), permissions)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
permissions.addAll(
|
||||||
|
arrayOf(
|
||||||
|
Manifest.permission.BLUETOOTH_CONNECT,
|
||||||
|
Manifest.permission.BLUETOOTH_SCAN
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val hasPermission = PermissionsUtils.hasPermission(requireContext(), permissions.toTypedArray())
|
||||||
if (!hasPermission) {
|
if (!hasPermission) {
|
||||||
button = binding.bluetoothButton
|
button = binding.bluetoothButton
|
||||||
activityResult.launch(permissions)
|
activityResult.launch(permissions.toTypedArray())
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
@ -140,16 +147,20 @@ class ListWeightFragment :
|
|||||||
updateGraph(list, it)
|
updateGraph(list, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.massUnit.observe(viewLifecycleOwner) { unit ->
|
||||||
|
binding.chart.yAxis.onValueFormat = { getString(unit.unit, unit.fromKilogram(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.weights.observe(viewLifecycleOwner) { list ->
|
viewModel.weights.observe(viewLifecycleOwner) { list ->
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
val unit = viewModel.massUnit.value ?: Units.Mass.KILOGRAM
|
val unit = viewModel.massUnit.value ?: Mass.KILOGRAM
|
||||||
adapter.set(
|
adapter.set(
|
||||||
list.map {
|
list.map {
|
||||||
ItemAdapter.Item(
|
ItemAdapter.Item(
|
||||||
it,
|
it,
|
||||||
getString(
|
getString(
|
||||||
unit.unit,
|
unit.unit,
|
||||||
unit.formatToString(it.weight)
|
it.weight
|
||||||
),
|
),
|
||||||
getString(
|
getString(
|
||||||
R.string.weight_item,
|
R.string.weight_item,
|
||||||
@ -185,8 +196,6 @@ class ListWeightFragment :
|
|||||||
|
|
||||||
yAxis.apply {
|
yAxis.apply {
|
||||||
setYMin(null)
|
setYMin(null)
|
||||||
|
|
||||||
onValueFormat = { value -> "${value.toInt()}" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xAxis.apply {
|
xAxis.apply {
|
||||||
@ -228,8 +237,6 @@ class ListWeightFragment :
|
|||||||
val serie = chart.series[0] as LineSerie
|
val serie = chart.series[0] as LineSerie
|
||||||
val avSerie = chart.series[1] as LineSerie
|
val avSerie = chart.series[1] as LineSerie
|
||||||
|
|
||||||
val entries: ArrayList<Entry> = arrayListOf()
|
|
||||||
|
|
||||||
val previous = 5
|
val previous = 5
|
||||||
val next = 5
|
val next = 5
|
||||||
val averageList = arrayListOf<Entry>()
|
val averageList = arrayListOf<Entry>()
|
||||||
@ -245,6 +252,13 @@ class ListWeightFragment :
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val entries: ArrayList<Entry> = list.map {
|
||||||
|
Entry(
|
||||||
|
it.timestamp.toDouble(),
|
||||||
|
it.weight
|
||||||
|
)
|
||||||
|
} as ArrayList<Entry>
|
||||||
|
|
||||||
val direction = averageList.last().y - averageList[averageList.size - 2].y
|
val direction = averageList.last().y - averageList[averageList.size - 2].y
|
||||||
|
|
||||||
chart.yAxis.clearLines()
|
chart.yAxis.clearLines()
|
||||||
@ -257,39 +271,30 @@ class ListWeightFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
val dt = averageList.last().x - averageList[list.size - previous].x
|
val dt = averageList.last().x - averageList[list.size - previous].x
|
||||||
val timeUntilGoal = ((list.last().weight - goal) / abs(direction)).toLong() * dt
|
val timeUntilGoal = ((entries.last().y - goal) / abs(direction)).toLong() * dt
|
||||||
|
|
||||||
binding.goalText.text = getString(
|
binding.goalText.text = getString(
|
||||||
R.string.days_until_goal_is_achieved,
|
R.string.days_until_goal_is_achieved,
|
||||||
(timeUntilGoal / 1000 / 60 / 60 / 24).toInt()
|
(timeUntilGoal / 1000 / 60 / 60 / 24).toInt()
|
||||||
)
|
)
|
||||||
averageList.add(
|
entries.add(
|
||||||
Entry(
|
Entry(
|
||||||
(list.last().timestamp + timeUntilGoal),
|
(entries.last().x + timeUntilGoal),
|
||||||
goal
|
goal
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
binding.goalText.visibility = View.VISIBLE
|
binding.goalText.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
averageList.add(
|
entries.add(
|
||||||
Entry(
|
Entry(
|
||||||
averageList.last().x + chart.xAxis.dataWidth!!,
|
entries.last().x + chart.xAxis.dataWidth!!,
|
||||||
averageList.last().y + direction * 7 * 4
|
entries.last().y + direction * 7 * 4
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
binding.goalText.visibility = View.GONE
|
binding.goalText.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
avSerie.entries = averageList
|
avSerie.entries = averageList
|
||||||
|
|
||||||
list.forEach {
|
|
||||||
entries.add(
|
|
||||||
Entry(
|
|
||||||
it.timestamp.toDouble(),
|
|
||||||
it.weight
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
serie.entries = entries
|
serie.entries = entries
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
|
@ -7,7 +7,7 @@ import com.dzeio.openhealth.Settings
|
|||||||
import com.dzeio.openhealth.core.BaseViewModel
|
import com.dzeio.openhealth.core.BaseViewModel
|
||||||
import com.dzeio.openhealth.data.weight.Weight
|
import com.dzeio.openhealth.data.weight.Weight
|
||||||
import com.dzeio.openhealth.data.weight.WeightRepository
|
import com.dzeio.openhealth.data.weight.WeightRepository
|
||||||
import com.dzeio.openhealth.units.Units
|
import com.dzeio.openhealth.units.Mass
|
||||||
import com.dzeio.openhealth.utils.Configuration
|
import com.dzeio.openhealth.utils.Configuration
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -21,8 +21,8 @@ class ListWeightViewModel @Inject internal constructor(
|
|||||||
settings: Configuration
|
settings: Configuration
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
|
private val _massUnit = MutableLiveData(Mass.KILOGRAM)
|
||||||
val massUnit: LiveData<Units.Mass> = _massUnit
|
val massUnit: LiveData<Mass> = _massUnit
|
||||||
|
|
||||||
private val _goalWeight = settings.getFloat(Settings.WEIGHT_GOAL)
|
private val _goalWeight = settings.getFloat(Settings.WEIGHT_GOAL)
|
||||||
val goalWeight = _goalWeight.toLiveData()
|
val goalWeight = _goalWeight.toLiveData()
|
||||||
@ -37,13 +37,13 @@ class ListWeightViewModel @Inject internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.getString(Settings.MASS_UNIT).apply {
|
settings.getInt(Settings.MASS_UNIT).apply {
|
||||||
addObserver {
|
addObserver {
|
||||||
if (it == null) return@addObserver
|
if (it == null) return@addObserver
|
||||||
_massUnit.postValue(Units.Mass.find(it))
|
_massUnit.postValue(Mass.find(it))
|
||||||
}
|
}
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
_massUnit.postValue(Units.Mass.find(value!!))
|
_massUnit.postValue(Mass.find(value!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ class ScanScalesDialog :
|
|||||||
override val bindingInflater: (LayoutInflater) -> DialogSearchBinding =
|
override val bindingInflater: (LayoutInflater) -> DialogSearchBinding =
|
||||||
DialogSearchBinding::inflate
|
DialogSearchBinding::inflate
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
override fun onBuilderInit(builder: MaterialAlertDialogBuilder) {
|
override fun onBuilderInit(builder: MaterialAlertDialogBuilder) {
|
||||||
super.onBuilderInit(builder)
|
super.onBuilderInit(builder)
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ class ScanScalesDialog :
|
|||||||
it,
|
it,
|
||||||
it.name,
|
it.name,
|
||||||
"${it.item!!.name} (${it.item!!.address})",
|
"${it.item!!.name} (${it.item!!.address})",
|
||||||
icon = R.drawable.ic_baseline_add_24
|
icon = R.drawable.vector_add
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -8,12 +8,12 @@ import com.dzeio.openhealth.core.BaseViewModel
|
|||||||
import com.dzeio.openhealth.data.weight.Weight
|
import com.dzeio.openhealth.data.weight.Weight
|
||||||
import com.dzeio.openhealth.data.weight.WeightRepository
|
import com.dzeio.openhealth.data.weight.WeightRepository
|
||||||
import com.dzeio.openhealth.units.ActivityLevel
|
import com.dzeio.openhealth.units.ActivityLevel
|
||||||
import com.dzeio.openhealth.units.Units
|
import com.dzeio.openhealth.units.Mass
|
||||||
import com.dzeio.openhealth.utils.Configuration
|
import com.dzeio.openhealth.utils.Configuration
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class WeightDialogViewModel @Inject internal constructor(
|
class WeightDialogViewModel @Inject internal constructor(
|
||||||
@ -33,7 +33,7 @@ class WeightDialogViewModel @Inject internal constructor(
|
|||||||
val weight: LiveData<Weight?> = _weight
|
val weight: LiveData<Weight?> = _weight
|
||||||
|
|
||||||
val format =
|
val format =
|
||||||
Units.Mass.find(settings.getString(Settings.MASS_UNIT).value ?: Units.Mass.KILOGRAM.id)
|
Mass.find(settings.getInt(Settings.MASS_UNIT).value ?: Mass.KILOGRAM.ordinal)
|
||||||
|
|
||||||
fun initWithWeight(id: Long?) {
|
fun initWithWeight(id: Long?) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
48
app/src/main/java/com/dzeio/openhealth/units/Mass.kt
Normal file
48
app/src/main/java/com/dzeio/openhealth/units/Mass.kt
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package com.dzeio.openhealth.units
|
||||||
|
|
||||||
|
import com.dzeio.openhealth.R
|
||||||
|
|
||||||
|
enum class Mass(
|
||||||
|
/**
|
||||||
|
* Value based on the Kilogram
|
||||||
|
*/
|
||||||
|
val modifier: Float,
|
||||||
|
val singular: Int,
|
||||||
|
val plural: Int,
|
||||||
|
val unit: Int
|
||||||
|
) {
|
||||||
|
KILOGRAM(
|
||||||
|
1f,
|
||||||
|
R.string.unit_mass_kilogram_name_singular,
|
||||||
|
R.string.unit_mass_kilogram_name_plural,
|
||||||
|
R.string.unit_mass_kilogram_unit
|
||||||
|
),
|
||||||
|
POUND(
|
||||||
|
2.204623f,
|
||||||
|
R.string.unit_mass_pound_name_singular,
|
||||||
|
R.string.unit_mass_pound_name_plural,
|
||||||
|
R.string.unit_mass_pound_unit
|
||||||
|
);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun find(index: Int): Mass {
|
||||||
|
return Mass.values().getOrNull(index) ?: KILOGRAM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun format(value: Float): Float {
|
||||||
|
return value * modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transform the value from the specified unit to kilograms
|
||||||
|
*/
|
||||||
|
fun toKilogram(value: Float): Float = value / modifier
|
||||||
|
fun toKilogram(value: Int): Int = toKilogram(value.toFloat()).toInt()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transform the value from the specified unit to kilograms
|
||||||
|
*/
|
||||||
|
fun fromKilogram(value: Float): Float = value * modifier
|
||||||
|
fun fromKilogram(value: Int): Int = fromKilogram(value.toFloat()).toInt()
|
||||||
|
}
|
@ -1,104 +0,0 @@
|
|||||||
package com.dzeio.openhealth.units
|
|
||||||
|
|
||||||
import com.dzeio.openhealth.R
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object containing the differents units and how they are converted
|
|
||||||
*/
|
|
||||||
object Units {
|
|
||||||
/**
|
|
||||||
* the Mass Unit
|
|
||||||
*/
|
|
||||||
enum class Mass(
|
|
||||||
val id: String,
|
|
||||||
/**
|
|
||||||
* Value based on the Kilogram
|
|
||||||
*/
|
|
||||||
val modifier: Float,
|
|
||||||
val singular: Int,
|
|
||||||
val plural: Int,
|
|
||||||
val unit: Int
|
|
||||||
) {
|
|
||||||
KILOGRAM(
|
|
||||||
"kg",
|
|
||||||
1f,
|
|
||||||
R.string.unit_mass_kilogram_name_singular,
|
|
||||||
R.string.unit_mass_kilogram_name_plural,
|
|
||||||
R.string.unit_mass_kilogram_unit
|
|
||||||
),
|
|
||||||
POUND(
|
|
||||||
"lbs",
|
|
||||||
2.204623f,
|
|
||||||
R.string.unit_mass_pound_name_singular,
|
|
||||||
R.string.unit_mass_pound_name_plural,
|
|
||||||
R.string.unit_mass_pound_unit
|
|
||||||
);
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun find(value: String): Mass {
|
|
||||||
return Mass.values().find {
|
|
||||||
it.id == value
|
|
||||||
} ?: KILOGRAM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun format(value: Float): Float {
|
|
||||||
return value * modifier
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format the value and let the hundred of grams to be outputed
|
|
||||||
*/
|
|
||||||
fun formatToString(value: Float): String {
|
|
||||||
return String.format("%.1f", value * modifier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the Volume unit
|
|
||||||
*/
|
|
||||||
enum class Volume(
|
|
||||||
val id: String,
|
|
||||||
/**
|
|
||||||
* Value based on the Milliliter
|
|
||||||
*/
|
|
||||||
val modifier: Float,
|
|
||||||
val singular: Int,
|
|
||||||
val plural: Int,
|
|
||||||
val unit: Int
|
|
||||||
) {
|
|
||||||
MILLILITER(
|
|
||||||
"ml",
|
|
||||||
1f,
|
|
||||||
R.string.unit_volume_milliliter_name_singular,
|
|
||||||
R.string.unit_volume_milliliter_name_plural,
|
|
||||||
R.string.unit_volume_milliliter_unit
|
|
||||||
),
|
|
||||||
IMPERIAL_OUNCE(
|
|
||||||
"ioz",
|
|
||||||
0.03519503f,
|
|
||||||
R.string.unit_volume_imperial_ounce_name_singular,
|
|
||||||
R.string.unit_volume_imperial_ounce_name_plural,
|
|
||||||
R.string.unit_volume_ounce_unit
|
|
||||||
),
|
|
||||||
US_OUNCE(
|
|
||||||
"uoz",
|
|
||||||
0.03381413f,
|
|
||||||
R.string.unit_volume_us_ounce_name_singular,
|
|
||||||
R.string.unit_volume_us_ounce_name_plural,
|
|
||||||
R.string.unit_volume_ounce_unit
|
|
||||||
);
|
|
||||||
|
|
||||||
fun formatToString(value: Int): String {
|
|
||||||
return String.format("%.0f", (value * modifier))
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun find(value: String): Volume {
|
|
||||||
return Volume.values().find {
|
|
||||||
it.id == value
|
|
||||||
} ?: MILLILITER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
53
app/src/main/java/com/dzeio/openhealth/units/Volume.kt
Normal file
53
app/src/main/java/com/dzeio/openhealth/units/Volume.kt
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package com.dzeio.openhealth.units
|
||||||
|
|
||||||
|
import com.dzeio.openhealth.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the Volume unit
|
||||||
|
*/
|
||||||
|
enum class Volume(
|
||||||
|
/**
|
||||||
|
* Value based on the Milliliter
|
||||||
|
*/
|
||||||
|
val modifier: Float,
|
||||||
|
val singular: Int,
|
||||||
|
val plural: Int,
|
||||||
|
val unit: Int
|
||||||
|
) {
|
||||||
|
MILLILITER(
|
||||||
|
1f,
|
||||||
|
R.string.unit_volume_milliliter_name_singular,
|
||||||
|
R.string.unit_volume_milliliter_name_plural,
|
||||||
|
R.string.unit_volume_milliliter_unit
|
||||||
|
),
|
||||||
|
IMPERIAL_OUNCE(
|
||||||
|
0.03519503f,
|
||||||
|
R.string.unit_volume_imperial_ounce_name_singular,
|
||||||
|
R.string.unit_volume_imperial_ounce_name_plural,
|
||||||
|
R.string.unit_volume_ounce_unit
|
||||||
|
),
|
||||||
|
US_OUNCE(
|
||||||
|
0.03381413f,
|
||||||
|
R.string.unit_volume_us_ounce_name_singular,
|
||||||
|
R.string.unit_volume_us_ounce_name_plural,
|
||||||
|
R.string.unit_volume_ounce_unit
|
||||||
|
);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun find(index: Int): Volume {
|
||||||
|
return Volume.values().getOrNull(index) ?: MILLILITER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transform the value from the specified unit to kilograms
|
||||||
|
*/
|
||||||
|
fun toMilliliter(value: Float): Float = value / modifier
|
||||||
|
fun toMilliliter(value: Int): Int = toMilliliter(value.toFloat()).toInt()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transform the value from the specified unit to kilograms
|
||||||
|
*/
|
||||||
|
fun fromMilliliter(value: Float): Float = value * modifier
|
||||||
|
fun fromMilliliter(value: Int): Int = fromMilliliter(value.toFloat()).toInt()
|
||||||
|
}
|
@ -2,7 +2,6 @@ package com.dzeio.openhealth.utils
|
|||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import com.dzeio.openhealth.Application
|
|
||||||
import com.dzeio.openhealth.core.Observable
|
import com.dzeio.openhealth.core.Observable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,7 +16,7 @@ class Configuration(
|
|||||||
private val cache: HashMap<String, Field<*>> = HashMap()
|
private val cache: HashMap<String, Field<*>> = HashMap()
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val TAG = "${Application.TAG}/Config"
|
const val TAG = "Configuration"
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -145,10 +144,12 @@ class Configuration(
|
|||||||
) : Field<Int?>(defaultValue) {
|
) : Field<Int?>(defaultValue) {
|
||||||
override fun exists(): Boolean = prefs.contains(key)
|
override fun exists(): Boolean = prefs.contains(key)
|
||||||
override fun internalGet(): Int? {
|
override fun internalGet(): Int? {
|
||||||
if (exists()) {
|
return try {
|
||||||
return prefs.getInt(key, 0)
|
prefs.getInt(key, 0)
|
||||||
|
} catch (e: ClassCastException) {
|
||||||
|
val it = prefs.getString(key, "")
|
||||||
|
it?.toIntOrNull() ?: defaultValue
|
||||||
}
|
}
|
||||||
return defaultValue
|
|
||||||
}
|
}
|
||||||
override fun internalSet(value: Int?) =
|
override fun internalSet(value: Int?) =
|
||||||
prefs.edit { if (value == null) remove(key) else putInt(key, value) }
|
prefs.edit { if (value == null) remove(key) else putInt(key, value) }
|
||||||
|
5
app/src/main/res/drawable/vector_remove.xml
Normal file
5
app/src/main/res/drawable/vector_remove.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19,13H5v-2h14v2z"/>
|
||||||
|
</vector>
|
@ -29,7 +29,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="Activity"
|
android:text="@string/activity"
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -69,7 +69,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="4dp"
|
android:paddingBottom="4dp"
|
||||||
android:text="Steps" />
|
android:text="@string/steps" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -94,13 +94,13 @@
|
|||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:src="@drawable/ic_baseline_add_24" />
|
android:src="@drawable/vector_add" />
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="Vitals"
|
android:text="@string/vitals"
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -138,14 +138,14 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Heart Rate"
|
android:text="@string/heart_rate"
|
||||||
android:textColor="?attr/colorSurfaceInverse" />
|
android:textColor="?attr/colorSurfaceInverse" />
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Coming soon"
|
android:text="@string/coming_soon"
|
||||||
android:textColor="?attr/colorSurfaceInverse" />
|
android:textColor="?attr/colorSurfaceInverse" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -169,7 +169,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="Measurements"
|
android:text="@string/measurements"
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -207,7 +207,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Weight" />
|
android:text="@string/weight" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -256,13 +256,13 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="?attr/colorSurfaceInverse"
|
android:textColor="?attr/colorSurfaceInverse"
|
||||||
android:paddingBottom="4dp"
|
android:paddingBottom="4dp"
|
||||||
android:text="Height" />
|
android:text="@string/height" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="?attr/colorSurfaceInverse"
|
android:textColor="?attr/colorSurfaceInverse"
|
||||||
android:text="Coming soon" />
|
android:text="@string/coming_soon" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@ -285,7 +285,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="Food"
|
android:text="@string/food"
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -323,7 +323,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Water Intake" />
|
android:text="@string/water_intake" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@ -364,7 +364,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Food Calories" />
|
android:text="@string/food_consumption" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
style="?attr/materialCardViewFilledStyle"
|
style="?attr/materialCardViewFilledStyle"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
|
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1">
|
android:layout_weight="1">
|
||||||
@ -72,7 +72,7 @@
|
|||||||
android:layout_height="18dp"
|
android:layout_height="18dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:src="@drawable/ic_outline_hexagon_24"
|
android:src="@drawable/vector_remove"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/linearLayout"
|
app:layout_constraintBottom_toBottomOf="@+id/linearLayout"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/linearLayout"
|
app:layout_constraintEnd_toStartOf="@+id/linearLayout"
|
||||||
app:layout_constraintTop_toTopOf="@+id/linearLayout" />
|
app:layout_constraintTop_toTopOf="@+id/linearLayout" />
|
||||||
@ -103,6 +103,8 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
android:id="@+id/fragment_home_water_total"
|
android:id="@+id/fragment_home_water_total"
|
||||||
style="@style/TextAppearance.Material3.LabelMedium"
|
style="@style/TextAppearance.Material3.LabelMedium"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -120,7 +122,7 @@
|
|||||||
android:layout_height="18dp"
|
android:layout_height="18dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:src="@drawable/ic_baseline_add_24"
|
android:src="@drawable/vector_add"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/linearLayout"
|
app:layout_constraintBottom_toBottomOf="@+id/linearLayout"
|
||||||
app:layout_constraintStart_toEndOf="@+id/linearLayout"
|
app:layout_constraintStart_toEndOf="@+id/linearLayout"
|
||||||
app:layout_constraintTop_toTopOf="@+id/linearLayout" />
|
app:layout_constraintTop_toTopOf="@+id/linearLayout" />
|
||||||
@ -130,7 +132,7 @@
|
|||||||
android:id="@+id/background"
|
android:id="@+id/background"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:src="@drawable/ic_outline_hexagon_24"
|
tools:src="@drawable/ic_outline_hexagon_24"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintDimensionRatio="2:1"
|
app:layout_constraintDimensionRatio="2:1"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
@ -145,7 +147,7 @@
|
|||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
style="?attr/materialCardViewFilledStyle"
|
style="?attr/materialCardViewFilledStyle"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1">
|
android:layout_weight="1">
|
||||||
|
|
||||||
@ -225,6 +227,8 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="@string/unit_volume_milliliter_unit"
|
android:text="@string/unit_volume_milliliter_unit"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
android:textColor="?attr/colorOnBackground" />
|
android:textColor="?attr/colorOnBackground" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@ -298,7 +302,7 @@
|
|||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:src="@drawable/ic_baseline_add_24" />
|
android:src="@drawable/vector_add" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/list_weight"
|
android:id="@+id/list_weight"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/action_add"
|
android:id="@+id/action_add"
|
||||||
android:visible="false"
|
android:visible="false"
|
||||||
android:icon="@drawable/ic_baseline_add_24"
|
android:icon="@drawable/vector_add"
|
||||||
android:title="@string/add"
|
android:title="@string/add"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
@ -170,9 +170,9 @@
|
|||||||
</dialog>
|
</dialog>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/foodHomeFragment"
|
android:id="@+id/foodHomeFragment"
|
||||||
tools:layout="@layout/fragment_food_home"
|
|
||||||
android:name="com.dzeio.openhealth.ui.food.FoodHomeFragment"
|
android:name="com.dzeio.openhealth.ui.food.FoodHomeFragment"
|
||||||
android:label="FoodHomeFragment" >
|
android:label="@string/food_consumption"
|
||||||
|
tools:layout="@layout/fragment_food_home">
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_foodHomeFragment_to_nav_dialog_food_search"
|
android:id="@+id/action_foodHomeFragment_to_nav_dialog_food_search"
|
||||||
app:destination="@id/nav_dialog_food_search" />
|
app:destination="@id/nav_dialog_food_search" />
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<string name="tagline">Ton Application de santé libre, open source et respectueuse de la vie privée</string>
|
<string name="tagline">Ton Application de santé libre, open source et respectueuse de la vie privée</string>
|
||||||
<string name="add">Ajouter</string>
|
<string name="add">Ajouter</string>
|
||||||
<string name="about">A Propos</string>
|
<string name="about">A Propos</string>
|
||||||
<string name="version_number" formatted="false">Version %1$</string>
|
<string name="version_number" formatted="false">Version %1$s</string>
|
||||||
<string name="about_star_on_github">Mettez une étoile sur Github</string>
|
<string name="about_star_on_github">Mettez une étoile sur Github</string>
|
||||||
<string name="contact_us">Contactez-nous</string>
|
<string name="contact_us">Contactez-nous</string>
|
||||||
<string name="licenses">Licenses</string>
|
<string name="licenses">Licenses</string>
|
||||||
@ -40,7 +40,7 @@
|
|||||||
<string name="edit_goal">Modifier l\'objectif</string>
|
<string name="edit_goal">Modifier l\'objectif</string>
|
||||||
<string name="edit_daily_goal">Modifier le but journalier</string>
|
<string name="edit_daily_goal">Modifier le but journalier</string>
|
||||||
<string name="permission_declined">Vous avez décliné une permission, vous ne pouvez pas utiliser cette extension suaf si vous réactivez la permission manuellement</string>
|
<string name="permission_declined">Vous avez décliné une permission, vous ne pouvez pas utiliser cette extension suaf si vous réactivez la permission manuellement</string>
|
||||||
<string name="menu_steps">Pas</string>
|
<string name="steps">Pas</string>
|
||||||
<string name="weight_current">Poid actuel: %1$s%2$s</string>
|
<string name="weight_current">Poid actuel: %1$s%2$s</string>
|
||||||
<string name="delete">Supprimer</string>
|
<string name="delete">Supprimer</string>
|
||||||
<string name="close">Fermer</string>
|
<string name="close">Fermer</string>
|
||||||
@ -57,7 +57,7 @@
|
|||||||
<string name="connectivity_error">Il semplerais que nous ne pouvons pas communiquer avec OpenFoodFact, Merci de re-essayer plus tard</string>
|
<string name="connectivity_error">Il semplerais que nous ne pouvons pas communiquer avec OpenFoodFact, Merci de re-essayer plus tard</string>
|
||||||
<string name="bluetooth_scale">Balance bluetooth</string>
|
<string name="bluetooth_scale">Balance bluetooth</string>
|
||||||
<string name="sync">Synchroniser</string>
|
<string name="sync">Synchroniser</string>
|
||||||
<string name="searching_scales">Recherche de balances connecté...</string>
|
<string name="searching_scales">Recherche de balances connecté…</string>
|
||||||
<string name="import_export_data">Importer & Exporter les données de l\'application.</string>
|
<string name="import_export_data">Importer & Exporter les données de l\'application.</string>
|
||||||
<string name="export">Exporter</string>
|
<string name="export">Exporter</string>
|
||||||
<string name="importTxt">Importer</string>
|
<string name="importTxt">Importer</string>
|
||||||
@ -78,4 +78,12 @@
|
|||||||
<item>Femme</item>
|
<item>Femme</item>
|
||||||
<item>Homme</item>
|
<item>Homme</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string name="activity">Acitivité</string>
|
||||||
|
<string name="vitals">signes vitaux</string>
|
||||||
|
<string name="heart_rate">Rythme cardiaque</string>
|
||||||
|
<string name="coming_soon">À venir</string>
|
||||||
|
<string name="measurements">Mesurements</string>
|
||||||
|
<string name="height">Taille</string>
|
||||||
|
<string name="food">Nouriturre</string>
|
||||||
|
<string name="food_consumption">Consomation Alimentaire</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -13,21 +13,21 @@
|
|||||||
<!-- Units -->
|
<!-- Units -->
|
||||||
<string name="unit_mass_kilogram_name_singular">Kilogram</string>
|
<string name="unit_mass_kilogram_name_singular">Kilogram</string>
|
||||||
<string name="unit_mass_kilogram_name_plural">Kilograms</string>
|
<string name="unit_mass_kilogram_name_plural">Kilograms</string>
|
||||||
<string name="unit_mass_kilogram_unit" translatable="false">%1$skg</string>
|
<string name="unit_mass_kilogram_unit" translatable="false">%1$.2fkg</string>
|
||||||
|
|
||||||
<string name="unit_mass_pound_name_singular">Pound</string>
|
<string name="unit_mass_pound_name_singular">Pound</string>
|
||||||
<string name="unit_mass_pound_name_plural">Pounds</string>
|
<string name="unit_mass_pound_name_plural">Pounds</string>
|
||||||
<string name="unit_mass_pound_unit" translatable="false">%1$slbs</string>
|
<string name="unit_mass_pound_unit" translatable="false">%1$.2flbs</string>
|
||||||
|
|
||||||
<string name="unit_volume_milliliter_name_singular">Milliliter</string>
|
<string name="unit_volume_milliliter_name_singular">Milliliter</string>
|
||||||
<string name="unit_volume_milliliter_name_plural">Milliliters</string>
|
<string name="unit_volume_milliliter_name_plural">Milliliters</string>
|
||||||
<string name="unit_volume_milliliter_unit" translatable="false">%1$sml</string>
|
<string name="unit_volume_milliliter_unit" translatable="false">%1$dml</string>
|
||||||
|
|
||||||
<string name="unit_volume_imperial_ounce_name_singular">Imperial Ounce</string>
|
<string name="unit_volume_imperial_ounce_name_singular">Imperial Ounce</string>
|
||||||
<string name="unit_volume_imperial_ounce_name_plural">Imperial Ounces</string>
|
<string name="unit_volume_imperial_ounce_name_plural">Imperial Ounces</string>
|
||||||
<string name="unit_volume_us_ounce_name_singular">US Ounce</string>
|
<string name="unit_volume_us_ounce_name_singular">US Ounce</string>
|
||||||
<string name="unit_volume_us_ounce_name_plural">US Ounces</string>
|
<string name="unit_volume_us_ounce_name_plural">US Ounces</string>
|
||||||
<string name="unit_volume_ounce_unit" translatable="false">%1$soz</string>
|
<string name="unit_volume_ounce_unit" translatable="false">%1$doz</string>
|
||||||
<string name="languages">Languages</string>
|
<string name="languages">Languages</string>
|
||||||
<string name="settings_global">Global Settings</string>
|
<string name="settings_global">Global Settings</string>
|
||||||
<string name="weight">Weight</string>
|
<string name="weight">Weight</string>
|
||||||
@ -51,7 +51,7 @@
|
|||||||
<string name="edit_goal">Modify Goal</string>
|
<string name="edit_goal">Modify Goal</string>
|
||||||
<string name="permission_declined">You declined a permission, you can\'t use this extension unless you enable it manually</string>
|
<string name="permission_declined">You declined a permission, you can\'t use this extension unless you enable it manually</string>
|
||||||
<string name="edit_daily_goal">Modifiy daily goal</string>
|
<string name="edit_daily_goal">Modifiy daily goal</string>
|
||||||
<string name="menu_steps">Steps</string>
|
<string name="steps">Steps</string>
|
||||||
<string name="weight_current">Current weight: %1$s</string>
|
<string name="weight_current">Current weight: %1$s</string>
|
||||||
<string name="delete">Delete</string>
|
<string name="delete">Delete</string>
|
||||||
<string name="close">Close</string>
|
<string name="close">Close</string>
|
||||||
@ -79,6 +79,14 @@
|
|||||||
<string name="import_export">Import/Export</string>
|
<string name="import_export">Import/Export</string>
|
||||||
<string name="days_until_goal_is_achieved">Days until goal is achieved: ~%1$d days</string>
|
<string name="days_until_goal_is_achieved">Days until goal is achieved: ~%1$d days</string>
|
||||||
<string name="weight_item">Date: %1$s\nBMI: %2$.2f\nBody water: %3$.2f\nMuscles: %4$.2f\nLean body mass: %5$.2f\nBody fat: %6$.2f\nBone mass: %7$.2f\nVisceral fat: %8$.2f\nBasal metabolic rate: %9$d\nTotal daily energy expendure: %10$d\n</string>
|
<string name="weight_item">Date: %1$s\nBMI: %2$.2f\nBody water: %3$.2f\nMuscles: %4$.2f\nLean body mass: %5$.2f\nBody fat: %6$.2f\nBone mass: %7$.2f\nVisceral fat: %8$.2f\nBasal metabolic rate: %9$d\nTotal daily energy expendure: %10$d\n</string>
|
||||||
|
<string name="activity">Activity</string>
|
||||||
|
<string name="vitals">Vitals</string>
|
||||||
|
<string name="heart_rate">Heart Rate</string>
|
||||||
|
<string name="coming_soon">Coming soon</string>
|
||||||
|
<string name="measurements">Measurements</string>
|
||||||
|
<string name="height">Height</string>
|
||||||
|
<string name="food">Food</string>
|
||||||
|
<string name="food_consumption">Food Consumption</string>
|
||||||
<string-array name="activity_levels">
|
<string-array name="activity_levels">
|
||||||
<item>Bedridden</item>
|
<item>Bedridden</item>
|
||||||
<item>Sedentary</item>
|
<item>Sedentary</item>
|
||||||
|
@ -53,14 +53,10 @@
|
|||||||
android:key="water_hourly_notification"
|
android:key="water_hourly_notification"
|
||||||
android:title="Enable Hourly Notification" />
|
android:title="Enable Hourly Notification" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="ml"
|
android:key="tmp.com.dzeio.open-health.volume-unit"
|
||||||
android:entries="@array/volume_units"
|
|
||||||
android:entryValues="@array/volume_units"
|
|
||||||
android:key="water_unit"
|
|
||||||
android:title="Volume Unit" />
|
android:title="Volume Unit" />
|
||||||
<EditTextPreference
|
<com.dzeio.openhealth.utils.fields.IntEditTextPreference
|
||||||
android:defaultValue="2700"
|
android:key="tmp.com.dzeio.open-health.water.daily"
|
||||||
android:key="water_intake"
|
|
||||||
android:selectAllOnFocus="true"
|
android:selectAllOnFocus="true"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
@ -70,7 +66,7 @@
|
|||||||
<PreferenceCategory android:title="Steps settings">
|
<PreferenceCategory android:title="Steps settings">
|
||||||
<com.dzeio.openhealth.utils.fields.IntEditTextPreference
|
<com.dzeio.openhealth.utils.fields.IntEditTextPreference
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:key="com.dzeio.open-health.steps.goal-daily"
|
android:key="tmp.com.dzeio.open-health.steps.goal-daily"
|
||||||
android:selectAllOnFocus="true"
|
android:selectAllOnFocus="true"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:title="Number of steps each days" />
|
android:title="Number of steps each days" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user