1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-04-22 19:02:16 +00:00

feat(app): Add weight goal #88

This commit is contained in:
Florian Bouillon 2022-08-24 22:26:13 +02:00
parent 218d23f223
commit 1e0988d5b2
21 changed files with 553 additions and 125 deletions

View File

@ -16,4 +16,10 @@ object Settings {
*/
const val APP_LANGUAGE = "com.dzeio.open-health.app.language"
}
/***************************
* Weight related settings *
***************************/
const val WEIGHT_GOAL = "com.dzeio.open-health.weight.goal"
}

View File

@ -1,61 +1,17 @@
package com.dzeio.openhealth.core
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
abstract class BaseDialog<VM : BaseViewModel, VB : ViewBinding>(private val viewModelClass: Class<VM>) : DialogFragment() {
/**
* Base dialog
*
* note: Dialog crash app with viewmodel error? add @AndroidEntryPoint
*/
abstract class BaseDialog<VM : BaseViewModel, VB : ViewBinding>(private val viewModelClass: Class<VM>) :
BaseSimpleDialog<VB>() {
val viewModel by lazy {
ViewModelProvider(this)[viewModelClass]
}
private var _binding: VB? = null
val binding get() = _binding!!
/**
* Setup everything!
*/
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { act ->
val builder = MaterialAlertDialogBuilder(requireContext())
_binding = bindingInflater(act.layoutInflater)
builder.setView(binding.root)
onBuilderInit(builder)
val dialog = builder.create()
onDialogInit(dialog)
onCreated()
dialog
} ?: throw IllegalStateException("Activity cannot be null")
}
open fun onBuilderInit(builder: MaterialAlertDialogBuilder): Unit {}
open fun onDialogInit(dialog: AlertDialog): Unit {}
open fun onCreated(): Unit {}
/**
* Function to inflate the Fragment Bindings
*/
abstract val bindingInflater: (LayoutInflater) -> VB
/**
* Destroy binding
*/
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
}

View File

@ -0,0 +1,57 @@
package com.dzeio.openhealth.core
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.viewbinding.ViewBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
abstract class BaseSimpleDialog<VB : ViewBinding> : DialogFragment() {
private var _binding: VB? = null
val binding get() = _binding!!
/**
* Setup everything!
*/
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { act ->
val builder = MaterialAlertDialogBuilder(requireContext())
_binding = bindingInflater(act.layoutInflater)
builder.setView(binding.root)
onBuilderInit(builder)
val dialog = builder.create()
onDialogInit(dialog)
onCreated()
dialog
} ?: throw IllegalStateException("Activity cannot be null")
}
open fun onBuilderInit(builder: MaterialAlertDialogBuilder) {}
open fun onDialogInit(dialog: AlertDialog) {}
open fun onCreated() {}
/**
* Function to inflate the Fragment Bindings
*/
abstract val bindingInflater: (LayoutInflater) -> VB
/**
* Destroy binding
*/
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -0,0 +1,48 @@
package com.dzeio.openhealth.core
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
open class Observable<T>(baseValue: T) {
private val functionObservers: ArrayList<(T) -> Unit> = ArrayList()
fun addObserver(fn: (T) -> Unit) {
if (!functionObservers.contains(fn)) {
functionObservers.add(fn)
}
}
fun removeObserver(fn: (T) -> Unit) {
if (functionObservers.contains(fn)) {
functionObservers.remove(fn)
}
}
open var value: T = baseValue
set(value) {
field = value
notifyObservers()
}
fun notifyObservers() {
// Notify Functions
for (fn in functionObservers) {
notifyObserver(fn)
}
}
fun notifyObserver(observer: (T) -> Unit) {
observer.invoke(value)
}
fun toLiveData(): LiveData<T> {
val ld = MutableLiveData(value)
addObserver {
ld.postValue(it)
}
return ld
}
}

View File

