1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-04-23 19:32:11 +00:00
This commit is contained in:
Florian Bouillon 2021-12-23 16:47:30 +01:00
parent 8c33478e17
commit e5615c9463
23 changed files with 374 additions and 185 deletions

8
.idea/misc.xml generated
View File

@ -3,9 +3,15 @@
<component name="DesignSurface"> <component name="DesignSurface">
<option name="filePathToZoomLevelMap"> <option name="filePathToZoomLevelMap">
<map> <map>
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_home.xml" value="0.33" /> <entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/drawable/ic_outline_hexagon_24.xml" value="0.3475" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/layout/dialog_edit_weight.xml" value="0.5510416666666667" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_home.xml" value="0.67" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_import.xml" value="0.1" /> <entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_import.xml" value="0.1" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/layout/fragment_main_water_home.xml" value="0.5" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/layout/layout_item_list.xml" value="0.5" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/layout/layout_item_weight.xml" value="0.267983789260385" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/menu/activity_main_drawer.xml" value="0.10989583333333333" /> <entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/menu/activity_main_drawer.xml" value="0.10989583333333333" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/menu/fullscreen_dialog.xml" value="0.31197916666666664" />
<entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/menu/main.xml" value="0.1875" /> <entry key="..\:/Git/Dzeio/OpenHealth/app/src/main/res/menu/main.xml" value="0.1875" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/drawable/half_circle.xml" value="0.421" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/drawable/half_circle.xml" value="0.421" />
<entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/drawable/ic_ellipse_2.xml" value="0.4165" /> <entry key="..\:/git/Dzeio/OpenHealth/app/src/main/res/drawable/ic_ellipse_2.xml" value="0.4165" />

View File

@ -23,19 +23,6 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.OpenHealth"> android:theme="@style/Theme.OpenHealth">
<receiver android:name=".services.BroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<!-- Water Intake -->
<service android:name=".services.WaterReminderService"
android:label="Water Intake service"
android:permission="android.permission.BIND_JOB_SERVICE" />
<!-- Samsung Health--> <!-- Samsung Health-->
<meta-data <meta-data
android:name="com.samsung.android.health.permission.read" android:name="com.samsung.android.health.permission.read"

View File

@ -15,8 +15,10 @@ 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
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import androidx.work.WorkManager
import com.dzeio.openhealth.core.BaseActivity 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.services.WaterReminderService import com.dzeio.openhealth.services.WaterReminderService
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -27,14 +29,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private lateinit var navController: NavController private lateinit var navController: NavController
override val bindingInflater: (LayoutInflater) -> ActivityMainBinding = ActivityMainBinding::inflate override val bindingInflater: (LayoutInflater) -> ActivityMainBinding =
ActivityMainBinding::inflate
override fun onCreated(savedInstanceState: Bundle?) { override fun onCreated(savedInstanceState: Bundle?) {
super.onCreated(savedInstanceState) super.onCreated(savedInstanceState)
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController navController = navHostFragment.navController
binding.navView.setupWithNavController(navController) binding.navView.setupWithNavController(navController)
@ -46,9 +50,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
WaterReminderService.setup(this)
createNotificationChannel() createNotificationChannel()
// Services
WorkManager.getInstance(this)
.cancelAllWork()
WaterReminderService.setup(this)
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
@ -83,13 +91,21 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private fun createNotificationChannel() { private fun createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because // Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library // the NotificationChannel class is new and not in the support library
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val importance = NotificationManager.IMPORTANCE_DEFAULT for (channel in NotificationChannels.values()) {
val channel = NotificationChannel("openhealth", "Default Channel", importance) notificationManager.createNotificationChannel(
// Register the channel with the system NotificationChannel(
val notificationManager: NotificationManager = channel.id,
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager channel.channelName,
notificationManager.createNotificationChannel(channel) channel.importance
)
)
}
} }
} }

View File

