1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-06-15 10:09:19 +00:00
This commit is contained in:
2021-12-24 00:18:34 +01:00
parent e5615c9463
commit 7844eec09a
29 changed files with 626 additions and 121 deletions

4
.idea/misc.xml generated
View File

@ -22,16 +22,20 @@
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/dialog_add_weight.xml" value="0.2604166666666667" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/dialog_add_weight.xml" value="0.2604166666666667" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/dialog_edit_weight.xml" value="0.33" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/dialog_edit_weight.xml" value="0.33" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/dialog_register_weight.xml" value="0.5" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/dialog_register_weight.xml" value="0.5" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/dialog_water_edit_water.xml" value="0.2674772036474164" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_extensions.xml" value="0.55" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_gallery.xml" value="0.3109375" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_gallery.xml" value="0.3109375" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_home.xml" value="0.6845493562231759" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_home.xml" value="0.6845493562231759" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_import.xml" value="0.55" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_import.xml" value="0.55" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_list_weight.xml" value="0.33" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_list_weight.xml" value="0.33" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_main_water_home.xml" value="0.225" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_water_home.xml" value="0.55" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_water_home.xml" value="0.55" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/layout_item_weight.xml" value="0.5" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/layout_item_weight.xml" value="0.5" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/nav_header_main.xml" value="0.3109375" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/layout/nav_header_main.xml" value="0.3109375" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/menu/activity_main_drawer.xml" value="0.39947916666666666" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/menu/activity_main_drawer.xml" value="0.39947916666666666" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/menu/fullscreen_dialog.xml" value="0.40185185185185185" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/menu/fullscreen_dialog.xml" value="0.40185185185185185" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/menu/main.xml" value="0.39947916666666666" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/menu/main.xml" value="0.39947916666666666" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/xml/preferences.xml" value="0.55" />
</map> </map>
</option> </option>
</component> </component>

View File

@ -50,6 +50,9 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
// Settings
implementation "androidx.preference:preference-ktx:1.1.1"
// DataStore // DataStore
implementation "androidx.datastore:datastore:1.0.0" implementation "androidx.datastore:datastore:1.0.0"

View File

@ -9,8 +9,12 @@ import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuItem
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
@ -20,6 +24,8 @@ import com.dzeio.openhealth.core.BaseActivity
import com.dzeio.openhealth.databinding.ActivityMainBinding import com.dzeio.openhealth.databinding.ActivityMainBinding
import com.dzeio.openhealth.interfaces.NotificationChannels import com.dzeio.openhealth.interfaces.NotificationChannels
import com.dzeio.openhealth.services.WaterReminderService import com.dzeio.openhealth.services.WaterReminderService
import com.dzeio.openhealth.ui.home.HomeFragmentDirections
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint @AndroidEntryPoint
@ -40,12 +46,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
val navHostFragment = val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController navController = navHostFragment.navController
binding.navView.setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration( appBarConfiguration = AppBarConfiguration(
setOf( setOf(
R.id.nav_home R.id.nav_home
), binding.drawerLayout )
) )
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
@ -109,4 +114,23 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
} }
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> {
navController.navigate(
HomeFragmentDirections.actionNavHomeToNavSettings()
)
true
}
R.id.action_extensions -> {
navController.navigate(
HomeFragmentDirections.actionNavHomeToNavExtensions()
)
true
}
else -> super.onOptionsItemSelected(item)
}
}
} }

View File

