1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-04-23 11:22:10 +00:00

fix: Allow to use other volumes units than Milliliter (#156)

This commit is contained in:
Florian Bouillon 2023-03-06 09:48:28 +01:00 committed by GitHub
parent fa56970fb6
commit 497cc58057
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 533 additions and 328 deletions

View File

@ -40,6 +40,7 @@ jobs:
- name: Zip artifacts
run: zip -r assemble.zip . -i '**/build/*.apk' '**/build/*.aab' '**/build/*.aar' '**/build/*.so'
- name: Upload artifacts
continue-on-error: true
uses: actions/upload-artifact@v3
with:
name: assemble

View File

@ -40,6 +40,13 @@ object Settings {
*/
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
*/

View File

@ -1,7 +1,6 @@
package com.dzeio.openhealth.ui.home
import android.animation.ValueAnimator
import android.content.SharedPreferences
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
@ -10,21 +9,22 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import com.dzeio.charts.Entry
import com.dzeio.charts.axis.Line
import com.dzeio.charts.series.LineSerie
import com.dzeio.openhealth.BuildConfig
import com.dzeio.openhealth.R
import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.databinding.FragmentHomeBinding
import com.dzeio.openhealth.ui.weight.WeightDialog
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.ChartUtils
import com.dzeio.openhealth.utils.DrawUtils
import com.google.android.material.color.MaterialColors
import dagger.hilt.android.AndroidEntryPoint
import java.text.DateFormat
import java.util.Date
import java.util.Locale
import kotlin.math.max
import kotlin.math.min
@ -34,10 +34,6 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHomeBinding
get() = FragmentHomeBinding::inflate
private val settings: SharedPreferences by lazy {
PreferenceManager.getDefaultSharedPreferences(requireContext())
}
override fun onStart() {
super.onStart()
// Bindings
@ -63,14 +59,14 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
viewModel.updateWater(water)
}
}
val waterUnit =
Units.Volume.find(settings.getString("water_unit", "milliliter") ?: "Milliliter")
binding.fragmentHomeWaterTotal.text =
String.format(
resources.getString(waterUnit.unit),
viewModel.dailyWaterIntake
)
viewModel.waterUnit.observe(viewLifecycleOwner) {
updateWaterTotal()
}
viewModel.dailyWaterIntake.observe(viewLifecycleOwner) {
updateWaterTotal()
}
binding.fragmentHomeWaterRemove.setOnClickListener {
val water = viewModel.water.value
@ -95,12 +91,21 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
}
binding.weightGraph.apply {
val serie = LineSerie(this)
LineSerie(this)
animator.enabled = false
xAxis.dataWidth = 2.4192e+9
xAxis.scrollEnabled = true
xAxis.apply {
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())
series = arrayListOf(serie)
}
if (BuildConfig.DEBUG) {
@ -116,75 +121,84 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
// Update the water intake Graph when the water intake changes
viewModel.water.observe(viewLifecycleOwner) {
if (it != null) {
updateWater(it.value)
} else {
updateWater(0)
}
updateWaterGraph()
}
// Update the steps Graph when the steps count changes
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
viewModel.stepsGoal.observe(viewLifecycleOwner) {
if (it == null) {
binding.stepsTotal.text = ""
binding.stepsTotal.visibility = View.GONE
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
viewModel.weights.observe(viewLifecycleOwner) {
if (it != null) {
updateGraph(it)
}
updateWeightGraph()
}
// update the graph when the goal weight change
viewModel.goalWeight.observe(viewLifecycleOwner) {
if (viewModel.weights.value != null) updateGraph(viewModel.weights.value!!)
updateWeightGraph()
}
// update the graph when the weight unit change
viewModel.massUnit.observe(viewLifecycleOwner) {
if (viewModel.weights.value != null) updateGraph(viewModel.weights.value!!)
updateWeightGraph()
}
}
/**
* Function that update the graph for the weight
*/
private fun updateGraph(list: List<Weight>) {
val chart = binding.weightGraph
private fun updateWeightGraph() {
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 entries: ArrayList<Entry> = arrayListOf()
list.forEach {
entries.add(
Entry(
it.timestamp.toDouble(),
it.weight
)
val entries: ArrayList<Entry> = values.map {
Entry(
it.timestamp.toDouble(),
it.weight * unit.modifier
)
}
} as ArrayList<Entry>
serie.entries = entries
if (viewModel.goalWeight.value != null) {
chart.yAxis.clearLines()
if (goal != null) {
chart.yAxis.addLine(
viewModel.goalWeight.value!!,
goal,
Line(true, Paint(chart.yAxis.linePaint).apply { strokeWidth = 4f })
)
}
if (list.isEmpty()) {
if (entries.isEmpty()) {
chart.xAxis.x = 0.0
} else {
chart.xAxis.x = list.last().timestamp - chart.xAxis.dataWidth!!
chart.xAxis.x = entries.last().x - chart.xAxis.dataWidth!!
}
chart.refresh()
@ -193,29 +207,30 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
/**
* 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
*/
private fun updateWater(newValue: Int) {
// get the current Unit
val waterUnit =
Units.Volume.find(settings.getString("water_unit", "milliliter") ?: "Milliliter")
private fun updateWaterGraph() {
val newValue = viewModel.water.value?.value ?: 0
val daily = viewModel.dailyWaterIntake.value
val unit = viewModel.waterUnit.value
if (unit == null) {
return
}
// Update the count
binding.fragmentHomeWaterCurrent.text =
String.format(
resources.getString(waterUnit.unit),
(newValue * waterUnit.modifier).toInt()
getString(
unit.unit,
(newValue * unit.modifier).toInt()
)
// TODO: move it elsewhere
binding.fragmentHomeWaterTotal.text =
String.format(
resources.getString(waterUnit.unit),
viewModel.dailyWaterIntake
)
if (daily == null) {
return
}
// get the with/height of the ImageView
var width = 1500
@ -228,7 +243,7 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
// Prepare the update animation
val animator = ValueAnimator.ofInt(
this.oldValue.toInt(),
this.oldValue,
newValue
)
animator.duration = 300 // ms
@ -237,8 +252,8 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
if (localView == null) {
return@addUpdateListener
}
this.oldValue = (it.animatedValue as Int).toFloat()
val value = 100 * it.animatedValue as Int / viewModel.dailyWaterIntake
this.oldValue = (it.animatedValue as Int)
val value = 100 * it.animatedValue as Int / daily.toFloat()
val graph = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(graph)
@ -283,4 +298,23 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
// start the animation
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)
)
}
}

View File

@ -10,7 +10,8 @@ import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.water.WaterRepository
import com.dzeio.openhealth.data.weight.Weight
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 dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -54,26 +55,25 @@ class HomeViewModel @Inject internal constructor(
/**
* 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()
/**
* The unit used to display the water intake of the user
*/
var waterUnit = Units.Volume.find(config.getString("water_unit").value ?: "ml")
private val _waterUnit = MutableLiveData(Volume.MILLILITER)
val waterUnit: LiveData<Volume> = _waterUnit
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
private val _massUnit = MutableLiveData(Mass.KILOGRAM)
/**
* The Mass unit used by the user
*/
val massUnit: LiveData<Units.Mass> = _massUnit
val massUnit: LiveData<Mass> = _massUnit
/**
* the User weight goal
*/
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 {
// 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 {
if (it == null) return@addObserver
_massUnit.postValue(Units.Mass.find(it))
_massUnit.postValue(Mass.find(it))
}
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) {

View File

@ -13,9 +13,11 @@ import com.dzeio.openhealth.Application
import com.dzeio.openhealth.BuildConfig
import com.dzeio.openhealth.R
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.LocaleUtils
import com.dzeio.openhealth.utils.fields.IntEditTextPreference
import dagger.hilt.android.AndroidEntryPoint
import java.util.Locale
import javax.inject.Inject
@ -48,11 +50,11 @@ class SettingsFragment : PreferenceFragmentCompat() {
val value = config.getFloat(Settings.WEIGHT_GOAL)
setOnPreferenceClickListener {
if (value.value != null) {
val unit = config.getString(Settings.MASS_UNIT).value
val unit = config.getInt(Settings.MASS_UNIT).value
text = if (unit == null) {
value.value!!.toString()
} else {
val modifier = Units.Mass.find(unit).modifier
val modifier = Mass.find(unit).modifier
(value.value!! * modifier).toString()
}
}
@ -60,10 +62,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
}
setOnPreferenceChangeListener { _, newValue ->
val unit = config.getString(Settings.MASS_UNIT).value
var modifier = Units.Mass.KILOGRAM.modifier
val unit = config.getInt(Settings.MASS_UNIT).value
var modifier = Mass.KILOGRAM.modifier
if (unit != null) {
modifier = Units.Mass.find(unit).modifier
modifier = Mass.find(unit).modifier
}
value.value = ((newValue as String).toFloat() / modifier)
@ -132,6 +134,52 @@ class SettingsFragment : PreferenceFragmentCompat() {
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
languagesPreference?.setOnPreferenceChangeListener { _, newValue ->
LocaleUtils.setLanguage(requireContext(), newValue as String)

View File

@ -13,7 +13,6 @@ import com.dzeio.openhealth.adapters.ItemAdapter
import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.databinding.FragmentMainWaterHomeBinding
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.ChartUtils
import dagger.hilt.android.AndroidEntryPoint
import java.text.SimpleDateFormat
@ -27,17 +26,18 @@ class WaterHomeFragment :
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentMainWaterHomeBinding =
FragmentMainWaterHomeBinding::inflate
private val adapter = ItemAdapter<Water>()
private val serie by lazy { BarSerie(binding.chart) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.init()
val recycler = binding.list
val manager = LinearLayoutManager(requireContext())
recycler.layoutManager = manager
recycler.layoutManager = LinearLayoutManager(requireContext())
val adapter = ItemAdapter<Water>().apply {
adapter.apply {
onItemClick = {
findNavController().navigate(
WaterHomeFragmentDirections.actionNavWaterHomeToNavWaterEdit(
@ -48,20 +48,16 @@ class WaterHomeFragment :
recycler.adapter = this
}
val chart = binding.chart
val serie = BarSerie(chart)
chart.apply {
ChartUtils.materielTheme(chart, requireView())
binding.chart.apply {
serie
ChartUtils.materielTheme(this, requireView())
yAxis.apply {
// onValueFormat
setYMin(0f)
}
xAxis.apply {
dataWidth = 604800000.0
textPaint.textSize = 32f
scrollEnabled = true
onValueFormat = onValueFormat@{
return@onValueFormat SimpleDateFormat(
@ -79,37 +75,50 @@ class WaterHomeFragment :
}
viewModel.items.observe(viewLifecycleOwner) { list ->
val unit = Units.Volume.MILLILITER
adapter.set(
list.map {
ItemAdapter.Item(
it,
getString(
unit.unit,
unit.formatToString(it.value)
),
it.formatTimestamp(),
icon = R.drawable.ic_outline_edit_24
)
}
)
if (list.isEmpty()) {
return@observe
}
val dataset = list.map {
return@map Entry(
it.timestamp.toDouble(),
it.value.toFloat()
)
}
serie.entries = dataset as ArrayList<Entry>
chart.xAxis.x = chart.xAxis.getXMin()
chart.xAxis.x =
chart.xAxis.getXMax() - chart.xAxis.dataWidth!! + chart.xAxis.dataWidth!! / 7
chart.refresh()
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(
data.map {
ItemAdapter.Item(
it,
getString(
unit.unit,
unit.fromMilliliter(it.value)
),
it.formatTimestamp(),
icon = R.drawable.ic_outline_edit_24
)
}
)
// update graph
val dataset = data.map {
return@map Entry(
it.timestamp.toDouble(),
unit.fromMilliliter(it.value).toFloat()
)
}
serie.entries = dataset as ArrayList<Entry>
binding.chart.xAxis.x = 0.0
binding.chart.refresh()
}
}

View File

@ -1,10 +1,14 @@
package com.dzeio.openhealth.ui.water
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.dzeio.openhealth.Settings
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.water.Water
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 javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
@ -12,15 +16,25 @@ import kotlinx.coroutines.launch
@HiltViewModel
class WaterHomeViewModel@Inject internal constructor(
private val waterRepository: WaterRepository
private val waterRepository: WaterRepository,
config: Configuration
) : BaseViewModel() {
val items: MutableLiveData<List<Water>> = MutableLiveData()
fun init() {
private val _unit = MutableLiveData<Volume?>()
val unit: LiveData<Volume?> = _unit
init {
viewModelScope.launch {
waterRepository.getWaters().collectLatest {
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!!))
}
}
}

View File

@ -7,6 +7,7 @@ import com.dzeio.openhealth.R
import com.dzeio.openhealth.Settings
import com.dzeio.openhealth.core.BaseDialog
import com.dzeio.openhealth.databinding.DialogWaterSizeSelectorBinding
import com.dzeio.openhealth.units.Volume
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@ -30,14 +31,30 @@ class WaterSizeSelectorDialog :
}
viewModel.cupSize.observe(this) {
var real = it ?: Settings.WATER_INTAKE_SIZE_DEFAULT
binding.customSize.text = String.format(
getString(R.string.custom_amount),
"${real}ml"
)
if (binding.inputParent.visibility == View.GONE) {
binding.input.setText(real.toString())
setCustomSizeText()
}
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 {
@ -61,10 +78,11 @@ class WaterSizeSelectorDialog :
setTextFieldStatus(true)
}
binding.input.doOnTextChanged { text, start, before, count ->
binding.input.doOnTextChanged { text, _, _, _ ->
val newSize = text.toString().toIntOrNull()
if (newSize != null) {
viewModel.setCupSize(newSize)
if (newSize != null && binding.inputParent.visibility == View.VISIBLE) {
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.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())
}
}
}

View File

@ -1,7 +1,10 @@
package com.dzeio.openhealth.ui.water
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.dzeio.openhealth.Settings
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.units.Volume
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -12,8 +15,20 @@ class WaterSizeSelectorViewModel @Inject constructor(
) : BaseViewModel() {
val cupSize = settings.getInt(Settings.WATER_INTAKE_SIZE).toLiveData()
private val _unit = MutableLiveData<Volume?>()
val unit: LiveData<Volume?> = _unit
fun setCupSize(value: Int) {
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!!))
}
}
}

View File

@ -8,7 +8,7 @@ import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.weight.Weight
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 dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -30,7 +30,7 @@ class EditWeightDialogViewModel @Inject internal constructor(
private val _weights = MutableLiveData<List<Weight>?>(null)
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
private val _massUnit = MutableLiveData(Mass.KILOGRAM)
init {
@ -41,13 +41,13 @@ class EditWeightDialogViewModel @Inject internal constructor(
}
}
config.getString(Settings.MASS_UNIT).apply {
config.getInt(Settings.MASS_UNIT).apply {
addObserver {
if (it == null) return@addObserver
_massUnit.postValue(Units.Mass.find(it))
_massUnit.postValue(Mass.find(it))
}
if (value != null) {
_massUnit.postValue(Units.Mass.find(value!!))
_massUnit.postValue(Mass.find(value!!))
}
}
}

View File

@ -3,6 +3,7 @@ package com.dzeio.openhealth.ui.weight
import android.Manifest
import android.content.SharedPreferences
import android.graphics.Paint
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
@ -25,7 +26,7 @@ import com.dzeio.openhealth.adapters.ItemAdapter
import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.data.weight.Weight
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.PermissionsUtils
import com.google.android.material.color.MaterialColors
@ -99,16 +100,22 @@ class ListWeightFragment :
}
binding.bluetoothButton.setOnClickListener {
val permissions = arrayOf(
val permissions = arrayListOf(
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_SCAN,
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) {
button = binding.bluetoothButton
activityResult.launch(permissions)
activityResult.launch(permissions.toTypedArray())
return@setOnClickListener
}
findNavController().navigate(
@ -140,16 +147,20 @@ class ListWeightFragment :
updateGraph(list, it)
}
viewModel.massUnit.observe(viewLifecycleOwner) { unit ->
binding.chart.yAxis.onValueFormat = { getString(unit.unit, unit.fromKilogram(it)) }
}
viewModel.weights.observe(viewLifecycleOwner) { list ->
if (list != null) {
val unit = viewModel.massUnit.value ?: Units.Mass.KILOGRAM
val unit = viewModel.massUnit.value ?: Mass.KILOGRAM
adapter.set(
list.map {
ItemAdapter.Item(
it,
getString(
unit.unit,
unit.formatToString(it.weight)
it.weight
),
getString(
R.string.weight_item,
@ -185,8 +196,6 @@ class ListWeightFragment :
yAxis.apply {
setYMin(null)
onValueFormat = { value -> "${value.toInt()}" }
}
xAxis.apply {
@ -228,8 +237,6 @@ class ListWeightFragment :
val serie = chart.series[0] as LineSerie
val avSerie = chart.series[1] as LineSerie
val entries: ArrayList<Entry> = arrayListOf()
val previous = 5
val next = 5
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
chart.yAxis.clearLines()
@ -257,39 +271,30 @@ class ListWeightFragment :
}
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(
R.string.days_until_goal_is_achieved,
(timeUntilGoal / 1000 / 60 / 60 / 24).toInt()
)
averageList.add(
entries.add(
Entry(
(list.last().timestamp + timeUntilGoal),
(entries.last().x + timeUntilGoal),
goal
)
)
binding.goalText.visibility = View.VISIBLE
} else {
averageList.add(
entries.add(
Entry(
averageList.last().x + chart.xAxis.dataWidth!!,
averageList.last().y + direction * 7 * 4
entries.last().x + chart.xAxis.dataWidth!!,
entries.last().y + direction * 7 * 4
)
)
binding.goalText.visibility = View.GONE
}
avSerie.entries = averageList
list.forEach {
entries.add(
Entry(
it.timestamp.toDouble(),
it.weight
)
)
}
serie.entries = entries
if (list.isEmpty()) {

View File

@ -7,7 +7,7 @@ import com.dzeio.openhealth.Settings
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.weight.Weight
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 dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -21,8 +21,8 @@ class ListWeightViewModel @Inject internal constructor(
settings: Configuration
) : BaseViewModel() {
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
val massUnit: LiveData<Units.Mass> = _massUnit
private val _massUnit = MutableLiveData(Mass.KILOGRAM)
val massUnit: LiveData<Mass> = _massUnit
private val _goalWeight = settings.getFloat(Settings.WEIGHT_GOAL)
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 {
if (it == null) return@addObserver
_massUnit.postValue(Units.Mass.find(it))
_massUnit.postValue(Mass.find(it))
}
if (value != null) {
_massUnit.postValue(Units.Mass.find(value!!))
_massUnit.postValue(Mass.find(value!!))
}
}
}

View File

@ -25,6 +25,7 @@ class ScanScalesDialog :
override val bindingInflater: (LayoutInflater) -> DialogSearchBinding =
DialogSearchBinding::inflate
@SuppressLint("MissingPermission")
override fun onBuilderInit(builder: MaterialAlertDialogBuilder) {
super.onBuilderInit(builder)
@ -102,7 +103,7 @@ class ScanScalesDialog :
it,
it.name,
"${it.item!!.name} (${it.item!!.address})",
icon = R.drawable.ic_baseline_add_24
icon = R.drawable.vector_add
)
}
)

View File

@ -8,12 +8,12 @@ import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.data.weight.WeightRepository
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 dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class WeightDialogViewModel @Inject internal constructor(
@ -33,7 +33,7 @@ class WeightDialogViewModel @Inject internal constructor(
val weight: LiveData<Weight?> = _weight
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?) {
viewModelScope.launch {

View 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()
}

View File

@ -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
}
}
}
}

View 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()
}

View File

@ -2,7 +2,6 @@ package com.dzeio.openhealth.utils
import android.content.SharedPreferences
import androidx.core.content.edit
import com.dzeio.openhealth.Application
import com.dzeio.openhealth.core.Observable
/**
@ -17,7 +16,7 @@ class Configuration(
private val cache: HashMap<String, Field<*>> = HashMap()
private companion object {
const val TAG = "${Application.TAG}/Config"
const val TAG = "Configuration"
}
init {
@ -145,10 +144,12 @@ class Configuration(
) : Field<Int?>(defaultValue) {
override fun exists(): Boolean = prefs.contains(key)
override fun internalGet(): Int? {
if (exists()) {
return prefs.getInt(key, 0)
return try {
prefs.getInt(key, 0)
} catch (e: ClassCastException) {
val it = prefs.getString(key, "")
it?.toIntOrNull() ?: defaultValue
}
return defaultValue
}
override fun internalSet(value: Int?) =
prefs.edit { if (value == null) remove(key) else putInt(key, value) }

View 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>

View File

@ -29,7 +29,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Activity"
android:text="@string/activity"
/>
</LinearLayout>
@ -69,7 +69,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
android:text="Steps" />
android:text="@string/steps" />
<TextView
android:layout_width="match_parent"
@ -94,13 +94,13 @@
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"
android:src="@drawable/ic_baseline_add_24" />
android:src="@drawable/vector_add" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Vitals"
android:text="@string/vitals"
/>
</LinearLayout>
@ -138,14 +138,14 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Heart Rate"
android:text="@string/heart_rate"
android:textColor="?attr/colorSurfaceInverse" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Coming soon"
android:text="@string/coming_soon"
android:textColor="?attr/colorSurfaceInverse" />
</LinearLayout>
@ -169,7 +169,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Measurements"
android:text="@string/measurements"
/>
</LinearLayout>
@ -207,7 +207,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Weight" />
android:text="@string/weight" />
<TextView
android:layout_width="match_parent"
@ -256,13 +256,13 @@
android:layout_height="wrap_content"
android:textColor="?attr/colorSurfaceInverse"
android:paddingBottom="4dp"
android:text="Height" />
android:text="@string/height" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/colorSurfaceInverse"
android:text="Coming soon" />
android:text="@string/coming_soon" />
</LinearLayout>
</LinearLayout>
@ -285,7 +285,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Food"
android:text="@string/food"
/>
</LinearLayout>
@ -323,7 +323,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Water Intake" />
android:text="@string/water_intake" />
</LinearLayout>
</LinearLayout>
@ -364,7 +364,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Food Calories" />
android:text="@string/food_consumption" />
</LinearLayout>

View File

@ -25,7 +25,7 @@
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
android:layout_width="0dp"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:layout_height="match_parent"
android:layout_weight="1">
@ -72,7 +72,7 @@
android:layout_height="18dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:src="@drawable/ic_outline_hexagon_24"
android:src="@drawable/vector_remove"
app:layout_constraintBottom_toBottomOf="@+id/linearLayout"
app:layout_constraintEnd_toStartOf="@+id/linearLayout"
app:layout_constraintTop_toTopOf="@+id/linearLayout" />
@ -103,6 +103,8 @@
/>
<TextView
android:visibility="gone"
tools:visibility="visible"
android:id="@+id/fragment_home_water_total"
style="@style/TextAppearance.Material3.LabelMedium"
android:layout_width="wrap_content"
@ -120,7 +122,7 @@
android:layout_height="18dp"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:src="@drawable/ic_baseline_add_24"
android:src="@drawable/vector_add"
app:layout_constraintBottom_toBottomOf="@+id/linearLayout"
app:layout_constraintStart_toEndOf="@+id/linearLayout"
app:layout_constraintTop_toTopOf="@+id/linearLayout" />
@ -130,7 +132,7 @@
android:id="@+id/background"
android:layout_width="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_constraintDimensionRatio="2:1"
app:layout_constraintEnd_toEndOf="parent"
@ -145,7 +147,7 @@
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
android:layout_width="0dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_height="wrap_content"
android:layout_weight="1">
@ -225,6 +227,8 @@
android:layout_height="match_parent"
android:text="@string/unit_volume_milliliter_unit"
android:textAlignment="center"
android:visibility="gone"
tools:visibility="visible"
android:textColor="?attr/colorOnBackground" />
</LinearLayout>
@ -298,7 +302,7 @@
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"
android:src="@drawable/ic_baseline_add_24" />
android:src="@drawable/vector_add" />
<ImageView
android:id="@+id/list_weight"

View File

@ -5,7 +5,7 @@
<item
android:id="@+id/action_add"
android:visible="false"
android:icon="@drawable/ic_baseline_add_24"
android:icon="@drawable/vector_add"
android:title="@string/add"
app:showAsAction="ifRoom" />

View File

@ -170,9 +170,9 @@
</dialog>
<fragment
android:id="@+id/foodHomeFragment"
tools:layout="@layout/fragment_food_home"
android:name="com.dzeio.openhealth.ui.food.FoodHomeFragment"
android:label="FoodHomeFragment" >
android:label="@string/food_consumption"
tools:layout="@layout/fragment_food_home">
<action
android:id="@+id/action_foodHomeFragment_to_nav_dialog_food_search"
app:destination="@id/nav_dialog_food_search" />

View File

@ -27,7 +27,7 @@
<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="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="contact_us">Contactez-nous</string>
<string name="licenses">Licenses</string>
@ -40,7 +40,7 @@
<string name="edit_goal">Modifier l\'objectif</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="menu_steps">Pas</string>
<string name="steps">Pas</string>
<string name="weight_current">Poid actuel: %1$s%2$s</string>
<string name="delete">Supprimer</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="bluetooth_scale">Balance bluetooth</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 &amp; Exporter les données de l\'application.</string>
<string name="export">Exporter</string>
<string name="importTxt">Importer</string>
@ -78,4 +78,12 @@
<item>Femme</item>
<item>Homme</item>
</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>

View File

@ -13,21 +13,21 @@
<!-- Units -->
<string name="unit_mass_kilogram_name_singular">Kilogram</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_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_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_plural">Imperial Ounces</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_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="settings_global">Global Settings</string>
<string name="weight">Weight</string>
@ -51,7 +51,7 @@
<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="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="delete">Delete</string>
<string name="close">Close</string>
@ -79,6 +79,14 @@
<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="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">
<item>Bedridden</item>
<item>Sedentary</item>

View File

@ -53,14 +53,10 @@
android:key="water_hourly_notification"
android:title="Enable Hourly Notification" />
<ListPreference
android:defaultValue="ml"
android:entries="@array/volume_units"
android:entryValues="@array/volume_units"
android:key="water_unit"
android:key="tmp.com.dzeio.open-health.volume-unit"
android:title="Volume Unit" />
<EditTextPreference
android:defaultValue="2700"
android:key="water_intake"
<com.dzeio.openhealth.utils.fields.IntEditTextPreference
android:key="tmp.com.dzeio.open-health.water.daily"
android:selectAllOnFocus="true"
android:singleLine="true"
android:inputType="number"
@ -70,7 +66,7 @@
<PreferenceCategory android:title="Steps settings">
<com.dzeio.openhealth.utils.fields.IntEditTextPreference
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:singleLine="true"
android:title="Number of steps each days" />