@ -0,0 +1,31 @@
package com.dzeio.openhealth.adapters
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import com.dzeio.openhealth.core.BaseAdapter
import com.dzeio.openhealth.core.BaseViewHolder
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.databinding.LayoutItemListBinding
import com.dzeio.openhealth.databinding.LayoutItemWeightBinding
class WaterAdapter() : BaseAdapter<Water, LayoutItemListBinding>() {
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> LayoutItemListBinding
get() = LayoutItemListBinding::inflate
var onItemClick: ((weight: Water) -> Unit)? = null
override fun onBindData(
holder: BaseViewHolder<LayoutItemListBinding>,
item: Water,
position: Int
) {
holder.binding.value.text = "${item.value}ml"
holder.binding.datetime.text = item.formatTimestamp()
holder.binding.edit.setOnClickListener {
onItemClick?.invoke(item)
}
}
}

View File

@ -4,8 +4,8 @@ import android.content.Context
import androidx.room.Database import androidx.room.Database
import androidx.room.Room import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import com.dzeio.openhealth.data.weight.Water import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.weight.WaterDao import com.dzeio.openhealth.data.water.WaterDao
import com.dzeio.openhealth.data.weight.WeightDao import com.dzeio.openhealth.data.weight.WeightDao
import com.dzeio.openhealth.data.weight.Weight import com.dzeio.openhealth.data.weight.Weight

View File

