diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 322ff6e..b9521cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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 diff --git a/app/src/main/java/com/dzeio/openhealth/Settings.kt b/app/src/main/java/com/dzeio/openhealth/Settings.kt index 7b01b8b..07cffdc 100644 --- a/app/src/main/java/com/dzeio/openhealth/Settings.kt +++ b/app/src/main/java/com/dzeio/openhealth/Settings.kt @@ -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 */ diff --git a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt index a036ada..7c53ef8 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt @@ -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(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(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(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(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) { - 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 = arrayListOf() - - list.forEach { - entries.add( - Entry( - it.timestamp.toDouble(), - it.weight - ) + val entries: ArrayList = values.map { + Entry( + it.timestamp.toDouble(), + it.weight * unit.modifier ) - } + } as ArrayList + 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(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(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(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(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) + ) + } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeViewModel.kt index dfc5928..3b7b5a0 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeViewModel.kt @@ -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 = _waterUnit - private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM) + private val _massUnit = MutableLiveData(Mass.KILOGRAM) /** * The Mass unit used by the user */ - val massUnit: LiveData = _massUnit + val massUnit: LiveData = _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(null) + val dailyWaterIntake: LiveData = _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) { diff --git a/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt index 07fda30..db90b9f 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt @@ -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("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("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) diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeFragment.kt index c22b002..8901efb 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeFragment.kt @@ -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() + + 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().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 - 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 + binding.chart.xAxis.x = 0.0 + binding.chart.refresh() + } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeViewModel.kt index 5a06b4f..4c22406 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeViewModel.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeViewModel.kt @@ -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> = MutableLiveData() - fun init() { + private val _unit = MutableLiveData() + val unit: LiveData = _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!!)) + } } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorDialog.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorDialog.kt index ba13487..38fbb7e 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorDialog.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorDialog.kt @@ -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()) + } + } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorViewModel.kt index bcd20aa..75a6572 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorViewModel.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorViewModel.kt @@ -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() + val unit: LiveData = _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!!)) + } + } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialogViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialogViewModel.kt index e1115c6..8840b01 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialogViewModel.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialogViewModel.kt @@ -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?>(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!!)) } } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightFragment.kt index d8864c7..9605162 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightFragment.kt @@ -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 = arrayListOf() - val previous = 5 val next = 5 val averageList = arrayListOf() @@ -245,6 +252,13 @@ class ListWeightFragment : ) } + val entries: ArrayList = list.map { + Entry( + it.timestamp.toDouble(), + it.weight + ) + } as ArrayList + 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()) { diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightViewModel.kt index dc47292..447094a 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightViewModel.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightViewModel.kt @@ -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 = _massUnit + private val _massUnit = MutableLiveData(Mass.KILOGRAM) + val massUnit: LiveData = _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!!)) } } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesDialog.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesDialog.kt index 776050d..3b8dcb2 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesDialog.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesDialog.kt @@ -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 ) } ) diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialogViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialogViewModel.kt index dd6994e..f76883e 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialogViewModel.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialogViewModel.kt @@ -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 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 { diff --git a/app/src/main/java/com/dzeio/openhealth/units/Mass.kt b/app/src/main/java/com/dzeio/openhealth/units/Mass.kt new file mode 100644 index 0000000..789c714 --- /dev/null +++ b/app/src/main/java/com/dzeio/openhealth/units/Mass.kt @@ -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() +} diff --git a/app/src/main/java/com/dzeio/openhealth/units/Units.kt b/app/src/main/java/com/dzeio/openhealth/units/Units.kt deleted file mode 100644 index 80abbae..0000000 --- a/app/src/main/java/com/dzeio/openhealth/units/Units.kt +++ /dev/null @@ -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 - } - } - } -} diff --git a/app/src/main/java/com/dzeio/openhealth/units/Volume.kt b/app/src/main/java/com/dzeio/openhealth/units/Volume.kt new file mode 100644 index 0000000..37700ea --- /dev/null +++ b/app/src/main/java/com/dzeio/openhealth/units/Volume.kt @@ -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() +} diff --git a/app/src/main/java/com/dzeio/openhealth/utils/Configuration.kt b/app/src/main/java/com/dzeio/openhealth/utils/Configuration.kt index 29676d5..2c8f936 100644 --- a/app/src/main/java/com/dzeio/openhealth/utils/Configuration.kt +++ b/app/src/main/java/com/dzeio/openhealth/utils/Configuration.kt @@ -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> = HashMap() private companion object { - const val TAG = "${Application.TAG}/Config" + const val TAG = "Configuration" } init { @@ -145,10 +144,12 @@ class Configuration( ) : Field(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) } diff --git a/app/src/main/res/drawable/ic_baseline_add_24.xml b/app/src/main/res/drawable/vector_add.xml similarity index 100% rename from app/src/main/res/drawable/ic_baseline_add_24.xml rename to app/src/main/res/drawable/vector_add.xml diff --git a/app/src/main/res/drawable/vector_remove.xml b/app/src/main/res/drawable/vector_remove.xml new file mode 100644 index 0000000..1f55b25 --- /dev/null +++ b/app/src/main/res/drawable/vector_remove.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/fragment_browse.xml b/app/src/main/res/layout/fragment_browse.xml index 793c645..25aa93e 100644 --- a/app/src/main/res/layout/fragment_browse.xml +++ b/app/src/main/res/layout/fragment_browse.xml @@ -29,7 +29,7 @@ @@ -69,7 +69,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="4dp" - android:text="Steps" /> + android:text="@string/steps" /> + android:src="@drawable/vector_add" /> @@ -138,14 +138,14 @@ @@ -169,7 +169,7 @@ @@ -207,7 +207,7 @@ + android:text="@string/weight" /> + android:text="@string/height" /> + android:text="@string/coming_soon" /> @@ -285,7 +285,7 @@ @@ -323,7 +323,7 @@ + android:text="@string/water_intake" /> @@ -364,7 +364,7 @@ + android:text="@string/food_consumption" /> diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index d4173c3..d17f0c0 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -25,7 +25,7 @@ @@ -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 @@ /> @@ -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 @@ @@ -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" /> @@ -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" /> diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 6144d0a..a441bc1 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -170,9 +170,9 @@ + android:label="@string/food_consumption" + tools:layout="@layout/fragment_food_home"> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 35f6696..31bac6c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -27,7 +27,7 @@ Ton Application de santé libre, open source et respectueuse de la vie privée Ajouter A Propos - Version %1$ + Version %1$s Mettez une étoile sur Github Contactez-nous Licenses @@ -40,7 +40,7 @@ Modifier l\'objectif Modifier le but journalier Vous avez décliné une permission, vous ne pouvez pas utiliser cette extension suaf si vous réactivez la permission manuellement - Pas + Pas Poid actuel: %1$s%2$s Supprimer Fermer @@ -57,7 +57,7 @@ Il semplerais que nous ne pouvons pas communiquer avec OpenFoodFact, Merci de re-essayer plus tard Balance bluetooth Synchroniser - Recherche de balances connecté... + Recherche de balances connecté… Importer & Exporter les données de l\'application. Exporter Importer @@ -78,4 +78,12 @@ Femme Homme + Acitivité + signes vitaux + Rythme cardiaque + À venir + Mesurements + Taille + Nouriturre + Consomation Alimentaire diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ca4efda..ab60d29 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,21 +13,21 @@ Kilogram Kilograms - %1$skg + %1$.2fkg Pound Pounds - %1$slbs + %1$.2flbs Milliliter Milliliters - %1$sml + %1$dml Imperial Ounce Imperial Ounces US Ounce US Ounces - %1$soz + %1$doz Languages Global Settings Weight @@ -51,7 +51,7 @@ Modify Goal You declined a permission, you can\'t use this extension unless you enable it manually Modifiy daily goal - Steps + Steps Current weight: %1$s Delete Close @@ -79,6 +79,14 @@ Import/Export Days until goal is achieved: ~%1$d days 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 + Activity + Vitals + Heart Rate + Coming soon + Measurements + Height + Food + Food Consumption Bedridden Sedentary diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 4ab61ac..659ae85 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -53,14 +53,10 @@ android:key="water_hourly_notification" android:title="Enable Hourly Notification" /> -