@ -1,4 +1,4 @@
package com.dzeio.openhealth.ui.imports package com.dzeio.openhealth.ui.extensions
import android.app.ProgressDialog import android.app.ProgressDialog
import android.content.Intent import android.content.Intent
@ -16,17 +16,19 @@ import com.dzeio.openhealth.extensions.GoogleFit
//import com.dzeio.openhealth.connectors.GoogleFit //import com.dzeio.openhealth.connectors.GoogleFit
import com.dzeio.openhealth.extensions.samsunghealth.SamsungHealth import com.dzeio.openhealth.extensions.samsunghealth.SamsungHealth
import com.dzeio.openhealth.core.BaseFragment import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.databinding.FragmentImportBinding import com.dzeio.openhealth.databinding.FragmentExtensionsBinding
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint @AndroidEntryPoint
class ImportFragment : BaseFragment<ImportViewModel, FragmentImportBinding>(ImportViewModel::class.java) { class ExtensionsFragment :
BaseFragment<ExtensionsViewModel, FragmentExtensionsBinding>(ExtensionsViewModel::class.java) {
companion object { companion object {
const val TAG = "ImportFragment" const val TAG = "ImportFragment"
} }
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentImportBinding = FragmentImportBinding::inflate override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentExtensionsBinding =
FragmentExtensionsBinding::inflate
private lateinit var progressDialog: ProgressDialog private lateinit var progressDialog: ProgressDialog
@ -111,8 +113,10 @@ class ImportFragment : BaseFragment<ImportViewModel, FragmentImportBinding>(Impo
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, override fun onRequestPermissionsResult(
grantResults: IntArray) { requestCode: Int, permissions: Array<String>,
grantResults: IntArray
) {
when { when {
grantResults.isEmpty() -> { grantResults.isEmpty() -> {
// If user interaction was interrupted, the permission request // If user interaction was interrupted, the permission request

View File

@ -1,4 +1,4 @@
package com.dzeio.openhealth.ui.imports package com.dzeio.openhealth.ui.extensions
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.dzeio.openhealth.core.BaseViewModel import com.dzeio.openhealth.core.BaseViewModel
@ -9,7 +9,7 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class ImportViewModel @Inject internal constructor( class ExtensionsViewModel @Inject internal constructor(
private val weightRepository: WeightRepository private val weightRepository: WeightRepository
) : BaseViewModel() { ) : BaseViewModel() {

View File

@ -11,6 +11,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import com.dzeio.openhealth.Application import com.dzeio.openhealth.Application
import com.dzeio.openhealth.R import com.dzeio.openhealth.R
import com.dzeio.openhealth.core.BaseFragment import com.dzeio.openhealth.core.BaseFragment
@ -35,6 +36,7 @@ import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import kotlin.math.min import kotlin.math.min
import kotlin.properties.Delegates
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewModel::class.java) { class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewModel::class.java) {
@ -46,6 +48,8 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHomeBinding override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHomeBinding
get() = FragmentHomeBinding::inflate get() = FragmentHomeBinding::inflate
private var intake by Delegates.notNull<Float>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -70,6 +74,11 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
} }
} }
intake = PreferenceManager.getDefaultSharedPreferences(requireContext())
.getString("water_intake", "1200")?.toFloat() ?: 1200f
binding.fragmentHomeWaterTotal.text = "${intake.toInt()}ml"
binding.fragmentHomeWaterRemove.setOnClickListener { _ -> binding.fragmentHomeWaterRemove.setOnClickListener { _ ->
val water = viewModel.water.value val water = viewModel.water.value
@ -131,8 +140,9 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
description = Description().apply { isEnabled = false } description = Description().apply { isEnabled = false }
isScaleXEnabled = true isScaleXEnabled = true
setPinchZoom(false) setPinchZoom(false)
axisLeft.setLabelCount(0, true) setDrawGridBackground(false)
setDrawBorders(false) setDrawBorders(false)
axisLeft.setLabelCount(0, true)
xAxis.apply { xAxis.apply {
valueFormatter = object : ValueFormatter() { valueFormatter = object : ValueFormatter() {
@ -196,14 +206,14 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
) )
graph?.let { btmp -> graph?.let { btmp ->
ValueAnimator.ofFloat(min(oldValue.toFloat(), 1200f), min(water.toFloat(), 1200f)) ValueAnimator.ofFloat(min(oldValue.toFloat(), intake), min(water.toFloat(), intake))
.apply { .apply {
duration = 300 duration = 300
addUpdateListener { addUpdateListener {
val canvas = Canvas(btmp) val canvas = Canvas(btmp)
DrawUtils.drawArc( DrawUtils.drawArc(
canvas, canvas,
100 * it.animatedValue as Float / 1200f, 100 * it.animatedValue as Float / intake,
MaterialColors.getColor( MaterialColors.getColor(
requireView(), requireView(),
com.google.android.material.R.attr.colorPrimary com.google.android.material.R.attr.colorPrimary

View File

@ -1,6 +1,5 @@
package com.dzeio.openhealth.ui.home package com.dzeio.openhealth.ui.home
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.dzeio.openhealth.core.BaseViewModel import com.dzeio.openhealth.core.BaseViewModel
@ -9,9 +8,7 @@ import com.dzeio.openhealth.data.water.WaterRepository
import com.dzeio.openhealth.data.weight.Weight import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.data.weight.WeightRepository import com.dzeio.openhealth.data.weight.WeightRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -48,6 +45,7 @@ class HomeViewModel @Inject internal constructor(
waterRepository.addWater(water) waterRepository.addWater(water)
} }
} }
fun deleteWater(item: Water) { fun deleteWater(item: Water) {
viewModelScope.launch { viewModelScope.launch {
waterRepository.deleteWater(item) waterRepository.deleteWater(item)

View File

@ -0,0 +1,11 @@
package com.dzeio.openhealth.ui.settings
import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
import com.dzeio.openhealth.R
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
}
}

View File

@ -0,0 +1,92 @@
package com.dzeio.openhealth.ui.water
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.Window
import androidx.core.content.ContextCompat
import androidx.core.widget.doOnTextChanged
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.dzeio.openhealth.R
import com.dzeio.openhealth.core.BaseFullscreenDialog
import com.dzeio.openhealth.databinding.DialogWaterEditWaterBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class EditWaterDialog :
BaseFullscreenDialog<EditWaterViewModel, DialogWaterEditWaterBinding>(EditWaterViewModel::class.java) {
override val bindingInflater: (LayoutInflater) -> DialogWaterEditWaterBinding =
DialogWaterEditWaterBinding::inflate
private val args: EditWaterDialogArgs by navArgs()
override val isFullscreenLayout = true
var newValue: Int = 0
override fun onDialogInit(dialog: Dialog) {
super.onDialogInit(dialog)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
}
override fun onCreated(savedInstanceState: Bundle?) {
super.onCreated(savedInstanceState)
viewModel.water.observe(viewLifecycleOwner) {
binding.editTextNumber.setText(it.value.toString())
}
binding.editTextNumber.doOnTextChanged { text, start, before, count ->
newValue = text.toString().toInt()
}
viewModel.init(args.id)
}
private fun save() {
val water = viewModel.water.value
water?.let {
it.value = newValue
viewModel.save(it)
}
findNavController().popBackStack()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_fullscreen_dialog_save -> {
save()
true
}
R.id.menu_fullscreen_dialog_delete -> {
MaterialAlertDialogBuilder(requireContext())
.setTitle("Delete Water Intake?")
.setMessage("Are you sure you want to delete this water intake?")
.setPositiveButton("Yes") { _, _ ->
lifecycleScope.launchWhenStarted {
viewModel.delete()
findNavController().popBackStack()
}
}
.setIcon(
ContextCompat.getDrawable(
requireContext(),
R.drawable.ic_outline_delete_24
)
)
.setNegativeButton("No") { _, _ -> }
.show()
true
}
else -> super.onOptionsItemSelected(item)
}
}
}

View File

@ -0,0 +1,39 @@
package com.dzeio.openhealth.ui.water
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.water.WaterRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class EditWaterViewModel @Inject internal constructor(
private val waterRepository: WaterRepository
) : BaseViewModel() {
val water: MutableLiveData<Water> = MutableLiveData()
fun init(id: Long) {
viewModelScope.launch {
waterRepository.getWater(id).collectLatest {
water.postValue(it)
}
}
}
fun delete() {
viewModelScope.launch {
water.value?.let { waterRepository.deleteWater(it) }
}
}
fun save(water: Water) {
viewModelScope.launch {
waterRepository.addWater(water)
}
}
}

View File

@ -1,5 +1,6 @@
package com.dzeio.openhealth.ui.water package com.dzeio.openhealth.ui.water
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -14,8 +15,17 @@ import com.dzeio.openhealth.databinding.FragmentListWeightBinding
import com.dzeio.openhealth.databinding.FragmentMainWaterHomeBinding import com.dzeio.openhealth.databinding.FragmentMainWaterHomeBinding
import com.dzeio.openhealth.ui.home.HomeViewModel import com.dzeio.openhealth.ui.home.HomeViewModel
import com.dzeio.openhealth.ui.weight.ListWeightFragmentDirections import com.dzeio.openhealth.ui.weight.ListWeightFragmentDirections
import com.dzeio.openhealth.utils.GraphUtils
import com.github.mikephil.charting.data.BarData
import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.data.Entry
import com.google.android.material.color.MaterialColors
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.*
@AndroidEntryPoint @AndroidEntryPoint
class WaterHomeFragment : class WaterHomeFragment :
@ -37,16 +47,41 @@ class WaterHomeFragment :
val adapter = WaterAdapter() val adapter = WaterAdapter()
adapter.onItemClick = { adapter.onItemClick = {
findNavController().navigate( findNavController().navigate(
ListWeightFragmentDirections.actionNavListWeightToNavEditWeight( WaterHomeFragmentDirections.actionNavWaterHomeToNavWaterEdit(
it.id it.id
) )
) )
//EditWeightDialog().show(requireActivity().supportFragmentManager, "dialog")
} }
recycler.adapter = adapter recycler.adapter = adapter
viewModel.items.observe(viewLifecycleOwner) { val chart = binding.chart
adapter.set(it)
GraphUtils.barChartSetup(
chart, MaterialColors.getColor(
requireView(),
com.google.android.material.R.attr.colorPrimary
)
)
viewModel.items.observe(viewLifecycleOwner) { list ->
adapter.set(list)
val dataset = BarDataSet(
list.map {
val epoch = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
epoch.time = Date(0)
epoch.add(Calendar.MILLISECOND, it.timestamp.toInt())
return@map BarEntry(
epoch.get(Calendar.DATE).toFloat(),
it.value.toFloat()
)
},
""
)
chart.data = BarData(dataset)
chart.invalidate()
} }
} }
} }

View File

@ -36,22 +36,6 @@ class EditWeightDialog :
lateinit var weight: Weight lateinit var weight: Weight
// override fun onBuilderInit(builder: AlertDialog.Builder) {
// super.onBuilderInit(builder)
//
// builder.apply {
// setTitle("Add your weight (kg)")
// setIcon(activity?.let { ContextCompat.getDrawable(it, R.drawable.ic_outline_timeline_24) })
// setPositiveButton("Validate") { dialog, _ ->
// save()
// }
// setNegativeButton("Cancel") { dialog, _ ->
// dialog.cancel()
// }
//
// }
// }
override fun onDialogInit(dialog: Dialog) { override fun onDialogInit(dialog: Dialog) {
super.onDialogInit(dialog) super.onDialogInit(dialog)

View File

@ -0,0 +1,77 @@
package com.dzeio.openhealth.utils
import android.graphics.Color
import com.github.mikephil.charting.charts.BarChart
import com.github.mikephil.charting.charts.BarLineChartBase
import com.github.mikephil.charting.charts.Chart
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.AxisBase
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.ChartData
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet
import com.github.mikephil.charting.interfaces.datasets.IDataSet
import com.google.android.material.color.MaterialColors
import java.text.SimpleDateFormat
import java.util.*
object GraphUtils {
fun lineChartSetup(chart: LineChart, mainColor: Int) {
barLineChartSetup(chart, mainColor)
}
fun barChartSetup(chart: BarChart, mainColor: Int) {
barLineChartSetup(chart, mainColor)
}
fun <T : BarLineScatterCandleBubbleData<out IBarLineScatterCandleBubbleDataSet<out Entry>>?> barLineChartSetup(chart: BarLineChartBase<T>, mainColor: Int) {
chart.apply {
// Setup
legend.isEnabled = false
description = Description().apply { isEnabled = false }
xAxis.apply {
valueFormatter = object : ValueFormatter() {
override fun getAxisLabel(value: Float, axis: AxisBase?): String {
return SimpleDateFormat(
"yyyy-MM-dd",
Locale.getDefault()
).format(Date(value.toLong()))
//return super.getAxisLabel(value, axis)
}
}
position = XAxis.XAxisPosition.BOTTOM
setDrawGridLines(false)
setLabelCount(3, true)
textColor = Color.WHITE
}
axisLeft.apply {
axisLineColor = mainColor
textColor = Color.WHITE
setLabelCount(0, true)
}
axisRight.apply {
textColor = Color.WHITE
}
setNoDataTextColor(Color.WHITE)
isAutoScaleMinMaxEnabled = true
legend.isEnabled = false
isDragEnabled = true
isScaleYEnabled = false
description = Description().apply { isEnabled = false }
isScaleXEnabled = true
setPinchZoom(false)
//setDrawGridBackground(false)
//setDrawBorders(false)
}
}
}

View 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="M20.5,11H19V7c0,-1.1 -0.9,-2 -2,-2h-4V3.5C13,2.12 11.88,1 10.5,1S8,2.12 8,3.5V5H4c-1.1,0 -1.99,0.9 -1.99,2v3.8H3.5c1.49,0 2.7,1.21 2.7,2.7s-1.21,2.7 -2.7,2.7H2V20c0,1.1 0.9,2 2,2h3.8v-1.5c0,-1.49 1.21,-2.7 2.7,-2.7 1.49,0 2.7,1.21 2.7,2.7V22H17c1.1,0 2,-0.9 2,-2v-4h1.5c1.38,0 2.5,-1.12 2.5,-2.5S21.88,11 20.5,11z"/>
</vector>

View 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="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
</vector>

View File

@ -0,0 +1,25 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M6,6h28v28h-28z"/>
<path
android:pathData="M8.6814,20.6882L10.0932,22.1L13.1424,19.0627L11.7424,17.6509L11.1017,17.0102C10.5915,16.5 10.3186,15.8356 10.3186,15.1119C10.3186,14.4831 10.5322,13.9136 10.9,13.4627C11.3983,12.8339 12.1576,12.4305 13.0119,12.4305C13.7356,12.4305 14.4,12.7153 14.922,13.2255L15.5508,13.8305L16.9627,15.2543L20.0237,12.217L18.6,10.8051L17.9593,10.1882C16.6898,8.9187 14.9458,8.1356 13.0119,8.1356C9.1322,8.1356 6,11.2678 6,15.1238C6,16.0848 6.1898,16.9983 6.5458,17.8407C6.9017,18.6831 7.4119,19.4305 8.0525,20.0593L8.6814,20.6882"
android:fillColor="#EA4335"/>
<path
android:pathData="M15.6695,22.6339L20.0238,18.3034L16.9628,15.2543L13.1424,19.0627L10.0933,22.1L11.7306,23.7492L13.1424,25.1492L14.6136,23.678"
android:fillColor="#FBBC04"/>
<path
android:pathData="M23.061,28.9695L29.9423,22.1L26.8813,19.0627L20.0118,25.9204L16.1915,22.1119L13.1423,25.1492L16.9627,28.9695L16.9508,28.9814L20.0118,31.8644L23.0728,28.9695H23.061Z"
android:fillColor="#34A853"/>
<path
android:pathData="M31.9711,20.0593C33.3948,18.6356 34.2135,16.4525 33.9881,14.2458C33.6559,10.9 30.8796,8.3848 27.5101,8.1593C25.3864,8.0169 23.4406,8.8119 22.0643,10.1881L16.9626,15.2542L20.0118,18.3034L25.1135,13.2254C25.7304,12.6203 26.5847,12.3356 27.4626,12.478C28.6016,12.6559 29.527,13.5932 29.6813,14.7322C29.7999,15.5864 29.5152,16.417 28.9101,17.022L26.8813,19.0627L29.9423,22.1L31.9711,20.0593V20.0593Z"
android:fillColor="#4285F4"/>
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -15,11 +15,14 @@
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
style="?attr/appBarLayoutStyle"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
style="?attr/toolbarStyle"
app:titleCentered="true"
android:layout_height="?attr/actionBarSize" /> android:layout_height="?attr/actionBarSize" />
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
@ -49,11 +52,4 @@
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout> </androidx.drawerlayout.widget.DrawerLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/editTextNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
tools:layout_editor_absoluteX="101dp"
tools:layout_editor_absoluteY="107dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,122 @@
<?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:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.extensions.ExtensionsFragment">
<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:id="@+id/import_google_fit"
android:layout_marginEnd="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:src="@drawable/ic_logo_fit" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="54dp"
android:layout_marginVertical="16dp"
android:gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Google Fit" />
<TextView
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Last Sync: Yesterday" />
</LinearLayout>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:src="@drawable/ic_baseline_extension_24" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/import_samsung_health"
style="?attr/materialCardViewOutlinedStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:src="@drawable/logo_shealth" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="54dp"
android:layout_marginVertical="16dp"
android:gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Samsung Health" />
<TextView
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Currently Unavailable" />
</LinearLayout>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:src="@drawable/ic_baseline_extension_24" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>

View File

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".ui.imports.ImportFragment">
<TextView
android:id="@+id/text_slideshow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.044" />
<Button
android:id="@+id/import_google_fit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Import From Google Fit"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_slideshow" />
<Button
android:id="@+id/import_samsung_health"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Import From Samsung Health"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/import_google_fit" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -22,7 +22,7 @@
<com.github.mikephil.charting.charts.LineChart <com.github.mikephil.charting.charts.BarChart
android:id="@+id/chart" android:id="@+id/chart"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" android:layout_height="200dp"

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_home"
android:icon="@drawable/ic_menu_camera"
android:title="@string/menu_home" />
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="@string/menu_gallery" />
<item
android:id="@+id/nav_import"
android:icon="@drawable/ic_menu_slideshow"
android:title="@string/menu_import" />
</group>
</menu>

View File

@ -5,5 +5,12 @@
android:id="@+id/action_settings" android:id="@+id/action_settings"
android:orderInCategory="100" android:orderInCategory="100"
android:title="@string/action_settings" android:title="@string/action_settings"
app:showAsAction="never" /> app:showAsAction="ifRoom"
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> </menu>

View File

@ -18,22 +18,41 @@
app:popEnterAnim="@android:anim/slide_in_left" app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right" /> app:popExitAnim="@android:anim/slide_out_right" />
<action <action
android:id="@+id/action_nav_home_to_nav_import" android:id="@+id/action_nav_home_to_nav_extensions"
app:destination="@id/nav_import" app:destination="@id/nav_extensions"
app:enterAnim="@android:anim/slide_in_left" app:enterAnim="@android:anim/slide_in_left"
app:exitAnim="@android:anim/slide_out_right" app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left" app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right" /> app:popExitAnim="@android:anim/slide_out_right" />
<action <action
android:id="@+id/action_nav_home_to_nav_water_home" android:id="@+id/action_nav_home_to_nav_water_home"
app:destination="@id/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" />
<action
android:id="@+id/action_nav_home_to_nav_settings"
app:destination="@id/nav_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" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/nav_import" android:id="@+id/nav_extensions"
android:name="com.dzeio.openhealth.ui.imports.ImportFragment" android:name="com.dzeio.openhealth.ui.extensions.ExtensionsFragment"
android:label="@string/menu_import" android:label="@string/menu_import"
tools:layout="@layout/fragment_import" /> tools:layout="@layout/fragment_extensions" >
<action
android:id="@+id/action_nav_import_to_nav_settings"
app:destination="@id/nav_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" />
</fragment>
<fragment <fragment
android:id="@+id/nav_list_weight" android:id="@+id/nav_list_weight"
@ -47,6 +66,13 @@
app:exitAnim="@android:anim/slide_out_right" app:exitAnim="@android:anim/slide_out_right"
app:popEnterAnim="@android:anim/slide_in_left" app:popEnterAnim="@android:anim/slide_in_left"
app:popExitAnim="@android:anim/slide_out_right" /> app:popExitAnim="@android:anim/slide_out_right" />
<action
android:id="@+id/action_nav_list_weight_to_nav_settings"
app:destination="@id/nav_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" />
</fragment> </fragment>
<fragment <fragment
@ -65,7 +91,37 @@
android:id="@+id/nav_water_home" android:id="@+id/nav_water_home"
android:name="com.dzeio.openhealth.ui.water.WaterHomeFragment" android:name="com.dzeio.openhealth.ui.water.WaterHomeFragment"
android:label="@string/nav_water_home" android:label="@string/nav_water_home"
tools:layout="@layout/fragment_water_home"> tools:layout="@layout/fragment_main_water_home">
<action
android:id="@+id/action_nav_water_home_to_nav_settings"
app:destination="@id/nav_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" />
<action
android:id="@+id/action_nav_water_home_to_nav_water_edit"
app:destination="@id/nav_water_edit" />
</fragment>
<fragment
android:id="@+id/nav_settings"
android:name="com.dzeio.openhealth.ui.settings.SettingsFragment">
</fragment>
<fragment
android:id="@+id/nav_water_edit"
android:name="com.dzeio.openhealth.ui.water.EditWaterDialog"
tools:layout="@layout/dialog_water_edit_water"
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">
<argument
android:name="id"
app:argType="long" />
</fragment> </fragment>
</navigation> </navigation>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="genders">
<item>Male</item>
<item>Female</item>
</string-array>
<string-array name="water_units">
<item>Millimeters</item>
<item>Ounces</item>
</string-array>
</resources>

View File

@ -15,4 +15,5 @@
<string name="menu_edit_weight">Edit Weight</string> <string name="menu_edit_weight">Edit Weight</string>
<string name="nav_list_water">Water Intake</string> <string name="nav_list_water">Water Intake</string>
<string name="nav_water_home">Water Intake</string> <string name="nav_water_home">Water Intake</string>
<string name="menu_extensions">Extensions</string>
</resources> </resources>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Global Settings">
<ListPreference
android:defaultValue="Male"
android:entries="@array/genders"
android:entryValues="@array/genders"
android:key="global_gender"
android:title="Gender" />
</PreferenceCategory>
<PreferenceCategory android:title="Weight Settings">
<EditTextPreference
android:key="global_height"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="Height" />
</PreferenceCategory>
<PreferenceCategory android:title="Water Settings">
<SwitchPreference
android:defaultValue="false"
android:key="water_hourly_notification"
android:title="Enable Hourly Notification" />
<ListPreference
android:defaultValue="Millimeters"
android:entries="@array/water_units"
android:entryValues="@array/water_units"
android:key="water_unit"
android:title="Water Unit" />
<EditTextPreference
android:defaultValue="2700"
android:key="water_intake"
android:selectAllOnFocus="true"
android:singleLine="true"
android:inputType="number"
android:title="Daily Water intake" />
</PreferenceCategory>
</PreferenceScreen>