mirror of
https://github.com/dzeiocom/OpenHealth.git
synced 2025-06-12 17:19:18 +00:00
@ -51,6 +51,12 @@ android {
|
||||
versionName "1.0.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
// Languages
|
||||
def locales = ["en", "fr"]
|
||||
|
||||
buildConfigField "String[]", "LOCALES", "new String[]{\""+locales.join("\",\"")+"\"}"
|
||||
resConfigs locales
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@ -143,4 +149,4 @@ dependencies {
|
||||
testImplementation "androidx.room:room-testing:$room_version"
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">OpenHealth - Debug</string>
|
||||
</resources>
|
||||
<string name="app_name" translatable="false">OpenHealth - Debug</string>
|
||||
</resources>
|
||||
|
@ -1,8 +1,13 @@
|
||||
package com.dzeio.openhealth
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Resources
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import java.util.Locale
|
||||
|
||||
@HiltAndroidApp
|
||||
class Application : Application() {
|
||||
@ -15,5 +20,16 @@ class Application : Application() {
|
||||
|
||||
// Android Dynamics Colors
|
||||
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||
|
||||
// Change application Language based on setting
|
||||
val preferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val lang = preferences.getString("global_language", Locale.getDefault().language)
|
||||
val locale = Locale(lang)
|
||||
Locale.setDefault(locale)
|
||||
|
||||
val overrideConfiguration = baseContext.resources.configuration
|
||||
overrideConfiguration.locale = locale
|
||||
val context: Context = createConfigurationContext(overrideConfiguration)
|
||||
val resources: Resources = context.getResources()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
WorkManager.getInstance(this)
|
||||
.cancelAllWork()
|
||||
WaterReminderService.setup(this)
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
@ -107,7 +106,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
Log.e("MainActivity", "Error Creating Notification Channel", e)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,9 +123,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
)
|
||||
true
|
||||
}
|
||||
R.id.action_about -> {
|
||||
navController.navigate(
|
||||
HomeFragmentDirections.actionNavHomeToAboutFragment()
|
||||
)
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class WaterAdapter() : BaseAdapter<Water, LayoutItemListBinding>() {
|
||||
position: Int
|
||||
) {
|
||||
holder.binding.value.text = "${item.value}ml"
|
||||
holder.binding.datetime.text = "${item.formatTimestamp()} ${item.timestamp}"
|
||||
holder.binding.datetime.text = "${item.formatTimestamp()}"
|
||||
holder.binding.edit.setOnClickListener {
|
||||
onItemClick?.invoke(item)
|
||||
}
|
||||
|
@ -6,8 +6,11 @@ import com.dzeio.openhealth.core.BaseAdapter
|
||||
import com.dzeio.openhealth.core.BaseViewHolder
|
||||
import com.dzeio.openhealth.data.weight.Weight
|
||||
import com.dzeio.openhealth.databinding.LayoutItemListBinding
|
||||
import com.dzeio.openhealth.units.WeightUnit
|
||||
|
||||
class WeightAdapter() : BaseAdapter<Weight, LayoutItemListBinding>() {
|
||||
class WeightAdapter : BaseAdapter<Weight, LayoutItemListBinding>() {
|
||||
|
||||
var unit: WeightUnit = WeightUnit.KG
|
||||
|
||||
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> LayoutItemListBinding
|
||||
get() = LayoutItemListBinding::inflate
|
||||
@ -19,10 +22,11 @@ class WeightAdapter() : BaseAdapter<Weight, LayoutItemListBinding>() {
|
||||
item: Weight,
|
||||
position: Int
|
||||
) {
|
||||
holder.binding.value.text = "${item.weight}kg"
|
||||
val weightTxt = String.format("%.1f", item.weight * unit.fromKG)
|
||||
holder.binding.value.text = "$weightTxt${unit.unit}"
|
||||
holder.binding.datetime.text = item.formatTimestamp()
|
||||
holder.binding.edit.setOnClickListener {
|
||||
onItemClick?.invoke(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +1,14 @@
|
||||
package com.dzeio.openhealth.core
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.viewbinding.ViewBinding
|
||||
|
||||
abstract class BaseFragment<VM : BaseViewModel, VB : ViewBinding>(private val viewModelClass: Class<VM>) : Fragment() {
|
||||
abstract class BaseFragment<VM : BaseViewModel, VB : ViewBinding>(
|
||||
private val viewModelClass: Class<VM>
|
||||
) :
|
||||
BaseStaticFragment<VB>() {
|
||||
|
||||
val viewModel by lazy {
|
||||
ViewModelProvider(this)[viewModelClass]
|
||||
}
|
||||
|
||||
private var _binding: VB? = null
|
||||
val binding get() = _binding!!
|
||||
|
||||
/**
|
||||
* Setup everything!
|
||||
*/
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
||||
_binding = bindingInflater(inflater, container, false)
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to inflate the Fragment Bindings
|
||||
*
|
||||
* use like this: `ViewBinding::inflater`
|
||||
*/
|
||||
abstract val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> VB
|
||||
|
||||
/**
|
||||
* Destroy binding
|
||||
*/
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package com.dzeio.openhealth.core
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewbinding.ViewBinding
|
||||
|
||||
abstract class BaseStaticFragment<VB : ViewBinding> : Fragment() {
|
||||
|
||||
private var _binding: VB? = null
|
||||
val binding get() = _binding!!
|
||||
|
||||
/**
|
||||
* Setup everything!
|
||||
*/
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
||||
_binding = bindingInflater(inflater, container, false)
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to inflate the Fragment Bindings
|
||||
*
|
||||
* use like this: `ViewBinding::inflater`
|
||||
*/
|
||||
abstract val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> VB
|
||||
|
||||
/**
|
||||
* Destroy binding
|
||||
*/
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
22
app/src/main/java/com/dzeio/openhealth/di/SystemModule.kt
Normal file
22
app/src/main/java/com/dzeio/openhealth/di/SystemModule.kt
Normal file
@ -0,0 +1,22 @@
|
||||
package com.dzeio.openhealth.di
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.PreferenceManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Module
|
||||
class SystemModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideSettings(@ApplicationContext context: Context): SharedPreferences {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||
}
|
||||
}
|
143
app/src/main/java/com/dzeio/openhealth/graphs/WeightChart.kt
Normal file
143
app/src/main/java/com/dzeio/openhealth/graphs/WeightChart.kt
Normal file
@ -0,0 +1,143 @@
|
||||
package com.dzeio.openhealth.graphs
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import com.dzeio.openhealth.data.weight.Weight
|
||||
import com.dzeio.openhealth.units.Units
|
||||
import com.dzeio.openhealth.utils.GraphUtils
|
||||
import com.github.mikephil.charting.charts.LineChart
|
||||
import com.github.mikephil.charting.components.LimitLine
|
||||
import com.github.mikephil.charting.components.YAxis
|
||||
import com.github.mikephil.charting.data.Entry
|
||||
import com.github.mikephil.charting.data.LineData
|
||||
import com.github.mikephil.charting.data.LineDataSet
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
object WeightChart {
|
||||
fun setup(
|
||||
chart: LineChart,
|
||||
view: View,
|
||||
data: List<Weight>,
|
||||
modifier: Units.Mass,
|
||||
goal: Float?,
|
||||
limit: Boolean = true
|
||||
) {
|
||||
GraphUtils.lineChartSetup(
|
||||
chart,
|
||||
MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
),
|
||||
MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorOnBackground
|
||||
)
|
||||
)
|
||||
|
||||
if (data.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
// Axis Max/Min
|
||||
var axisMin = max(data.minOf { it.weight } - 10, 0f)
|
||||
var axisMax = data.maxOf { it.weight } + 10
|
||||
|
||||
if (goal != null) {
|
||||
axisMax = max(axisMax, goal)
|
||||
axisMin = min(axisMin, goal)
|
||||
}
|
||||
|
||||
// Average calculation
|
||||
val averageCalculation = min(30, max(3, data.size / 2))
|
||||
val isEven = averageCalculation % 2 == 1
|
||||
val midValue = averageCalculation / 2
|
||||
|
||||
val averageYs = data.mapIndexed { index, entry ->
|
||||
var minItem = index - midValue
|
||||
var maxItem = index + if (!isEven) midValue + 1 else midValue
|
||||
val lastEntry = data.size - 1
|
||||
if (minItem < 0) {
|
||||
maxItem += kotlin.math.abs(minItem)
|
||||
minItem = 0
|
||||
}
|
||||
if (maxItem >= lastEntry) {
|
||||
val diff = maxItem - lastEntry
|
||||
minItem = max(0, minItem - diff)
|
||||
maxItem -= diff
|
||||
}
|
||||
|
||||
var average = 0f
|
||||
for (i in minItem..maxItem) {
|
||||
average += data[i].weight
|
||||
}
|
||||
|
||||
return@mapIndexed Entry(
|
||||
entry.timestamp.toFloat(),
|
||||
(average / (maxItem - minItem + 1)) * modifier.modifier
|
||||
)
|
||||
}
|
||||
|
||||
val rawData = GraphUtils.lineDataSet(
|
||||
LineDataSet(
|
||||
data.mapIndexed { _, weight ->
|
||||
return@mapIndexed Entry(
|
||||
weight.timestamp.toFloat(),
|
||||
weight.weight * modifier.modifier
|
||||
)
|
||||
},
|
||||
"Weight"
|
||||
)
|
||||
).apply {
|
||||
axisDependency = YAxis.AxisDependency.RIGHT
|
||||
}
|
||||
|
||||
val averageData = GraphUtils.lineDataSet(LineDataSet(averageYs, "Average")).apply {
|
||||
axisDependency = YAxis.AxisDependency.RIGHT
|
||||
color = Color.GREEN
|
||||
}
|
||||
|
||||
val entries = ArrayList<Entry>()
|
||||
for (item in data) {
|
||||
entries.add(
|
||||
Entry(
|
||||
item.timestamp.toFloat(),
|
||||
item.weight * modifier.modifier
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
chart.apply {
|
||||
|
||||
this.data = LineData(rawData, averageData)
|
||||
|
||||
val twoWeeks = (data[data.size - 1].timestamp - data[0].timestamp) > 1290000000f
|
||||
|
||||
if (twoWeeks && limit) {
|
||||
// idk what I did but it works lol
|
||||
setVisibleXRange(
|
||||
0f, data[data.size - 1].timestamp / 1000f
|
||||
)
|
||||
|
||||
axisRight.axisMinimum = axisMin * modifier.modifier
|
||||
axisRight.axisMaximum = axisMax * modifier.modifier
|
||||
|
||||
// BIS... :(
|
||||
// Also it invalidate the view so I don't have to call invalidate
|
||||
moveViewToX(data[data.size - 1].timestamp - 1290000000f)
|
||||
}
|
||||
|
||||
if (goal != null) {
|
||||
val limit = LimitLine(goal * modifier.modifier)
|
||||
limit.lineColor = Color.RED
|
||||
val dash = 30f
|
||||
limit.enableDashedLine(dash, dash, 1f)
|
||||
limit.lineWidth = 1f
|
||||
limit.textColor = Color.BLACK
|
||||
|
||||
axisRight.addLimitLine(limit)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,5 +6,5 @@ enum class NotificationChannels(
|
||||
val importance: Int
|
||||
) {
|
||||
// 3 is IMPORTANCE_DEFAULT
|
||||
DEFAULT("openhealth_default", "Default Channel", 3)
|
||||
}
|
||||
WATER("water", "Water Notifications", 3)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.navigation.NavDeepLinkBuilder
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkerParameters
|
||||
import com.dzeio.openhealth.Application
|
||||
@ -42,23 +43,24 @@ class WaterReminderService(
|
||||
Log.d(TAG, "Ran! ${Date().toLocaleString()}")
|
||||
with(NotificationManagerCompat.from(context)) {
|
||||
val flag =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_IMMUTABLE else 0
|
||||
val intent = NavDeepLinkBuilder(context)
|
||||
.setGraph(R.navigation.mobile_navigation)
|
||||
.setDestination(R.id.nav_home)
|
||||
// Will nav to water home when there will be a way to add it there
|
||||
// .setDestination(R.id.nav_water_home)
|
||||
.createTaskStackBuilder()
|
||||
.getPendingIntent(0, flag)
|
||||
val builder =
|
||||
NotificationCompat.Builder(context, NotificationChannels.DEFAULT.channelName)
|
||||
NotificationCompat.Builder(context, NotificationChannels.WATER.id)
|
||||
.setContentTitle("Did you drink?")
|
||||
.setContentText("Drink now! ${Date().toLocaleString()}")
|
||||
.setSmallIcon(R.drawable.ic_logo_small)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
Intent(context, MainActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
},
|
||||
flag
|
||||
)
|
||||
).build()
|
||||
intent
|
||||
)
|
||||
.build()
|
||||
notify(
|
||||
NotificationIds.WaterIntake.ordinal,
|
||||
builder
|
||||
@ -66,4 +68,4 @@ class WaterReminderService(
|
||||
}
|
||||
return Result.success()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
package com.dzeio.openhealth.ui.about
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import com.dzeio.openhealth.BuildConfig
|
||||
import com.dzeio.openhealth.R
|
||||
import com.dzeio.openhealth.core.BaseStaticFragment
|
||||
import com.dzeio.openhealth.databinding.FragmentAboutBinding
|
||||
|
||||
class AboutFragment : BaseStaticFragment<FragmentAboutBinding>() {
|
||||
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentAboutBinding
|
||||
get() = FragmentAboutBinding::inflate
|
||||
|
||||
@SuppressLint("StringFormatInvalid")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.version.text =
|
||||
resources.getString(R.string.version_number, BuildConfig.VERSION_NAME)
|
||||
|
||||
binding.contactUs.setOnClickListener {
|
||||
openLink("mailto:context.openhealth@dze.io")
|
||||
}
|
||||
|
||||
binding.github.setOnClickListener {
|
||||
openLink("https://github.com/dzeiocom/OpenHealth")
|
||||
}
|
||||
}
|
||||
|
||||
private fun openLink(url: String) {
|
||||
try {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Toast.makeText(requireContext(), "Could not handle link $url", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
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.Color
|
||||
import android.graphics.RectF
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
@ -13,74 +13,61 @@ import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.dzeio.openhealth.Application
|
||||
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.graphs.WeightChart
|
||||
import com.dzeio.openhealth.ui.weight.AddWeightDialog
|
||||
import com.dzeio.openhealth.units.UnitFactory
|
||||
import com.dzeio.openhealth.utils.DrawUtils
|
||||
import com.dzeio.openhealth.utils.GraphUtils
|
||||
import com.github.mikephil.charting.components.LimitLine
|
||||
import com.github.mikephil.charting.components.YAxis
|
||||
import com.github.mikephil.charting.data.Entry
|
||||
import com.github.mikephil.charting.data.LineData
|
||||
import com.github.mikephil.charting.data.LineDataSet
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.min
|
||||
import kotlin.properties.Delegates
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
|
||||
@AndroidEntryPoint
|
||||
class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewModel::class.java) {
|
||||
|
||||
companion object {
|
||||
const val TAG = "${Application.TAG}/HomeFragment"
|
||||
}
|
||||
|
||||
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHomeBinding
|
||||
get() = FragmentHomeBinding::inflate
|
||||
|
||||
private var intake by Delegates.notNull<Float>()
|
||||
private val settings: SharedPreferences by lazy {
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// Bindings
|
||||
binding.addWeight.setOnClickListener {
|
||||
AddWeightDialog().show(requireActivity().supportFragmentManager, null)
|
||||
}
|
||||
|
||||
binding.fragmentHomeWaterAdd.setOnClickListener {
|
||||
|
||||
val water = viewModel.water.value
|
||||
|
||||
if (water == null) {
|
||||
|
||||
if (water == null || !water.isToday()) {
|
||||
val w = Water()
|
||||
w.value = 200
|
||||
w.value = viewModel.waterCupSize
|
||||
viewModel.updateWater(w)
|
||||
} else {
|
||||
water.value += 200
|
||||
water.value += viewModel.waterCupSize
|
||||
viewModel.updateWater(water)
|
||||
}
|
||||
}
|
||||
|
||||
intake = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
.getString("water_intake", "1200")?.toFloat() ?: 1200f
|
||||
|
||||
binding.fragmentHomeWaterTotal.text = "${intake.toInt()}ml"
|
||||
|
||||
binding.fragmentHomeWaterRemove.setOnClickListener { _ ->
|
||||
binding.fragmentHomeWaterTotal.text =
|
||||
String.format(
|
||||
resources.getString(viewModel.waterUnit.unit),
|
||||
viewModel.dailyWaterIntake
|
||||
)
|
||||
|
||||
binding.fragmentHomeWaterRemove.setOnClickListener {
|
||||
val water = viewModel.water.value
|
||||
|
||||
if (water != null) {
|
||||
|
||||
water.value -= 200
|
||||
if (water.value == 0) {
|
||||
water.value -= viewModel.waterCupSize
|
||||
if (water.value <= 0) {
|
||||
viewModel.deleteWater(water)
|
||||
} else {
|
||||
viewModel.updateWater(water)
|
||||
@ -88,22 +75,6 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
}
|
||||
}
|
||||
|
||||
binding.fragmentHomeWaterRemove.setOnClickListener {
|
||||
lifecycleScope.launch {
|
||||
|
||||
val item = viewModel.fetchTodayWater().first()
|
||||
Log.d(TAG, "Collected latest $it")
|
||||
if (item != null) {
|
||||
item.value -= 200
|
||||
if (item.value == 0) {
|
||||
viewModel.deleteWater(item)
|
||||
} else {
|
||||
viewModel.updateWater(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.listWeight.setOnClickListener {
|
||||
findNavController().navigate(HomeFragmentDirections.actionNavHomeToNavListWeight())
|
||||
}
|
||||
@ -126,32 +97,13 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
}
|
||||
|
||||
private fun updateGraph(list: List<Weight>) {
|
||||
if (list.isNotEmpty()) {
|
||||
val entries = ArrayList<Entry>()
|
||||
for (item in list) {
|
||||
entries.add(Entry(item.timestamp.toFloat(), item.weight))
|
||||
}
|
||||
|
||||
val dataSet = LineDataSet(entries, "Label").apply {
|
||||
axisDependency = YAxis.AxisDependency.RIGHT
|
||||
setDrawCircles(false)
|
||||
setDrawCircleHole(false)
|
||||
mode = LineDataSet.Mode.HORIZONTAL_BEZIER
|
||||
}
|
||||
|
||||
binding.weightGraph.apply {
|
||||
|
||||
// Apply new dataset
|
||||
|
||||
data = LineData(dataSet)
|
||||
|
||||
// idk what I did but it works lol
|
||||
setVisibleXRange(
|
||||
0f, entries[entries.size - 1].x / 1000f
|
||||
)
|
||||
|
||||
val goal = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
.getString("weight_goal", null)?.toFloatOrNull()
|
||||
WeightChart.setup(
|
||||
binding.weightGraph,
|
||||
requireView(),
|
||||
list,
|
||||
viewModel.weightUnit,
|
||||
viewModel.goalWeight?.toFloat()
|
||||
)
|
||||
|
||||
// legend.apply {
|
||||
// isEnabled = true
|
||||
@ -165,29 +117,6 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
// setCustom(arrayOf(legendEntry))
|
||||
// }
|
||||
// }
|
||||
|
||||
setDrawBorders(false)
|
||||
|
||||
// BIS... :(
|
||||
// Also it invalidate the view so I don't have to call invalidate
|
||||
moveViewToX(entries[entries.size - 1].x - 1600000000f)
|
||||
|
||||
if (goal != null) {
|
||||
axisRight.axisMinimum = goal
|
||||
val limit = LimitLine(goal)
|
||||
limit.lineColor = Color.RED
|
||||
val dash = 30f
|
||||
limit.enableDashedLine(dash, dash, 0f)
|
||||
limit.lineWidth = 1f
|
||||
limit.textColor = Color.BLACK
|
||||
limit.textSize = 12f
|
||||
|
||||
axisRight.addLimitLine(limit)
|
||||
} else {
|
||||
isAutoScaleMinMaxEnabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
@ -197,23 +126,28 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
viewModel.fetchWeights().collectLatest {
|
||||
updateGraph(it)
|
||||
}
|
||||
updateWater(0)
|
||||
updateWater(1234)
|
||||
updateWater(0, 1)
|
||||
}
|
||||
|
||||
viewModel.water.observe(viewLifecycleOwner) {
|
||||
Log.d(TAG, "${it?.formatTimestamp()} $it")
|
||||
if (it != null) {
|
||||
updateWater(it.value)
|
||||
updateWater(0, it.value)
|
||||
} else {
|
||||
updateWater(0)
|
||||
updateWater(0, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWater(water: Int) {
|
||||
val oldValue = binding.fragmentHomeWaterCurrent.text.toString().replace("ml", "").toInt()
|
||||
binding.fragmentHomeWaterCurrent.text = "${water}ml"
|
||||
private fun updateWater(oldValue: Int, newValue: Int) {
|
||||
|
||||
val waterUnit =
|
||||
UnitFactory.volume(settings.getString("water_unit", "milliliter") ?: "Milliliter")
|
||||
|
||||
binding.fragmentHomeWaterCurrent.text =
|
||||
String.format(
|
||||
resources.getString(waterUnit.unit),
|
||||
(newValue * waterUnit.modifier).toInt()
|
||||
)
|
||||
|
||||
var width = 1500
|
||||
var height = 750
|
||||
@ -260,25 +194,27 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
3f
|
||||
)
|
||||
|
||||
Log.d("Test", "${min(oldValue.toFloat(), intake)} ${min(water.toFloat(), intake)}")
|
||||
ValueAnimator.ofFloat(min(oldValue.toFloat(), intake), min(water.toFloat(), intake))
|
||||
.apply {
|
||||
duration = 300
|
||||
addUpdateListener {
|
||||
DrawUtils.drawArc(
|
||||
canvas,
|
||||
100 * it.animatedValue as Float / intake,
|
||||
rect,
|
||||
MaterialColors.getColor(
|
||||
requireView(),
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
),
|
||||
6f
|
||||
)
|
||||
canvas.save()
|
||||
binding.background.setImageBitmap(graph)
|
||||
}
|
||||
start()
|
||||
ValueAnimator.ofInt(
|
||||
min(oldValue, viewModel.dailyWaterIntake),
|
||||
min(newValue, viewModel.dailyWaterIntake)
|
||||
).apply {
|
||||
duration = 300
|
||||
addUpdateListener {
|
||||
|
||||
DrawUtils.drawArc(
|
||||
canvas,
|
||||
100 * it.animatedValue as Int / viewModel.dailyWaterIntake.toFloat(),
|
||||
rect,
|
||||
MaterialColors.getColor(
|
||||
requireView(),
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
),
|
||||
6f
|
||||
)
|
||||
canvas.save()
|
||||
binding.background.setImageBitmap(graph)
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,62 @@
|
||||
package com.dzeio.openhealth.ui.home
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.dzeio.openhealth.Application.Companion.TAG
|
||||
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 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
|
||||
private val waterRepository: WaterRepository,
|
||||
settings: SharedPreferences
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val _water = MutableLiveData<Water?>(null)
|
||||
val water: LiveData<Water?> = _water
|
||||
|
||||
var waterCupSize = settings.getInt("water_cup_size", 200)
|
||||
|
||||
var waterUnit =
|
||||
UnitFactory.volume(settings.getString("water_unit", "milliliter") ?: "Milliliter")
|
||||
|
||||
var weightUnit =
|
||||
UnitFactory.mass(settings.getString("weight_unit", "kilogram") ?: "kilogram")
|
||||
|
||||
val goalWeight: Int? =
|
||||
(settings.getString("weight_goal", null)?.toIntOrNull())
|
||||
|
||||
val dailyWaterIntake: Int =
|
||||
((settings.getString("water_intake", "1200")?.toFloatOrNull() ?: 1200f) * waterUnit.modifier)
|
||||
.toInt()
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
waterRepository.todayWater().collectLatest {
|
||||
_water.value = it
|
||||
}
|
||||
}
|
||||
// don't listen for prefs changes
|
||||
settings.registerOnSharedPreferenceChangeListener { _, key ->
|
||||
Log.d(TAG, "Pref changed: $key")
|
||||
when (key) {
|
||||
"water_cup_size" -> {
|
||||
waterCupSize = settings.getInt("water_cup_size", 200)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,7 +64,6 @@ class HomeViewModel @Inject internal constructor(
|
||||
*/
|
||||
fun fetchWeights() = weightRepository.getWeights()
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@ -44,11 +75,7 @@ class HomeViewModel @Inject internal constructor(
|
||||
|
||||
suspend fun addWeight(weight: Weight) = weightRepository.addWeight(weight)
|
||||
|
||||
suspend fun fetchTodayWater() = waterRepository.todayWater()
|
||||
|
||||
private val _water = MutableLiveData<Water?>(null)
|
||||
val water: LiveData<Water?> = _water
|
||||
|
||||
fun fetchTodayWater() = waterRepository.todayWater()
|
||||
|
||||
fun updateWater(water: Water) {
|
||||
viewModelScope.launch {
|
||||
@ -62,4 +89,4 @@ class HomeViewModel @Inject internal constructor(
|
||||
_water.postValue(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,99 @@
|
||||
package com.dzeio.openhealth.ui.settings
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.text.InputType
|
||||
import android.util.Log
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.dzeio.openhealth.BuildConfig
|
||||
import com.dzeio.openhealth.R
|
||||
import com.dzeio.openhealth.units.UnitFactory
|
||||
import java.util.Locale
|
||||
|
||||
class SettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
val settings: SharedPreferences by lazy {
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences, rootKey)
|
||||
|
||||
// Force only numbers on Goal
|
||||
val weightGoal = findPreference<EditTextPreference>("weight_goal")
|
||||
weightGoal?.setOnBindEditTextListener {
|
||||
it.inputType = InputType.TYPE_CLASS_NUMBER
|
||||
weightGoal?.apply {
|
||||
setOnBindEditTextListener {
|
||||
it.inputType = InputType.TYPE_CLASS_NUMBER
|
||||
}
|
||||
val value = settings.getString("weight_goal", null)
|
||||
val modifier = UnitFactory.mass(settings.getString("weight_unit", null) ?: "kilogram")
|
||||
if (value != null && value.isNotEmpty()) {
|
||||
text = (value.toFloat() * modifier.modifier).toString()
|
||||
}
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val alue = ((newValue as String).toInt() / modifier.modifier).toInt().toString()
|
||||
settings.edit()
|
||||
.putString(
|
||||
"weight_goal",
|
||||
alue
|
||||
)
|
||||
.apply()
|
||||
text = alue
|
||||
return@setOnPreferenceChangeListener false
|
||||
}
|
||||
}
|
||||
|
||||
// 251 kg
|
||||
// 553 lb
|
||||
|
||||
findPreference<ListPreference>("weight_unit")?.apply {
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val unit = settings.getString("weight_unit", "kilogram")
|
||||
?: return@setOnPreferenceChangeListener true
|
||||
val goal = settings.getString("weight_goal", null)
|
||||
?: return@setOnPreferenceChangeListener true
|
||||
val modifier = UnitFactory.mass(newValue as String)
|
||||
val oldModifier = UnitFactory.mass(unit)
|
||||
val value =
|
||||
(goal.toFloat() / oldModifier.modifier * modifier.modifier).toInt().toString()
|
||||
settings.edit()
|
||||
.putString(
|
||||
"weight_goal",
|
||||
value
|
||||
)
|
||||
.apply()
|
||||
weightGoal?.text = value
|
||||
return@setOnPreferenceChangeListener true
|
||||
}
|
||||
}
|
||||
|
||||
val languagesPreference = findPreference<ListPreference>("global_language")
|
||||
Log.d("TAG", Locale.getDefault().language)
|
||||
languagesPreference?.apply {
|
||||
entries = BuildConfig.LOCALES
|
||||
entryValues = BuildConfig.LOCALES
|
||||
setDefaultValue(Locale.getDefault().language)
|
||||
}
|
||||
|
||||
// Update App Locale
|
||||
languagesPreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||
val locale = Locale(newValue as String)
|
||||
Locale.setDefault(locale)
|
||||
val config = Configuration()
|
||||
config.locale = locale
|
||||
|
||||
requireActivity().baseContext.resources.updateConfiguration(
|
||||
config,
|
||||
requireActivity().baseContext.resources.displayMetrics
|
||||
)
|
||||
|
||||
requireActivity().recreate()
|
||||
|
||||
return@setOnPreferenceChangeListener true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,6 @@ class EditWaterDialog :
|
||||
|
||||
water.timestamp = tsp
|
||||
binding.date.setText(water.formatTimestamp())
|
||||
|
||||
}
|
||||
datePicker.show(fragManager, "dialog")
|
||||
Log.d("Tag", "${date.year + 1900}, ${date.month}, ${date.day}")
|
||||
@ -88,8 +87,6 @@ class EditWaterDialog :
|
||||
} else {
|
||||
TODO("VERSION.SDK_INT < N")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
viewModel.init(args.id)
|
||||
@ -133,6 +130,5 @@ class EditWaterDialog :
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
package com.dzeio.openhealth.ui.water
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.dzeio.openhealth.Application.Companion.TAG
|
||||
import com.dzeio.openhealth.adapters.WaterAdapter
|
||||
import com.dzeio.openhealth.core.BaseFragment
|
||||
import com.dzeio.openhealth.databinding.FragmentMainWaterHomeBinding
|
||||
@ -17,9 +15,6 @@ import com.github.mikephil.charting.data.BarDataSet
|
||||
import com.github.mikephil.charting.data.BarEntry
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.TimeZone
|
||||
|
||||
@AndroidEntryPoint
|
||||
class WaterHomeFragment :
|
||||
@ -62,6 +57,10 @@ class WaterHomeFragment :
|
||||
)
|
||||
)
|
||||
|
||||
binding.buttonEditDefaultIntake.setOnClickListener {
|
||||
findNavController().navigate(WaterHomeFragmentDirections.actionNavWaterHomeToNavWaterSizeDialog())
|
||||
}
|
||||
|
||||
chart.xAxis.valueFormatter = GraphUtils.DateValueFormatter(1000 * 60 * 60 * 24)
|
||||
|
||||
viewModel.items.observe(viewLifecycleOwner) { list ->
|
||||
|
@ -1,13 +1,102 @@
|
||||
package com.dzeio.openhealth.ui.water
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import com.dzeio.openhealth.R
|
||||
import com.dzeio.openhealth.core.BaseDialog
|
||||
import com.dzeio.openhealth.databinding.DialogWaterSizeSelectorBinding
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class WaterSizeSelectorDialog :
|
||||
BaseDialog<WaterSizeSelectorViewModel, DialogWaterSizeSelectorBinding>(
|
||||
WaterSizeSelectorViewModel::class.java
|
||||
) {
|
||||
|
||||
override val bindingInflater: (LayoutInflater) -> DialogWaterSizeSelectorBinding
|
||||
get() = DialogWaterSizeSelectorBinding::inflate
|
||||
|
||||
override fun onCreated() {
|
||||
super.onCreated()
|
||||
|
||||
binding.cancel.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.validate.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
viewModel.cupSize.observe(this) {
|
||||
binding.customSizeText.text = String.format(
|
||||
getString(R.string.custom_amount),
|
||||
"${it}ml"
|
||||
)
|
||||
binding.size100ml.setBackgroundColor(Color.TRANSPARENT)
|
||||
binding.size250ml.setBackgroundColor(Color.TRANSPARENT)
|
||||
binding.size500ml.setBackgroundColor(Color.TRANSPARENT)
|
||||
binding.size1000ml.setBackgroundColor(Color.TRANSPARENT)
|
||||
binding.customSize.setBackgroundColor(Color.TRANSPARENT)
|
||||
val back = resources.getColor(
|
||||
com.google.android.material.R.color.material_dynamic_primary95,
|
||||
)
|
||||
when (it) {
|
||||
100 -> {
|
||||
binding.size100ml.setBackgroundColor(back)
|
||||
}
|
||||
250 -> {
|
||||
binding.size250ml.setBackgroundColor(back)
|
||||
}
|
||||
500 -> {
|
||||
binding.size500ml.setBackgroundColor(back)
|
||||
}
|
||||
1000 -> {
|
||||
binding.size1000ml.setBackgroundColor(back)
|
||||
}
|
||||
else -> {
|
||||
binding.customSize.setBackgroundColor(back)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.size100ml.setOnClickListener {
|
||||
viewModel.setCupSize(100)
|
||||
}
|
||||
binding.size250ml.setOnClickListener {
|
||||
viewModel.setCupSize(250)
|
||||
}
|
||||
binding.size500ml.setOnClickListener {
|
||||
viewModel.setCupSize(500)
|
||||
}
|
||||
binding.size1000ml.setOnClickListener {
|
||||
viewModel.setCupSize(1000)
|
||||
}
|
||||
|
||||
binding.customSize.setOnClickListener {
|
||||
val editTextLayout = TextInputLayout(requireContext())
|
||||
|
||||
val editText = TextInputEditText(requireContext())
|
||||
editText.setText(viewModel.cupSize.value.toString())
|
||||
|
||||
editTextLayout.addView(editText)
|
||||
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setView(editTextLayout)
|
||||
.setTitle("Custom Cup Size")
|
||||
.setOnCancelListener {
|
||||
it.dismiss()
|
||||
}
|
||||
.setPositiveButton(
|
||||
R.string.validate
|
||||
) { dialog, _ ->
|
||||
viewModel.setCupSize(editText.text.toString().toInt())
|
||||
dismiss()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,32 @@
|
||||
package com.dzeio.openhealth.ui.water
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.dzeio.openhealth.core.BaseViewModel
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
class WaterSizeSelectorViewModel : BaseViewModel() {
|
||||
@HiltViewModel
|
||||
class WaterSizeSelectorViewModel @Inject constructor(
|
||||
private val settings: SharedPreferences
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val _cupSize = MutableLiveData(0)
|
||||
|
||||
val cupSize = _cupSize
|
||||
|
||||
init {
|
||||
val cup = settings.getInt("water_cup_size", -1)
|
||||
if (cup != -1) {
|
||||
_cupSize.value = cup
|
||||
}
|
||||
}
|
||||
|
||||
fun setCupSize(value: Int) {
|
||||
settings.edit()
|
||||
.putInt("water_cup_size", value)
|
||||
.apply()
|
||||
|
||||
_cupSize.value = value
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ class AddWeightDialog : BaseDialog<HomeViewModel, DialogAddWeightBinding>(HomeVi
|
||||
setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.cancel()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +39,7 @@ class AddWeightDialog : BaseDialog<HomeViewModel, DialogAddWeightBinding>(HomeVi
|
||||
viewModel.lastWeight().collect {
|
||||
if (it != null) {
|
||||
binding.kg.value = it.weight.toInt()
|
||||
binding.gram.value = ((it.weight - it.weight.toInt()) * 10 ).toInt()
|
||||
binding.gram.value = ((it.weight - it.weight.toInt()) * 10).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -56,12 +55,11 @@ class AddWeightDialog : BaseDialog<HomeViewModel, DialogAddWeightBinding>(HomeVi
|
||||
val weight = Weight().apply {
|
||||
weight = binding.kg.value + (binding.gram.value.toFloat() / 10)
|
||||
source = "OpenHealth"
|
||||
|
||||
}
|
||||
lifecycleScope.launchWhenCreated {
|
||||
viewModel.addWeight(weight)
|
||||
}
|
||||
//callback?.invoke()
|
||||
// callback?.invoke()
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,24 @@ package com.dzeio.openhealth.ui.weight
|
||||
|
||||
import android.os.Bundle
|
||||
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
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.dzeio.openhealth.R
|
||||
import com.dzeio.openhealth.adapters.WeightAdapter
|
||||
import com.dzeio.openhealth.core.BaseFragment
|
||||
import com.dzeio.openhealth.data.weight.Weight
|
||||
import com.dzeio.openhealth.databinding.FragmentListWeightBinding
|
||||
import com.dzeio.openhealth.graphs.WeightChart
|
||||
import com.dzeio.openhealth.ui.home.HomeViewModel
|
||||
import com.dzeio.openhealth.units.WeightUnit
|
||||
import com.dzeio.openhealth.utils.GraphUtils
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
|
||||
@ -21,33 +30,82 @@ class ListWeightFragment :
|
||||
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentListWeightBinding =
|
||||
FragmentListWeightBinding::inflate
|
||||
|
||||
val settings by lazy {
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
val recycler = binding.list
|
||||
|
||||
val manager = LinearLayoutManager(requireContext())
|
||||
recycler.layoutManager = manager
|
||||
|
||||
val adapter = WeightAdapter()
|
||||
|
||||
val unit = settings.getString("weight_unit", "Kilogram") ?: "Kilogram"
|
||||
|
||||
adapter.unit = WeightUnit.fromSettings(unit)
|
||||
|
||||
adapter.onItemClick = {
|
||||
findNavController().navigate(
|
||||
ListWeightFragmentDirections.actionNavListWeightToNavEditWeight(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
//EditWeightDialog().show(requireActivity().supportFragmentManager, "dialog")
|
||||
// EditWeightDialog().show(requireActivity().supportFragmentManager, "dialog")
|
||||
}
|
||||
recycler.adapter = adapter
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
|
||||
viewModel.fetchWeights().collectLatest {
|
||||
updateGraph(it)
|
||||
val itt = it.toMutableList()
|
||||
itt.sortWith { o1, o2 -> if (o1.timestamp > o2.timestamp) -1 else 1 }
|
||||
adapter.set(itt)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GraphUtils.lineChartSetup(
|
||||
binding.chart,
|
||||
MaterialColors.getColor(
|
||||
requireView(),
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
),
|
||||
MaterialColors.getColor(
|
||||
requireView(),
|
||||
com.google.android.material.R.attr.colorOnBackground
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateGraph(list: List<Weight>) {
|
||||
WeightChart.setup(
|
||||
binding.chart,
|
||||
requireView(),
|
||||
list,
|
||||
viewModel.weightUnit,
|
||||
viewModel.goalWeight?.toFloat(),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
menu.findItem(R.id.action_add).isVisible = true
|
||||
|
||||
super.onPrepareOptionsMenu(menu)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.action_add -> {
|
||||
findNavController().navigate(ListWeightFragmentDirections.actionNavListWeightToNavAddWeightDialog())
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
20
app/src/main/java/com/dzeio/openhealth/units/UnitFactory.kt
Normal file
20
app/src/main/java/com/dzeio/openhealth/units/UnitFactory.kt
Normal file
@ -0,0 +1,20 @@
|
||||
package com.dzeio.openhealth.units
|
||||
|
||||
object UnitFactory {
|
||||
fun mass(unit: String): Units.Mass {
|
||||
return when (unit.lowercase()) {
|
||||
"kilogram", "kilograms", "kg" -> Units.Mass.KILOGRAM
|
||||
"pound", "pounds", "lb" -> Units.Mass.POUND
|
||||
else -> Units.Mass.KILOGRAM
|
||||
}
|
||||
}
|
||||
|
||||
fun volume(unit: String): Units.Volume {
|
||||
return when (unit.lowercase()) {
|
||||
"milliliter", "milliliters", "ml" -> Units.Volume.MILLILITER
|
||||
"imperial ounce", "imperial ounces", "oz" -> Units.Volume.IMPERIAL_OUNCE
|
||||
"us ounce", "us ounces" -> Units.Volume.US_OUNCE
|
||||
else -> Units.Volume.MILLILITER
|
||||
}
|
||||
}
|
||||
}
|
57
app/src/main/java/com/dzeio/openhealth/units/Units.kt
Normal file
57
app/src/main/java/com/dzeio/openhealth/units/Units.kt
Normal file
@ -0,0 +1,57 @@
|
||||
package com.dzeio.openhealth.units
|
||||
|
||||
import com.dzeio.openhealth.R
|
||||
|
||||
object Units {
|
||||
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(
|
||||
0.45359237f,
|
||||
R.string.unit_mass_pound_name_singular,
|
||||
R.string.unit_mass_pound_name_plural,
|
||||
R.string.unit_mass_pound_unit
|
||||
)
|
||||
}
|
||||
|
||||
enum class Volume(
|
||||
/**
|
||||
* Value based on the Kilogram
|
||||
*/
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
21
app/src/main/java/com/dzeio/openhealth/units/WaterUnit.kt
Normal file
21
app/src/main/java/com/dzeio/openhealth/units/WaterUnit.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package com.dzeio.openhealth.units
|
||||
|
||||
enum class WaterUnit(
|
||||
val unit: String,
|
||||
val fromML: Float
|
||||
) {
|
||||
ML("ml", 1f),
|
||||
US_OZ("oz", 0.03381413f),
|
||||
IMP_OZ("oz", 0.03519503f);
|
||||
|
||||
companion object {
|
||||
fun fromSettings(value: String): WaterUnit {
|
||||
return when (value.lowercase()) {
|
||||
"milliliter" -> ML
|
||||
"us ounce" -> US_OZ
|
||||
"imperial ounce" -> IMP_OZ
|
||||
else -> ML
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
app/src/main/java/com/dzeio/openhealth/units/WeightUnit.kt
Normal file
19
app/src/main/java/com/dzeio/openhealth/units/WeightUnit.kt
Normal file
@ -0,0 +1,19 @@
|
||||
package com.dzeio.openhealth.units
|
||||
|
||||
enum class WeightUnit(
|
||||
val unit: String,
|
||||
val fromKG: Float
|
||||
) {
|
||||
KG("kg", 1f),
|
||||
LBS("lbs", 2.2046226218488f);
|
||||
|
||||
companion object {
|
||||
fun fromSettings(value: String): WeightUnit {
|
||||
return when (value.lowercase()) {
|
||||
"kilogram" -> KG
|
||||
"pounds" -> LBS
|
||||
else -> KG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import com.github.mikephil.charting.components.Description
|
||||
import com.github.mikephil.charting.components.XAxis
|
||||
import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData
|
||||
import com.github.mikephil.charting.data.Entry
|
||||
import com.github.mikephil.charting.data.LineDataSet
|
||||
import com.github.mikephil.charting.formatter.ValueFormatter
|
||||
import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet
|
||||
import java.text.SimpleDateFormat
|
||||
@ -21,6 +22,14 @@ object GraphUtils {
|
||||
// chart.isAutoScaleMinMaxEnabled = true
|
||||
}
|
||||
|
||||
fun lineDataSet(lineDataSet: LineDataSet): LineDataSet {
|
||||
return lineDataSet.apply {
|
||||
setDrawCircles(false)
|
||||
setDrawCircleHole(false)
|
||||
mode = LineDataSet.Mode.HORIZONTAL_BEZIER
|
||||
}
|
||||
}
|
||||
|
||||
fun barChartSetup(chart: BarChart, mainColor: Int, textColor: Int) {
|
||||
barLineChartSetup(chart, mainColor, textColor)
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 9.0 KiB |
10
app/src/main/res/drawable/ic_baseline_line_style_24.xml
Normal file
10
app/src/main/res/drawable/ic_baseline_line_style_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,16h5v-2H3V16zM9.5,16h5v-2h-5V16zM16,16h5v-2h-5V16zM3,20h2v-2H3V20zM7,20h2v-2H7V20zM11,20h2v-2h-2V20zM15,20h2v-2h-2V20zM19,20h2v-2h-2V20zM3,12h8v-2H3V12zM13,12h8v-2h-8V12zM3,4v4h18V4H3z"/>
|
||||
</vector>
|
49
app/src/main/res/drawable/ic_logo_full.xml
Normal file
49
app/src/main/res/drawable/ic_logo_full.xml
Normal file
File diff suppressed because one or more lines are too long
10
app/src/main/res/drawable/ic_logo_github.xml
Normal file
10
app/src/main/res/drawable/ic_logo_github.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:pathData="M10.9,2.1c-4.6,0.5 -8.3,4.2 -8.8,8.7c-0.5,4.7 2.2,8.9 6.3,10.5C8.7,21.4 9,21.2 9,20.8v-1.6c0,0 -0.4,0.1 -0.9,0.1c-1.4,0 -2,-1.2 -2.1,-1.9c-0.1,-0.4 -0.3,-0.7 -0.6,-1C5.1,16.3 5,16.3 5,16.2C5,16 5.3,16 5.4,16c0.6,0 1.1,0.7 1.3,1c0.5,0.8 1.1,1 1.4,1c0.4,0 0.7,-0.1 0.9,-0.2c0.1,-0.7 0.4,-1.4 1,-1.8c-2.3,-0.5 -4,-1.8 -4,-4c0,-1.1 0.5,-2.2 1.2,-3C7.1,8.8 7,8.3 7,7.6C7,7.2 7,6.6 7.3,6c0,0 1.4,0 2.8,1.3C10.6,7.1 11.3,7 12,7s1.4,0.1 2,0.3C15.3,6 16.8,6 16.8,6C17,6.6 17,7.2 17,7.6c0,0.8 -0.1,1.2 -0.2,1.4c0.7,0.8 1.2,1.8 1.2,3c0,2.2 -1.7,3.5 -4,4c0.6,0.5 1,1.4 1,2.3v2.6c0,0.3 0.3,0.6 0.7,0.5c3.7,-1.5 6.3,-5.1 6.3,-9.3C22,6.1 16.9,1.4 10.9,2.1z"
|
||||
android:fillColor="@android:color/white"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_edit_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_edit_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M14.06,9.02l0.92,0.92L5.92,19L5,19v-0.92l9.06,-9.06M17.66,3c-0.25,0 -0.51,0.1 -0.7,0.29l-1.83,1.83 3.75,3.75 1.83,-1.83c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.2,-0.2 -0.45,-0.29 -0.71,-0.29zM14.06,6.19L3,17.25L3,21h3.75L17.81,9.94l-3.75,-3.75z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_free_breakfast_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_free_breakfast_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M4,19h16v2L4,21zM20,3L4,3v10c0,2.21 1.79,4 4,4h6c2.21,0 4,-1.79 4,-4v-3h2c1.11,0 2,-0.9 2,-2L22,5c0,-1.11 -0.89,-2 -2,-2zM16,13c0,1.1 -0.9,2 -2,2L8,15c-1.1,0 -2,-0.9 -2,-2L6,5h10v8zM20,8h-2L18,5h2v3z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_local_drink_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_local_drink_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,2l2.01,18.23C5.13,21.23 5.97,22 7,22h10c1.03,0 1.87,-0.77 1.99,-1.77L21,2L3,2zM17,20l-10,0.01L5.89,10L18.1,10L17,20zM18.33,8L5.67,8l-0.44,-4h13.53l-0.43,4zM12,19c1.66,0 3,-1.34 3,-3 0,-2 -3,-5.4 -3,-5.4S9,14 9,16c0,1.66 1.34,3 3,3zM12,13.91c0.59,0.91 1,1.73 1,2.09 0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1c0,-0.37 0.41,-1.19 1,-2.09z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_mail_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_mail_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M22,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6zM20,6l-8,4.99L4,6h16zM20,18L4,18L4,8l8,5 8,-5v10z"/>
|
||||
</vector>
|
@ -1,7 +1,182 @@
|
||||
<?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:orientation="vertical"
|
||||
android:padding="24dp"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_outline_local_drink_24" />
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.Material3.HeadlineSmall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:textAlignment="center"
|
||||
android:text="@string/switch_cup_size" />
|
||||
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/size_100ml"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_outline_local_drink_24" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="100ml" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/size_250ml"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_outline_local_drink_24" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="250ml" />
|
||||
</LinearLayout>
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/size_500ml"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_outline_local_drink_24" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="500ml" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/size_1000ml"
|
||||
android:layout_marginStart="8dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_outline_local_drink_24" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="1000ml" />
|
||||
</LinearLayout>
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/custom_size"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/material_dynamic_primary90"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_outline_edit_24" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/custom_size_text"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/custom_amount"
|
||||
tools:text="Custom amount: 100ml" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@android:string/cancel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/validate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/validate" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
65
app/src/main/res/layout/fragment_about.xml
Normal file
65
app/src/main/res/layout/fragment_about.xml
Normal file
@ -0,0 +1,65 @@
|
||||
<?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:layout_margin="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:layout_margin="32dp"
|
||||
app:srcCompat="@drawable/ic_logo_full" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/tagline"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/version"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="8dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/version_number"
|
||||
app:drawableStartCompat="@drawable/ic_baseline_extension_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/github"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="8dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/about_star_on_github"
|
||||
app:drawableStartCompat="@drawable/ic_logo_github" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/contact_us"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="8dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/contact_us"
|
||||
app:drawableStartCompat="@drawable/ic_outline_mail_24" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/licenses"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="8dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/licenses"
|
||||
app:drawableStartCompat="@drawable/ic_baseline_line_style_24" />
|
||||
|
||||
</LinearLayout>
|
@ -15,7 +15,7 @@
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="?attr/materialCardViewFilledStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
@ -40,7 +40,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Weight" />
|
||||
android:text="@string/water_intake" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
@ -48,12 +48,6 @@
|
||||
android:layout_weight="1"
|
||||
android:gravity="end">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:src="@drawable/ic_baseline_add_24" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/goto_water_home"
|
||||
android:layout_width="24dp"
|
||||
@ -75,7 +69,7 @@
|
||||
android:id="@+id/fragment_home_water_remove"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:src="@drawable/ic_outline_hexagon_24"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/linearLayout"
|
||||
@ -98,7 +92,7 @@
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="900ml"
|
||||
android:text="@string/unit_volume_milliliter_unit"
|
||||
android:textAlignment="center" />
|
||||
|
||||
|
||||
@ -107,7 +101,7 @@
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="1200ml"
|
||||
android:text="@string/unit_volume_milliliter_unit"
|
||||
android:textAlignment="center" />
|
||||
|
||||
</LinearLayout>
|
||||
@ -117,7 +111,7 @@
|
||||
android:id="@+id/fragment_home_water_add"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_weight="1"
|
||||
android:src="@drawable/ic_baseline_add_24"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/linearLayout"
|
||||
@ -180,7 +174,7 @@
|
||||
style="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Weight"
|
||||
android:text="@string/weight"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<LinearLayout
|
||||
@ -193,7 +187,7 @@
|
||||
android:id="@+id/add_weight"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:src="@drawable/ic_baseline_add_24" />
|
||||
|
||||
<ImageView
|
||||
@ -203,7 +197,6 @@
|
||||
android:src="@drawable/ic_outline_hexagon_24" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
@ -212,18 +205,8 @@
|
||||
android:layout_height="200dp"
|
||||
android:minHeight="200dp" />
|
||||
|
||||
<!-- <com.jjoe64.graphview.GraphView-->
|
||||
<!-- android:id="@+id/weight_graph"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="200dp"-->
|
||||
<!-- android:minHeight="200dp"-->
|
||||
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@+id/constraintLayout2" />-->
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
@ -1,14 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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:clipToPadding="false"
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="?attr/materialCardViewFilledStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp">
|
||||
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
android:id="@+id/chart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:minHeight="200dp" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:clipToPadding="false"
|
||||
android:id="@+id/list"
|
||||
android:padding="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
tools:listitem="@layout/layout_item_list"
|
||||
tools:context=".ui.weight.ListWeightFragment" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
tools:listitem="@layout/layout_item_list"
|
||||
tools:context=".ui.weight.ListWeightFragment" />
|
@ -1,35 +0,0 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/nav_header_height"
|
||||
android:background="@drawable/side_nav_bar"
|
||||
android:gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/nav_header_desc"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
app:srcCompat="@mipmap/ic_launcher_round" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
android:text="@string/nav_header_title"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/nav_header_subtitle" />
|
||||
</LinearLayout>
|
@ -1,16 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_add"
|
||||
android:visible="false"
|
||||
android:icon="@drawable/ic_baseline_add_24"
|
||||
android:title="@string/add"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="ifRoom"
|
||||
android:title="@string/page_settings"
|
||||
android:icon="@drawable/ic_baseline_settings_24"/>
|
||||
<item
|
||||
android:id="@+id/action_extensions"
|
||||
android:title="@string/menu_extensions"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/ic_baseline_extension_24"
|
||||
/>
|
||||
</menu>
|
||||
android:icon="@drawable/ic_baseline_extension_24" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_about"
|
||||
android:title="@string/about" />
|
||||
</menu>
|
||||
|
@ -38,6 +38,12 @@
|
||||
app:exitAnim="@android:anim/slide_out_right"
|
||||
app:popEnterAnim="@android:anim/slide_in_left"
|
||||
app:popExitAnim="@android:anim/slide_out_right" />
|
||||
<action
|
||||
android:id="@+id/action_nav_home_to_nav_add_weight_dialog"
|
||||
app:destination="@id/nav_add_weight_dialog" />
|
||||
<action
|
||||
android:id="@+id/action_nav_home_to_aboutFragment"
|
||||
app:destination="@id/aboutFragment" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
@ -53,7 +59,7 @@
|
||||
<fragment
|
||||
android:id="@+id/nav_list_weight"
|
||||
android:name="com.dzeio.openhealth.ui.weight.ListWeightFragment"
|
||||
android:label="@string/menu_list_weight"
|
||||
android:label="@string/weight"
|
||||
tools:layout="@layout/fragment_list_weight" >
|
||||
<action
|
||||
android:id="@+id/action_nav_list_weight_to_nav_edit_weight"
|
||||
@ -62,6 +68,9 @@
|
||||
app:exitAnim="@android:anim/slide_out_right"
|
||||
app:popEnterAnim="@android:anim/slide_in_left"
|
||||
app:popExitAnim="@android:anim/slide_out_right" />
|
||||
<action
|
||||
android:id="@+id/action_nav_list_weight_to_nav_add_weight_dialog"
|
||||
app:destination="@id/nav_add_weight_dialog" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
@ -88,11 +97,45 @@
|
||||
app:exitAnim="@android:anim/slide_out_right"
|
||||
app:popEnterAnim="@android:anim/slide_in_left"
|
||||
app:popExitAnim="@android:anim/slide_out_right" />
|
||||
<action
|
||||
android:id="@+id/action_nav_water_home_to_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"
|
||||
tools:layout="@layout/dialog_water_size_selector"
|
||||
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">
|
||||
|
||||
</dialog>
|
||||
|
||||
<dialog
|
||||
android:id="@+id/nav_add_weight_dialog"
|
||||
android:name="com.dzeio.openhealth.ui.weight.AddWeightDialog"
|
||||
tools:layout="@layout/dialog_water_size_selector"
|
||||
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">
|
||||
|
||||
</dialog>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_settings"
|
||||
android:name="com.dzeio.openhealth.ui.settings.SettingsFragment">
|
||||
android:label="@string/page_settings"
|
||||
android:name="com.dzeio.openhealth.ui.settings.SettingsFragment"
|
||||
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">
|
||||
|
||||
</fragment>
|
||||
|
||||
@ -125,4 +168,9 @@
|
||||
app:argType="string" />
|
||||
|
||||
</fragment>
|
||||
</navigation>
|
||||
<fragment
|
||||
android:id="@+id/aboutFragment"
|
||||
android:name="com.dzeio.openhealth.ui.about.AboutFragment"
|
||||
android:label="AboutFragment"
|
||||
tools:layout="@layout/fragment_about"/>
|
||||
</navigation>
|
||||
|
34
app/src/main/res/values-fr/strings.xml
Normal file
34
app/src/main/res/values-fr/strings.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="unit_mass_kilogram_name_singular">Kilograme</string>
|
||||
<string name="unit_mass_kilogram_name_plural">Kilogrames</string>
|
||||
<string name="unit_mass_pound_name_singular">Livre</string>
|
||||
<string name="unit_mass_pound_name_plural">Livres</string>
|
||||
<string name="unit_volume_milliliter_name_singular">Millilitre</string>
|
||||
<string name="unit_volume_milliliter_name_plural">Millilitres</string>
|
||||
<string name="unit_volume_imperial_ounce_name_singular">Once Impérial</string>
|
||||
<string name="unit_volume_imperial_ounce_name_plural">OncesImpérial</string>
|
||||
<string name="unit_volume_us_ounce_name_singular">Once États Unis</string>
|
||||
<string name="unit_volume_us_ounce_name_plural">Onces États Unis</string>
|
||||
<string name="extension_informations">Les importations sont faites au démarrage de l\'application\nLes exports sont faits lorsque qu\'il y a des nouvelles valeurs dans l\'application</string>
|
||||
<string name="menu_home">Accueil</string>
|
||||
<string name="page_settings">Paramètres</string>
|
||||
<string name="nav_water_home">Truc D\'eau</string>
|
||||
<string name="languages">Langages</string>
|
||||
<string name="settings_global">Paramètres Globaux</string>
|
||||
<string name="weight">Poids</string>
|
||||
<string name="water_intake">Consomation d\'eau</string>
|
||||
<string name="switch_cup_size">Changer la taille du verre</string>
|
||||
<string name="validate">Valider</string>
|
||||
<string name="custom_amount">Montant personnalisée: %1$s</string>
|
||||
<string name="menu_import">Importer</string>
|
||||
<string name="menu_edit_weight">Changer le poid</string>
|
||||
<string name="menu_extensions">Extensions</string>
|
||||
<string name="tagline">Ton Application de santé libre, open source et respectueuse de la vie privée</string>
|
||||
<string name="add">Ajouter</string>
|
||||
<string name="about">A Propos</string>
|
||||
<string name="version_number" formatted="false">Version %1$</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>
|
||||
</resources>
|
@ -4,8 +4,13 @@
|
||||
<item>Male</item>
|
||||
<item>Female</item>
|
||||
</string-array>
|
||||
<string-array name="water_units">
|
||||
<item>Millimeters</item>
|
||||
<item>Ounces</item>
|
||||
<string-array name="weight_units">
|
||||
<item name="kg">@string/unit_mass_kilogram_name_plural</item>
|
||||
<item name="lb">@string/unit_mass_pound_name_singular</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
<string-array name="water_units">
|
||||
<item name="ml">@string/unit_volume_milliliter_name_singular</item>
|
||||
<item name="us_oz">@string/unit_volume_imperial_ounce_name_singular</item>
|
||||
<item name="im_oz">@string/unit_volume_us_ounce_name_singular</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
@ -1,20 +1,44 @@
|
||||
<resources>
|
||||
<string name="app_name">OpenHealth</string>
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
<string name="nav_header_title">Android Studio</string>
|
||||
<string name="nav_header_subtitle">android.studio@android.com</string>
|
||||
<string name="nav_header_desc">Navigation header</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="app_name" translatable="false">OpenHealth</string>
|
||||
<string name="tagline">Your privacy-friendly FOSS Health Application </string>
|
||||
<string name="page_settings">Settings</string>
|
||||
|
||||
<string name="menu_home">Home</string>
|
||||
<string name="menu_gallery">Gallery</string>
|
||||
<string name="menu_slideshow">Slideshow</string>
|
||||
<string name="menu_import">Import</string>
|
||||
<string name="menu_list_weight">Weight List</string>
|
||||
<string name="menu_edit_weight">Edit Weight</string>
|
||||
<string name="nav_list_water">Water Intake</string>
|
||||
<string name="nav_water_home">Water Intake</string>
|
||||
<string name="menu_extensions">Extensions</string>
|
||||
<string name="extension_informations">Imports are done at app startup\nExports are done when new inputs are give to the app</string>
|
||||
</resources>
|
||||
|
||||
<!-- 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_pound_name_singular">Pound</string>
|
||||
<string name="unit_mass_pound_name_plural">Pounds</string>
|
||||
<string name="unit_mass_pound_unit" translatable="false">%1$slb</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_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="languages">Languages</string>
|
||||
<string name="settings_global">Global Settings</string>
|
||||
<string name="weight">Weight</string>
|
||||
<string name="water_intake">Water Intake</string>
|
||||
<string name="switch_cup_size">Switch cup size</string>
|
||||
<string name="validate">Validate</string>
|
||||
<string name="custom_amount">Custom amount: %1$s</string>
|
||||
<string name="add">Add</string>
|
||||
<string name="about">About</string>
|
||||
<string name="version_number" formatted="false">Version %1$s</string>
|
||||
<string name="about_star_on_github">Star on Github</string>
|
||||
<string name="contact_us">Contact us</string>
|
||||
<string name="licenses">Licenses</string>
|
||||
</resources>
|
||||
|
@ -1,13 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceCategory android:title="Global Settings">
|
||||
<PreferenceCategory android:title="@string/settings_global">
|
||||
<ListPreference
|
||||
android:defaultValue="Male"
|
||||
android:entries="@array/genders"
|
||||
android:entryValues="@array/genders"
|
||||
android:key="global_gender"
|
||||
android:title="Gender" />
|
||||
|
||||
<ListPreference
|
||||
android:key="global_language"
|
||||
android:title="@string/languages" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="Weight Settings">
|
||||
|
||||
@ -24,6 +28,14 @@
|
||||
android:digits="0123456789"
|
||||
android:inputType="numberDecimal"
|
||||
android:title="Goal Weight" />
|
||||
<ListPreference
|
||||
android:defaultValue="1"
|
||||
android:entries="@array/weight_units"
|
||||
android:entryValues="@array/weight_units"
|
||||
android:key="weight_unit"
|
||||
android:title="Weight Unit" />
|
||||
|
||||
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="Water Settings">
|
||||
|
||||
|
Reference in New Issue
Block a user