@ -1,4 +1,4 @@
package com.dzeio.openhealth.data.weight package com.dzeio.openhealth.data.water
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
@ -12,23 +12,25 @@ data class Water(
@PrimaryKey(autoGenerate = true) var id: Long = 0, @PrimaryKey(autoGenerate = true) var id: Long = 0,
var value: Int = 0, var value: Int = 0,
@ColumnInfo(index = true) @ColumnInfo(index = true)
var timestamp: Long = System.currentTimeMillis(), var timestamp: Long = 0,
var source: String = "OpenHealth" var source: String = "OpenHealth"
) { ) {
init { init {
val cal = Calendar.getInstance() if (timestamp == (0).toLong()) {
cal.set(Calendar.HOUR_OF_DAY, 0) val cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
cal.set(Calendar.MINUTE, 0) cal.set(Calendar.HOUR_OF_DAY, 0)
cal.set(Calendar.SECOND, 0) cal.set(Calendar.MINUTE, 0)
cal.set(Calendar.MILLISECOND, 0) cal.set(Calendar.SECOND, 0)
cal.set(Calendar.MILLISECOND, 0)
timestamp = cal.timeInMillis timestamp = cal.timeInMillis
}
} }
fun formatTimestamp(): String = getDateInstance().format(Date(timestamp)) fun formatTimestamp(): String = getDateInstance().format(Date(timestamp))
fun isToday(): Boolean { fun isToday(): Boolean {
val cal = Calendar.getInstance() val cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
cal.set(Calendar.HOUR_OF_DAY, 0) cal.set(Calendar.HOUR_OF_DAY, 0)
cal.set(Calendar.MINUTE, 0) cal.set(Calendar.MINUTE, 0)
cal.set(Calendar.SECOND, 0) cal.set(Calendar.SECOND, 0)

View File

@ -1,4 +1,4 @@
package com.dzeio.openhealth.data.weight package com.dzeio.openhealth.data.water
import androidx.room.* import androidx.room.*
import com.dzeio.openhealth.core.BaseDao import com.dzeio.openhealth.core.BaseDao
@ -8,7 +8,7 @@ import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface WaterDao : BaseDao<Water> { interface WaterDao : BaseDao<Water> {
@Query("SELECT * FROM Water") @Query("SELECT * FROM Water ORDER BY timestamp")
fun getAll(): Flow<List<Water>> fun getAll(): Flow<List<Water>>
@Query("SELECT * FROM Water where id = :weightId") @Query("SELECT * FROM Water where id = :weightId")

View File

@ -1,4 +1,4 @@
package com.dzeio.openhealth.data.weight package com.dzeio.openhealth.data.water
import android.util.Log import android.util.Log
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*

View File

@ -2,7 +2,7 @@ package com.dzeio.openhealth.di
import android.content.Context import android.content.Context
import com.dzeio.openhealth.data.AppDatabase import com.dzeio.openhealth.data.AppDatabase
import com.dzeio.openhealth.data.weight.WaterDao import com.dzeio.openhealth.data.water.WaterDao
import com.dzeio.openhealth.data.weight.WeightDao import com.dzeio.openhealth.data.weight.WeightDao
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides

View File

@ -0,0 +1,12 @@
package com.dzeio.openhealth.interfaces
import android.app.NotificationManager
enum class NotificationChannels(
val id: String,
val channelName: String,
val importance: Int
) {
// 3 is IMPORTANCE_DEFAULT
DEFAULT("default", "Default Channel", 3)
}

View File

@ -0,0 +1,5 @@
package com.dzeio.openhealth.interfaces
enum class NotificationIds {
WaterIntake
}

View File

@ -1,18 +0,0 @@
package com.dzeio.openhealth.services
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
class BroadcastReceiver : BroadcastReceiver() {
@SuppressLint("UnsafeProtectedBroadcastReceiver")
override fun onReceive(context: Context?, intent: Intent?) {
context?.let {
WaterReminderService.setup(it)
Log.d("OpenHealth/BR", "Scheduled Jobs!")
}
}
}

View File

@ -14,6 +14,8 @@ import com.dzeio.openhealth.Application
import com.dzeio.openhealth.MainActivity import com.dzeio.openhealth.MainActivity
import com.dzeio.openhealth.R import com.dzeio.openhealth.R
import com.dzeio.openhealth.core.BaseService import com.dzeio.openhealth.core.BaseService
import com.dzeio.openhealth.interfaces.NotificationChannels
import com.dzeio.openhealth.interfaces.NotificationIds
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -27,7 +29,7 @@ class WaterReminderService(
fun setup(context: Context) { fun setup(context: Context) {
schedule( schedule(
TAG, TAG,
PeriodicWorkRequestBuilder<WaterReminderService>(15, TimeUnit.MINUTES) PeriodicWorkRequestBuilder<WaterReminderService>(1, TimeUnit.HOURS)
.addTag(TAG) .addTag(TAG)
.build(), .build(),
context context
@ -39,48 +41,29 @@ class WaterReminderService(
override fun doWork(): Result { override fun doWork(): Result {
Log.d(TAG, "Ran! ${Date().toLocaleString()}") Log.d(TAG, "Ran! ${Date().toLocaleString()}")
with(NotificationManagerCompat.from(context)) { with(NotificationManagerCompat.from(context)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { val flag =
notify( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
(Math.random() * 100).toInt(), NotificationCompat.Builder(context, "openhealth") val builder =
.setContentTitle("Did you drink?") NotificationCompat.Builder(context, NotificationChannels.DEFAULT.channelName)
.setContentText("Drink now!") .setContentTitle("Did you drink?")
.setSmallIcon(R.drawable.ic_logo_small) .setContentText("Drink now! ${Date().toLocaleString()}")
.setPriority(NotificationCompat.PRIORITY_HIGH) .setSmallIcon(R.drawable.ic_logo_small)
.setContentIntent( .setPriority(NotificationCompat.PRIORITY_HIGH)
PendingIntent.getActivity( .setContentIntent(
context, PendingIntent.getActivity(
0, context,
Intent(context, MainActivity::class.java).apply { 0,
flags = Intent.FLAG_ACTIVITY_NEW_TASK Intent(context, MainActivity::class.java).apply {
}, flags = Intent.FLAG_ACTIVITY_NEW_TASK
PendingIntent.FLAG_IMMUTABLE },
) flag
) )
.build() ).build()
) notify(
} else { NotificationIds.WaterIntake.ordinal,
notify( builder
(Math.random() * 100).toInt(), NotificationCompat.Builder(context, "openhealth") )
.setContentTitle("Did you drink?")
.setContentText("Drink now!")
.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
},
0
)
)
.build()
)
}
} }
return Result.success() return Result.success()
} }
} }

View File

@ -11,9 +11,10 @@ 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 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
import com.dzeio.openhealth.data.weight.Water import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.databinding.FragmentHomeBinding import com.dzeio.openhealth.databinding.FragmentHomeBinding
import com.dzeio.openhealth.data.weight.Weight import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.ui.weight.AddWeightDialog import com.dzeio.openhealth.ui.weight.AddWeightDialog
@ -39,14 +40,12 @@ import kotlin.math.min
class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewModel::class.java) { class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewModel::class.java) {
companion object { companion object {
const val TAG = "HomeFragment" const val TAG = "${Application.TAG}/HomeFragment"
} }
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHomeBinding override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHomeBinding
get() = FragmentHomeBinding::inflate get() = FragmentHomeBinding::inflate
// private lateinit var fit: GoogleFit
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -107,99 +106,62 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
Log.d("T", "Trying to move") Log.d("T", "Trying to move")
findNavController().navigate(HomeFragmentDirections.actionNavHomeToNavListWeight()) findNavController().navigate(HomeFragmentDirections.actionNavHomeToNavListWeight())
// requireActivity().supportFragmentManager.commit {
// replace(R.id.nav_host_fragment_content_main, ListWeightFragment())
// addToBackStack(null)
// }
} }
// Setup Graph binding.gotoWaterHome.setOnClickListener {
// binding.weightGraph.apply { findNavController().navigate(HomeFragmentDirections.actionNavHomeToNavWaterHome())
// gridLabelRenderer.labelFormatter = DateAsXAxisLabelFormatter( }
// requireContext(),
// DateFormat.getDateInstance(DateFormat.MEDIUM)
// )
// gridLabelRenderer.numHorizontalLabels = 3 // only 4 because of the space
// gridLabelRenderer.numVerticalLabels = 3
// gridLabelRenderer.gridStyle = GridLabelRenderer.GridStyle.HORIZONTAL
// viewport.isXAxisBoundsManual = true
// viewport.isScalable = true
// viewport.setScalableY(true)
// viewport.isScrollable = true
// viewport.setScrollableY(true)
// gridLabelRenderer.setHumanRounding(false);
// addSeries(serie)
// }
} }
// private val serie: LineGraphSeries<DataPoint> = LineGraphSeries()
// private val entries = LineGraphSeries<DataPoint>()
private fun updateGraph(list: List<Weight>) { private fun updateGraph(list: List<Weight>) {
if (list.isNotEmpty()) { if (list.isNotEmpty()) {
val first = list[0].timestamp
val last = list[list.size - 1].timestamp
val weekFirst = last - 604800000
// binding.weightGraph.viewport.setMinX(if (first > weekFirst) first else weekFirst)
// binding.weightGraph.viewport.setMaxX(last);
val entries = ArrayList<Entry>() val entries = ArrayList<Entry>()
for (item in list) { for (item in list) {
entries.add(Entry(item.timestamp.toFloat(), item.weight)) entries.add(Entry(item.timestamp.toFloat(), item.weight))
} }
val dataSet = LineDataSet(entries, "Label") val dataSet = LineDataSet(entries, "Label")
// binding.weightGraph.xAxis.axisMinimum = if (first > weekFirst) first.toFloat() else weekFirst.toFloat() binding.weightGraph.apply {
// binding.weightGraph.setExtraOffsets(
// if (first > weekFirst) first.toFloat() else weekFirst.toFloat(), // Setup
// 100f, isAutoScaleMinMaxEnabled = true
// last.toFloat(), legend.isEnabled = false
// 0f isDragEnabled = true
// ) isScaleYEnabled = false
binding.weightGraph.isAutoScaleMinMaxEnabled = true description = Description().apply { isEnabled = false }
//binding.weightGraph.setvir isScaleXEnabled = true
binding.weightGraph.isDragEnabled = true setPinchZoom(false)
binding.weightGraph.isScaleYEnabled = false axisLeft.setLabelCount(0, true)
binding.weightGraph.description = Description().apply { isEnabled = false } setDrawBorders(false)
binding.weightGraph.isScaleXEnabled = true
binding.weightGraph.setPinchZoom(false) xAxis.apply {
binding.weightGraph.xAxis.setLabelCount(5, true) valueFormatter = object : ValueFormatter() {
binding.weightGraph.xAxis.position = XAxis.XAxisPosition.BOTTOM override fun getAxisLabel(value: Float, axis: AxisBase?): String {
binding.weightGraph.axisRight.isEnabled = false return SimpleDateFormat(
binding.weightGraph.axisRight.setDrawGridLines(false) "yyyy-MM-dd",
binding.weightGraph.xAxis.valueFormatter = object : ValueFormatter() { Locale.getDefault()
override fun getAxisLabel(value: Float, axis: AxisBase?): String { ).format(Date(value.toLong()))
return SimpleDateFormat( //return super.getAxisLabel(value, axis)
"yyyy-MM-dd", }
Locale.getDefault() }
).format(Date(value.toLong())) position = XAxis.XAxisPosition.BOTTOM
//return super.getAxisLabel(value, axis) setDrawGridLines(false)
setLabelCount(3, true)
} }
// Apply new dataset
data = LineData(dataSet)
// idk what I did but it works lol
setVisibleXRange(
0f, entries[entries.size - 1].x / 1000f
)
// BIS... :(
// Also it invalidate the view so I don't have to call invalidate
moveViewToX(entries[entries.size - 1].x - 1600000000f)
} }
binding.weightGraph.data = LineData(dataSet)
binding.weightGraph.invalidate()
binding.weightGraph.setVisibleXRange(
(list[list.size - 1].timestamp - 604800000).toFloat(),
list[list.size - 1].timestamp.toFloat()
)
} }
// binding.weightGraph.gridLabelRenderer.numHorizontalLabels = 3 // only 4 because of the space
// binding.weightGraph.gridLabelRenderer.numVerticalLabels = 3
//
// binding.weightGraph.viewport.maxXAxisSize = 604800000.0 * 2
//// binding.weightGraph.viewport.setMinimalViewport(0.0, 604800000.0, minValue.toDouble(), maxValue.toDouble())
//
// serie.resetData(list
// .map { DataPoint(Date(it.timestamp), it.weight.toDouble()) }
// .toTypedArray())
//
// binding.weightGraph.viewport.scrollToEnd()
} }
override fun onStart() { override fun onStart() {
@ -212,6 +174,7 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
} }
viewModel.water.observe(viewLifecycleOwner) { viewModel.water.observe(viewLifecycleOwner) {
Log.d(TAG, "${it?.formatTimestamp()} $it")
if (it != null) { if (it != null) {
updateWater(it.value) updateWater(it.value)
} else { } else {

View File

@ -4,8 +4,8 @@ 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
import com.dzeio.openhealth.data.weight.Water import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.weight.WaterRepository 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

View File

@ -1,2 +1,52 @@
package com.dzeio.openhealth.ui.water package com.dzeio.openhealth.ui.water
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.dzeio.openhealth.adapters.WaterAdapter
import com.dzeio.openhealth.adapters.WeightAdapter
import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.databinding.FragmentListWeightBinding
import com.dzeio.openhealth.databinding.FragmentMainWaterHomeBinding
import com.dzeio.openhealth.ui.home.HomeViewModel
import com.dzeio.openhealth.ui.weight.ListWeightFragmentDirections
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
@AndroidEntryPoint
class WaterHomeFragment :
BaseFragment<WaterHomeViewModel, FragmentMainWaterHomeBinding>(WaterHomeViewModel::class.java) {
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentMainWaterHomeBinding =
FragmentMainWaterHomeBinding::inflate
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.init()
val recycler = binding.list
val manager = LinearLayoutManager(requireContext())
recycler.layoutManager = manager
val adapter = WaterAdapter()
adapter.onItemClick = {
findNavController().navigate(
ListWeightFragmentDirections.actionNavListWeightToNavEditWeight(
it.id
)
)
//EditWeightDialog().show(requireActivity().supportFragmentManager, "dialog")
}
recycler.adapter = adapter
viewModel.items.observe(viewLifecycleOwner) {
adapter.set(it)
}
}
}

View File

@ -0,0 +1,26 @@
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 WaterHomeViewModel@Inject internal constructor(
private val waterRepository: WaterRepository
) : BaseViewModel() {
val items: MutableLiveData<List<Water>> = MutableLiveData()
fun init() {
viewModelScope.launch {
waterRepository.getWaters().collectLatest {
items.postValue(it)
}
}
}
}

View File

@ -2,9 +2,9 @@
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24" android:viewportHeight="24">
android:tint="?attr/colorControlNormal">
<path <path
android:fillColor="@android:color/white" android:pathData="M12.0001,1.7144L20.9078,6.8572V17.1429L12.0001,22.2858L3.0924,17.1429V6.8572L12.0001,1.7144Z"
android:pathData="M17.2,3H6.8l-5.2,9l5.2,9h10.4l5.2,-9L17.2,3zM16.05,19H7.95l-4.04,-7l4.04,-7h8.09l4.04,7L16.05,19z"/> android:strokeWidth="2"
android:strokeColor="@android:color/white"/>
</vector> </vector>

View File

@ -55,6 +55,7 @@
android:src="@drawable/ic_baseline_add_24" /> android:src="@drawable/ic_baseline_add_24" />
<ImageView <ImageView
android:id="@+id/goto_water_home"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:src="@drawable/ic_outline_hexagon_24" /> android:src="@drawable/ic_outline_hexagon_24" />

View File

@ -0,0 +1,62 @@
<?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:orientation="vertical"
tools:context=".ui.water.WaterHomeFragment">
<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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="200dp"
android:minHeight="200dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:gravity="end"
android:orientation="horizontal"
android:weightSum="2">
<com.google.android.material.button.MaterialButton
android:id="@+id/button_edit_default_intake"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="?attr/materialButtonOutlinedStyle"
android:text="Modify Default Intake" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.recyclerview.widget.RecyclerView
android:clipToPadding="false"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
tools:listitem="@layout/layout_item_weight" />
</LinearLayout>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="?attr/materialCardViewFilledStyle"
xmlns:tools="http://schemas.android.com/tools"
android:layout_marginBottom="8dp"
android:clickable="true"
android:focusable="true"
android:layout_width="match_parent"
android:id="@+id/edit"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:weightSum="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="xkg" />
<TextView
android:id="@+id/datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="Taken: yyyy-mm-dd" />
</LinearLayout>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_baseline_edit_24" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -24,6 +24,9 @@
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_home_to_nav_water_home"
app:destination="@id/nav_water_home" />
</fragment> </fragment>
<fragment <fragment
@ -57,4 +60,12 @@
app:argType="long" /> app:argType="long" />
</fragment> </fragment>
<fragment
android:id="@+id/nav_water_home"
android:name="com.dzeio.openhealth.ui.water.WaterHomeFragment"
android:label="@string/nav_water_home"
tools:layout="@layout/fragment_water_home">
</fragment>
</navigation> </navigation>

View File

@ -13,4 +13,6 @@
<string name="menu_import">Import</string> <string name="menu_import">Import</string>
<string name="menu_list_weight">Weight List</string> <string name="menu_list_weight">Weight List</string>
<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_water_home">Water Intake</string>
</resources> </resources>