@ -3,6 +3,7 @@ package com.dzeio.openhealth.di
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import com.dzeio.openhealth.utils.Configuration
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -19,4 +20,10 @@ class SystemModule {
fun provideSettings(@ApplicationContext context: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(context)
}
@Singleton
@Provides
fun provideConfig(sharedPreferences: SharedPreferences): Configuration {
return Configuration(sharedPreferences)
}
}

View File

@ -136,8 +136,10 @@ object WeightChart {
limit.lineWidth = 1f
limit.textColor = Color.BLACK
axisRight.removeAllLimitLines()
axisRight.addLimitLine(limit)
}
invalidate()
}
}
}

View File

@ -108,6 +108,15 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
updateWater(0)
}
}
viewModel.goalWeight.observe(viewLifecycleOwner) {
lifecycleScope.launchWhenStarted {
viewModel.fetchWeights().collectLatest {
updateGraph(it)
}
}
}
}
private fun updateGraph(list: List<Weight>) {
@ -116,7 +125,7 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
requireView(),
list,
viewModel.weightUnit,
viewModel.goalWeight?.toFloat()
viewModel.goalWeight.value
)
// legend.apply {

View File

@ -6,22 +6,25 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.dzeio.openhealth.Application.Companion.TAG
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.data.weight.Weight
import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.UnitFactory
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 HomeViewModel @Inject internal constructor(
private val weightRepository: WeightRepository,
private val waterRepository: WaterRepository,
settings: SharedPreferences
settings: SharedPreferences,
config: Configuration
) : BaseViewModel() {
private val _water = MutableLiveData<Water?>(null)
@ -35,8 +38,7 @@ class HomeViewModel @Inject internal constructor(
var weightUnit =
UnitFactory.mass(settings.getString("weight_unit", "kilogram") ?: "kilogram")
val goalWeight: Int? =
(settings.getString("weight_goal", null)?.toIntOrNull())
val goalWeight = config.getFloat(Settings.WEIGHT_GOAL).toLiveData()
val dailyWaterIntake: Int =
((settings.getString("water_intake", "1200")?.toFloatOrNull() ?: 1200f) * waterUnit.modifier)

View File

@ -20,7 +20,7 @@ import java.util.Locale
class SettingsFragment : PreferenceFragmentCompat() {
private companion object {
const val TAG = "${Application.TAG}/SttngsFrgmnt"
const val TAG = "${Application.TAG}/SettingsFragment"
}
val settings: SharedPreferences by lazy {
@ -31,12 +31,12 @@ class SettingsFragment : PreferenceFragmentCompat() {
setPreferencesFromResource(R.xml.preferences, rootKey)
// Force only numbers on Goal
val weightGoal = findPreference<EditTextPreference>("weight_goal")
val weightGoal = findPreference<EditTextPreference>(Settings.WEIGHT_GOAL)
weightGoal?.apply {
setOnBindEditTextListener {
it.inputType = InputType.TYPE_CLASS_NUMBER
}
val value = settings.getString("weight_goal", null)
val value = settings.getString(Settings.WEIGHT_GOAL, null)
val modifier = UnitFactory.mass(settings.getString("weight_unit", null) ?: "kilogram")
if (value != null && value.isNotEmpty()) {
text = (value.toFloat() * modifier.modifier).toString()
@ -45,7 +45,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
val alue = ((newValue as String).toInt() / modifier.modifier).toInt().toString()
settings.edit()
.putString(
"weight_goal",
Settings.WEIGHT_GOAL,
alue
)
.apply()
@ -61,7 +61,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
setOnPreferenceChangeListener { _, newValue ->
val unit = settings.getString("weight_unit", "kilogram")
?: return@setOnPreferenceChangeListener true
val goal = settings.getString("weight_goal", null)
val goal = settings.getString(Settings.WEIGHT_GOAL, null)
?: return@setOnPreferenceChangeListener true
val modifier = UnitFactory.mass(newValue as String)
val oldModifier = UnitFactory.mass(unit)
@ -69,7 +69,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
(goal.toFloat() / oldModifier.modifier * modifier.modifier).toInt().toString()
settings.edit()
.putString(
"weight_goal",
Settings.WEIGHT_GOAL,
value
)
.apply()

View File

@ -10,10 +10,10 @@ import com.dzeio.openhealth.databinding.DialogAddWeightBinding
import com.dzeio.openhealth.ui.home.HomeViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collect
@AndroidEntryPoint
class AddWeightDialog : BaseDialog<HomeViewModel, DialogAddWeightBinding>(HomeViewModel::class.java) {
class AddWeightDialog :
BaseDialog<HomeViewModel, DialogAddWeightBinding>(HomeViewModel::class.java) {
override val bindingInflater: (LayoutInflater) -> DialogAddWeightBinding = DialogAddWeightBinding::inflate

View File

@ -2,7 +2,11 @@ package com.dzeio.openhealth.ui.weight
import android.content.SharedPreferences
import android.os.Bundle
import android.view.*
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
@ -36,10 +40,16 @@ class ListWeightFragment :
// FIXME: deprecated
setHasOptionsMenu(true)
if (viewModel.goalWeight != null) {
if (viewModel.goalWeight.value != null) {
binding.goalButton.setText(R.string.edit_goal)
}
binding.goalButton.setOnClickListener {
findNavController().navigate(
ListWeightFragmentDirections.actionNavListWeightToNavWeightDialog(WeightDialog.DialogTypes.EDIT_GOAL.ordinal)
)
}
val recycler = binding.list
val manager = LinearLayoutManager(requireContext())
@ -70,6 +80,14 @@ class ListWeightFragment :
}
}
viewModel.goalWeight.observe(viewLifecycleOwner) {
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
viewModel.fetchWeights().collectLatest {
updateGraph(it)
}
}
}
GraphUtils.lineChartSetup(
binding.chart,
MaterialColors.getColor(
@ -89,7 +107,7 @@ class ListWeightFragment :
requireView(),
list,
viewModel.weightUnit,
viewModel.goalWeight?.toFloat(),
viewModel.goalWeight.value,
false
)
}

View File

@ -1,23 +1,29 @@
package com.dzeio.openhealth.ui.weight
import android.content.SharedPreferences
import com.dzeio.openhealth.Settings
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.UnitFactory
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class ListWeightViewModel @Inject internal constructor(
private val weightRepository: WeightRepository,
settings: SharedPreferences
private val settings: Configuration
) : BaseViewModel() {
var weightUnit =
UnitFactory.mass(settings.getString("weight_unit", "kilogram") ?: "kilogram")
private val _goalWeight = settings.getFloat(Settings.WEIGHT_GOAL)
val goalWeight: Float? =
(settings.getString("weight_goal", null)?.toFloatOrNull())
var weightUnit =
UnitFactory.mass(settings.getString("weight_unit").value ?: "kilogram")
val goalWeight = _goalWeight.toLiveData()
fun fetchWeights() = weightRepository.getWeights()
fun setWeightGoal(value: Float) {
_goalWeight.value = value
}
}

View File

@ -0,0 +1,111 @@
package com.dzeio.openhealth.ui.weight
import android.graphics.drawable.Drawable
import android.util.Log
import android.view.LayoutInflater
import androidx.navigation.fragment.navArgs
import com.dzeio.openhealth.R
import com.dzeio.openhealth.core.BaseDialog
import com.dzeio.openhealth.databinding.DialogAddWeightBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class WeightDialog :
BaseDialog<WeightDialogViewModel, DialogAddWeightBinding>(WeightDialogViewModel::class.java) {
private val args: WeightDialogArgs by navArgs()
override val bindingInflater: (LayoutInflater) -> DialogAddWeightBinding =
DialogAddWeightBinding::inflate
override fun onBuilderInit(builder: MaterialAlertDialogBuilder) {
super.onBuilderInit(builder)
val dialogType = DialogTypes.values()[args.dialogType]
builder.apply {
setTitle(dialogType.title)
setIcon(dialogType.icon)
setPositiveButton(R.string.validate) { dialog, _ ->
runAction(0)
dialog.dismiss()
}
setNegativeButton(R.string.cancel) { dialog, _ ->
runAction(1)
dialog.cancel()
}
if (dialogType.thirdText != null) {
setNeutralButton(dialogType.thirdText) { dialog, _ ->
runAction(2)
dialog.dismiss()
}
}
}
}
override fun onCreated() {
super.onCreated()
setValue(0f)
if (args.dialogType == DialogTypes.EDIT_GOAL.ordinal) {
Log.d("TAG", viewModel.toString())
Log.d("TAG", viewModel.goalWeight.value.toString())
viewModel.goalWeight.observe(this) {
if (it != null) setValue(it)
}
}
// init form
binding.kg.maxValue = 999
binding.kg.minValue = 0
binding.gram.maxValue = 9
binding.gram.minValue = 0
}
private fun setValue(value: Float) {
Log.d("TAG", "Setting dialog value to $value")
val kg = value.toInt()
val g = (value - kg) * 10
binding.kg.value = kg
binding.gram.value = g.toInt()
}
private fun getValue(): Float {
var finalValue: Float = binding.kg.value.toFloat()
finalValue += binding.gram.value.toFloat() / 10
return finalValue
}
/**
* @param click 0 = validate, 1 = cancel, 2 = third option
*/
private fun runAction(click: Int) {
when (DialogTypes.values()[args.dialogType]) {
DialogTypes.EDIT_GOAL -> {
if (click == 1) {
return
}
if (click == 2) {
viewModel.setWeightGoal(null)
return
}
viewModel.setWeightGoal(getValue())
return
}
}
}
enum class DialogTypes(
val title: String,
val icon: Drawable? = null,
val thirdText: Int? = null
) {
EDIT_GOAL("Edit Goal", null, R.string.goal_remove)
}
}

View File

@ -0,0 +1,27 @@
package com.dzeio.openhealth.ui.weight
import com.dzeio.openhealth.Settings
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.UnitFactory
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class WeightDialogViewModel @Inject internal constructor(
private val weightRepository: WeightRepository,
private val settings: Configuration
) : BaseViewModel() {
private val _goalWeight = settings.getFloat(Settings.WEIGHT_GOAL)
var weightUnit =
UnitFactory.mass(settings.getString("weight_unit").value ?: "kilogram")
val goalWeight = _goalWeight.toLiveData()
fun setWeightGoal(value: Float?) {
_goalWeight.value = value
}
}

View File

@ -0,0 +1,177 @@
package com.dzeio.openhealth.utils
import android.content.SharedPreferences
import android.util.Log
import androidx.core.content.edit
import com.dzeio.openhealth.Application
import com.dzeio.openhealth.core.Observable
class Configuration(
private val prefs: SharedPreferences
) : SharedPreferences.OnSharedPreferenceChangeListener {
private val cache: HashMap<String, Field<*>> = HashMap()
private companion object {
const val TAG = "${Application.TAG}/Config"
}
init {
prefs.registerOnSharedPreferenceChangeListener(this)
}
fun getString(key: String): StringField {
if (cache[key] == null) {
Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = StringField(key)
} else {
Log.d(TAG, "$key in cache")
}
return cache[key] as StringField
}
fun getLong(key: String): LongField {
if (cache[key] == null) {
Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = LongField(key)
} else {
Log.d(TAG, "$key in cache")
}
return cache[key] as LongField
}
fun getBoolean(key: String): BooleanField {
if (cache[key] == null) {
Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = BooleanField(key)
} else {
Log.d(TAG, "$key in cache")
}
return cache[key] as BooleanField
}
fun getInt(key: String): IntField {
if (cache[key] == null) {
Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = IntField(key)
} else {
Log.d(TAG, "$key in cache")
}
return cache[key] as IntField
}
fun getFloat(key: String): FloatField {
if (cache[key] == null) {
Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = FloatField(key)
} else {
Log.d(TAG, "$key in cache")
}
return cache[key] as FloatField
}
fun getStringSet(key: String): StringSetField {
if (cache[key] == null) {
Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = StringSetField(key)
} else {
Log.d(TAG, "$key in cache")
}
return cache[key] as StringSetField
}
override fun onSharedPreferenceChanged(u: SharedPreferences, key: String) {
Log.d(TAG, "configuration update for key: $key")
cache[key]?.needUpdate = true
cache[key]?.notifyObservers()
}
abstract class Field<T>(
baseValue: T
) : Observable<T>(baseValue) {
abstract fun exists(): Boolean
abstract fun internalGet(): T
abstract fun internalSet(value: T)
var needUpdate = true
override var value: T = baseValue
get() {
if (needUpdate) {
field = if (!exists()) {
null as T
} else {
internalGet()
}
}
return field
}
set(value) {
if (field == value) {
return
}
field = value
internalSet(value)
notifyObservers()
}
}
inner class StringField(
private val key: String,
private val defaultValue: String? = null
) : Field<String?>(defaultValue) {
override fun exists(): Boolean = prefs.contains(key)
override fun internalGet(): String? = prefs.getString(key, defaultValue)
override fun internalSet(value: String?) =
prefs.edit { if (value == null) remove(key) else putString(key, value) }
}
inner class BooleanField(
private val key: String,
private val defaultValue: Boolean = false
) : Field<Boolean?>(defaultValue) {
override fun exists(): Boolean = prefs.contains(key)
override fun internalGet(): Boolean = prefs.getBoolean(key, defaultValue)
override fun internalSet(value: Boolean?) =
prefs.edit { if (value == null) remove(key) else putBoolean(key, value) }
}
inner class IntField(
private val key: String,
private val defaultValue: Int = -1
) : Field<Int?>(defaultValue) {
override fun exists(): Boolean = prefs.contains(key)
override fun internalGet(): Int = prefs.getInt(key, defaultValue)
override fun internalSet(value: Int?) =
prefs.edit { if (value == null) remove(key) else putInt(key, value) }
}
inner class FloatField(
private val key: String,
private val defaultValue: Float = -1f
) : Field<Float?>(defaultValue) {
override fun exists(): Boolean = prefs.contains(key)
override fun internalGet(): Float = prefs.getFloat(key, defaultValue)
override fun internalSet(value: Float?) =
prefs.edit { if (value == null) remove(key) else putFloat(key, value) }
}
inner class LongField(
private val key: String,
private val defaultValue: Long = -1
) : Field<Long?>(defaultValue) {
override fun exists(): Boolean = prefs.contains(key)
override fun internalGet(): Long = prefs.getLong(key, defaultValue)
override fun internalSet(value: Long?) =
prefs.edit { if (value == null) remove(key) else putLong(key, value) }
}
inner class StringSetField(
private val key: String,
private val defaultValue: MutableSet<String>? = null
) : Field<MutableSet<String>?>(defaultValue) {
override fun exists(): Boolean = prefs.contains(key)
override fun internalGet(): MutableSet<String>? = prefs.getStringSet(key, defaultValue)
override fun internalSet(value: MutableSet<String>?) =
prefs.edit { if (value == null) remove(key) else putStringSet(key, value) }
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<android.widget.NumberPicker
android:id="@+id/kg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<android.widget.NumberPicker
android:id="@+id/gram"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:progress="0" />
</LinearLayout>

View File

@ -4,6 +4,10 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
android:label="@string/app_name"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right"
app:startDestination="@+id/nav_home">
<fragment
@ -13,18 +17,10 @@
tools:layout="@layout/fragment_home">
<action
android:id="@+id/action_nav_home_to_nav_list_weight"
app:destination="@id/nav_list_weight"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right" />
app:destination="@id/nav_list_weight" />
<action
android:id="@+id/action_nav_home_to_nav_water_home"
app:destination="@id/nav_water_home"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right" />
app:destination="@id/nav_water_home" />
<action
android:id="@+id/action_nav_home_to_nav_add_weight_dialog"
app:destination="@id/nav_add_weight_dialog" />
@ -47,14 +43,13 @@
tools:layout="@layout/fragment_list_weight">
<action
android:id="@+id/action_nav_list_weight_to_nav_edit_weight"
app:destination="@id/nav_edit_weight"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right" />
app:destination="@id/nav_edit_weight" />
<action
android:id="@+id/action_nav_list_weight_to_nav_add_weight_dialog"
app:destination="@id/nav_add_weight_dialog" />
<action
android:id="@+id/action_nav_list_weight_to_nav_weight_dialog"
app:destination="@id/nav_weight_dialog" />
</fragment>
<fragment
@ -76,27 +71,15 @@
tools:layout="@layout/fragment_main_water_home">
<action
android:id="@+id/action_nav_water_home_to_nav_water_edit"
app:destination="@id/nav_water_edit"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right" />
app:destination="@id/nav_water_edit" />
<action
android:id="@+id/action_nav_water_home_to_nav_water_size_dialog"
app:destination="@id/nav_water_size_dialog"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right" />
app:destination="@id/nav_water_size_dialog" />
</fragment>
<dialog
android:id="@+id/nav_water_size_dialog"
android:name="com.dzeio.openhealth.ui.water.WaterSizeSelectorDialog"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right"
tools:layout="@layout/dialog_water_size_selector">
</dialog>
@ -104,10 +87,6 @@
<dialog
android:id="@+id/nav_add_weight_dialog"
android:name="com.dzeio.openhealth.ui.weight.AddWeightDialog"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right"
tools:layout="@layout/dialog_water_size_selector">
</dialog>
@ -115,21 +94,13 @@
<fragment
android:id="@+id/nav_settings"
android:name="com.dzeio.openhealth.ui.settings.SettingsFragment"
android:label="@string/page_settings"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right">
android:label="@string/page_settings">
</fragment>
<fragment
android:id="@+id/nav_water_edit"
android:name="com.dzeio.openhealth.ui.water.EditWaterDialog"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right"
tools:layout="@layout/dialog_water_edit_water">
<argument
@ -141,10 +112,6 @@
<fragment
android:id="@+id/nav_extension"
android:name="com.dzeio.openhealth.ui.extension.ExtensionFragment"
app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right"
tools:layout="@layout/fragment_extension">
<argument
@ -184,4 +151,15 @@
android:name="com.dzeio.openhealth.ui.steps.StepsHomeFragment"
android:label="@string/menu_steps"
tools:layout="@layout/fragment_steps_home" />
<dialog
android:id="@+id/nav_weight_dialog"
android:name="com.dzeio.openhealth.ui.weight.WeightDialog"
tools:layout="@layout/dialog_weight"
>
<argument
android:name="dialog_type"
app:argType="integer" />
</dialog>
</navigation>

View File

@ -36,6 +36,7 @@
<string name="menu_browse">Browse</string>
<string name="menu_activity">Activity</string>
<string name="add_goal">Ajouter un objectif</string>
<string name="goal_remove">Supprimer l\'objectif</string>
<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>

View File

@ -47,6 +47,7 @@
<string name="menu_activity">Activity</string>
<string name="add_goal">Add Goal</string>
<string name="goal_remove">Remove 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="edit_daily_goal">Modifiy daily goal</string>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<locale android:name="en"/>
<locale android:name="fr"/>
<locale android:name="en" />
<locale android:name="fr" />
</locale-config>

View File

@ -22,7 +22,7 @@
android:title="Height" />
<EditTextPreference
android:key="weight_goal"
android:key="com.dzeio.open-health.weight.goal"
android:selectAllOnFocus="true"
android:singleLine="true"
android:digits="0123456789"