mirror of
https://github.com/dzeiocom/OpenHealth.git
synced 2025-06-13 09:29:19 +00:00
Clean up
This commit is contained in:
@ -42,7 +42,6 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||
implementation 'javax.inject:javax.inject:1'
|
||||
@ -50,8 +49,18 @@ dependencies {
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
|
||||
|
||||
// DataStore
|
||||
implementation "androidx.datastore:datastore:1.0.0"
|
||||
|
||||
// Navigation
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
|
||||
|
||||
// Services
|
||||
implementation 'androidx.work:work-runtime-ktx:2.7.1'
|
||||
|
||||
// Tests
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
@ -71,7 +80,7 @@ dependencies {
|
||||
implementation files('libs/samsung-health-data-1.5.0.aar')
|
||||
|
||||
// ROOM
|
||||
def room_version = "2.3.0"
|
||||
def room_version = "2.4.0"
|
||||
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
|
@ -23,6 +23,19 @@
|
||||
android:supportsRtl="true"
|
||||
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-->
|
||||
<meta-data
|
||||
android:name="com.samsung.android.health.permission.read"
|
||||
|
@ -4,4 +4,8 @@ import android.app.Application
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
||||
@HiltAndroidApp
|
||||
class Application : Application() {}
|
||||
class Application : Application() {
|
||||
companion object {
|
||||
const val TAG = "OpenHealth"
|
||||
}
|
||||
}
|
@ -1,6 +1,10 @@
|
||||
package com.dzeio.openhealth
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
@ -13,6 +17,7 @@ import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.dzeio.openhealth.core.BaseActivity
|
||||
import com.dzeio.openhealth.databinding.ActivityMainBinding
|
||||
import com.dzeio.openhealth.services.WaterReminderService
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -41,6 +46,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
|
||||
WaterReminderService.setup(this)
|
||||
createNotificationChannel()
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
@ -66,8 +74,23 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
Log.d("MainActivity", "onActivityResult $requestCode $resultCode")
|
||||
for (fragment in supportFragmentManager.primaryNavigationFragment!!.childFragmentManager.fragments) {
|
||||
fragment.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNotificationChannel() {
|
||||
// Create the NotificationChannel, but only on API 26+ because
|
||||
// the NotificationChannel class is new and not in the support library
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val importance = NotificationManager.IMPORTANCE_DEFAULT
|
||||
val channel = NotificationChannel("openhealth", "Default Channel", importance)
|
||||
// Register the channel with the system
|
||||
val notificationManager: NotificationManager =
|
||||
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
app/src/main/java/com/dzeio/openhealth/core/BaseService.kt
Normal file
25
app/src/main/java/com/dzeio/openhealth/core/BaseService.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package com.dzeio.openhealth.core
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkRequest
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
|
||||
abstract class BaseService(context: Context, params: WorkerParameters) : Worker(context, params) {
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
fun schedule(tag: String, request: WorkRequest, context: Context) {
|
||||
WorkManager.getInstance(context)
|
||||
.cancelAllWorkByTag(tag)
|
||||
|
||||
Log.d("OpenHealth/BaseService", "Scheduled Job $tag")
|
||||
WorkManager.getInstance(context)
|
||||
.enqueue(request)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -26,4 +26,13 @@ data class Water(
|
||||
}
|
||||
|
||||
fun formatTimestamp(): String = getDateInstance().format(Date(timestamp))
|
||||
|
||||
fun isToday(): Boolean {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0)
|
||||
cal.set(Calendar.MINUTE, 0)
|
||||
cal.set(Calendar.SECOND, 0)
|
||||
cal.set(Calendar.MILLISECOND, 0)
|
||||
return timestamp == cal.timeInMillis
|
||||
}
|
||||
}
|
@ -21,12 +21,6 @@ class WaterRepository @Inject constructor(
|
||||
suspend fun deleteFromSource(value: String) = waterDao.deleteFromSource(value)
|
||||
|
||||
fun todayWater() = lastWater().filter {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0)
|
||||
cal.set(Calendar.MINUTE, 0)
|
||||
cal.set(Calendar.SECOND, 0)
|
||||
cal.set(Calendar.MILLISECOND, 0)
|
||||
Log.d("WaterRepository", "${it?.timestamp} ${cal.timeInMillis}")
|
||||
return@filter it?.timestamp == cal.timeInMillis
|
||||
return@filter it != null && it.isToday()
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
@Dao
|
||||
interface WeightDao : BaseDao<Weight> {
|
||||
|
||||
@Query("SELECT * FROM Weight")
|
||||
@Query("SELECT * FROM Weight ORDER BY timestamp")
|
||||
fun getAll(): Flow<List<Weight>>
|
||||
|
||||
@Query("SELECT * FROM Weight where id = :weightId")
|
||||
|
@ -0,0 +1,18 @@
|
||||
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!")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package com.dzeio.openhealth.services
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkerParameters
|
||||
import com.dzeio.openhealth.Application
|
||||
import com.dzeio.openhealth.MainActivity
|
||||
import com.dzeio.openhealth.R
|
||||
import com.dzeio.openhealth.core.BaseService
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class WaterReminderService(
|
||||
private val context: Context,
|
||||
params: WorkerParameters
|
||||
) : BaseService(context, params) {
|
||||
|
||||
companion object {
|
||||
const val TAG = "${Application.TAG}/WaterService"
|
||||
fun setup(context: Context) {
|
||||
schedule(
|
||||
TAG,
|
||||
PeriodicWorkRequestBuilder<WaterReminderService>(15, TimeUnit.MINUTES)
|
||||
.addTag(TAG)
|
||||
.build(),
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("UnspecifiedImmutableFlag")
|
||||
override fun doWork(): Result {
|
||||
Log.d(TAG, "Ran! ${Date().toLocaleString()}")
|
||||
with(NotificationManagerCompat.from(context)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
notify(
|
||||
(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
|
||||
},
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
)
|
||||
.build()
|
||||
)
|
||||
} else {
|
||||
notify(
|
||||
(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()
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,20 +1,14 @@
|
||||
package com.dzeio.openhealth.ui.home
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.animation.ValueAnimator
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.dzeio.openhealth.R
|
||||
@ -36,10 +30,10 @@ import com.google.android.material.color.MaterialColors
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.IOException
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.math.min
|
||||
|
||||
@AndroidEntryPoint
|
||||
class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewModel::class.java) {
|
||||
@ -56,38 +50,39 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
viewModel.init()
|
||||
|
||||
binding.addWeight.setOnClickListener {
|
||||
AddWeightDialog().show(requireActivity().supportFragmentManager, null)
|
||||
}
|
||||
|
||||
binding.fragmentHomeWaterAdd.setOnClickListener {
|
||||
lifecycleScope.launchWhenStarted {
|
||||
binding.fragmentHomeWaterAdd.setOnClickListener { _ ->
|
||||
|
||||
Log.d(TAG, "Collecting latest $this")
|
||||
if (viewModel.fetchTodayWater().count() == 0) {
|
||||
Log.d(TAG, "No value, Adding...")
|
||||
val w = Water()
|
||||
w.value = 200
|
||||
viewModel.updateWater(w)
|
||||
return@launchWhenStarted
|
||||
val water = viewModel.water.value
|
||||
|
||||
if (water == null) {
|
||||
|
||||
val w = Water()
|
||||
w.value = 200
|
||||
viewModel.updateWater(w)
|
||||
} else {
|
||||
water.value += 200
|
||||
viewModel.updateWater(water)
|
||||
}
|
||||
}
|
||||
|
||||
binding.fragmentHomeWaterRemove.setOnClickListener { _ ->
|
||||
|
||||
val water = viewModel.water.value
|
||||
|
||||
if (water != null) {
|
||||
|
||||
water.value -= 200
|
||||
if (water.value == 0) {
|
||||
viewModel.deleteWater(water)
|
||||
} else {
|
||||
viewModel.updateWater(water)
|
||||
}
|
||||
try {
|
||||
viewModel.fetchTodayWater().count()
|
||||
val item = viewModel.fetchTodayWater().lastOrNull()
|
||||
Log.d(TAG, "Collected latest $item")
|
||||
if (item == null) {
|
||||
|
||||
val w = Water()
|
||||
w.value = 200
|
||||
viewModel.updateWater(w)
|
||||
} else {
|
||||
item.value += 200
|
||||
viewModel.updateWater(item)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "EXCEPTION", e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,13 +115,26 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
}
|
||||
|
||||
// Setup Graph
|
||||
// binding.weightGraph.gridLabelRenderer.labelFormatter = DateAsXAxisLabelFormatter(requireContext())
|
||||
// binding.weightGraph.gridLabelRenderer.numHorizontalLabels = 3 // only 4 because of the space
|
||||
// binding.weightGraph.viewport.isXAxisBoundsManual = true
|
||||
//// binding.weightGraph.gridLabelRenderer.setHumanRounding(false);
|
||||
// binding.weightGraph.addSeries(serie)
|
||||
// binding.weightGraph.apply {
|
||||
// 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>) {
|
||||
@ -173,37 +181,41 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
}
|
||||
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()
|
||||
// )
|
||||
// .toTypedArray())
|
||||
//
|
||||
// binding.weightGraph.viewport.scrollToEnd()
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateResource")
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
lifecycleScope.launchWhenStarted {
|
||||
viewModel.fetchWeights().collectLatest {
|
||||
if (it.isEmpty()) {
|
||||
return@collectLatest
|
||||
}
|
||||
updateGraph(it)
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launchWhenStarted {
|
||||
viewModel.fetchTodayWater().collect {
|
||||
Log.d(TAG, "Pouet? $it")
|
||||
if (it != null) {
|
||||
updateWater(it.value)
|
||||
} else {
|
||||
updateWater(0)
|
||||
}
|
||||
|
||||
viewModel.water.observe(viewLifecycleOwner) {
|
||||
if (it != null) {
|
||||
updateWater(it.value)
|
||||
} else {
|
||||
updateWater(0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,7 +224,8 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
}
|
||||
|
||||
private fun updateWater(water: Int) {
|
||||
binding.fragmentHomeWaterCurrent.text = water.toString()
|
||||
val oldValue = binding.fragmentHomeWaterCurrent.text.toString().replace("ml", "").toInt()
|
||||
binding.fragmentHomeWaterCurrent.text = "${water}ml"
|
||||
|
||||
val graph = BitmapUtils.convertToMutable(
|
||||
requireContext(),
|
||||
@ -220,22 +233,24 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
|
||||
)
|
||||
|
||||
graph?.let { btmp ->
|
||||
val canvas = Canvas(btmp)
|
||||
DrawUtils.drawArc(
|
||||
canvas,
|
||||
100 * water / 1200,
|
||||
MaterialColors.getColor(
|
||||
requireView(),
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
)
|
||||
)
|
||||
canvas.save()
|
||||
|
||||
// val params = binding.background.layoutParams
|
||||
// params.height = binding.background.measuredWidth
|
||||
// binding.background.layoutParams = params
|
||||
|
||||
binding.background.setImageBitmap(graph)
|
||||
ValueAnimator.ofFloat(min(oldValue.toFloat(), 1200f), min(water.toFloat(), 1200f))
|
||||
.apply {
|
||||
duration = 300
|
||||
addUpdateListener {
|
||||
val canvas = Canvas(btmp)
|
||||
DrawUtils.drawArc(
|
||||
canvas,
|
||||
100 * it.animatedValue as Float / 1200f,
|
||||
MaterialColors.getColor(
|
||||
requireView(),
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
)
|
||||
)
|
||||
canvas.save()
|
||||
binding.background.setImageBitmap(graph)
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package com.dzeio.openhealth.ui.home
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.dzeio.openhealth.core.BaseViewModel
|
||||
import com.dzeio.openhealth.data.weight.Water
|
||||
import com.dzeio.openhealth.data.weight.WaterRepository
|
||||
@ -9,6 +12,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
@ -29,8 +33,25 @@ class HomeViewModel @Inject internal constructor(
|
||||
|
||||
fun fetchTodayWater() = waterRepository.todayWater()
|
||||
|
||||
suspend fun updateWater(water: Water) = waterRepository.addWater(water)
|
||||
suspend fun deleteWater(water: Water) = waterRepository.deleteWater(water)
|
||||
val water: MutableLiveData<Water?> = MutableLiveData(null)
|
||||
|
||||
fun init() {
|
||||
viewModelScope.launch {
|
||||
waterRepository.todayWater().collectLatest {
|
||||
water.postValue(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateWater(water: Water) {
|
||||
viewModelScope.launch {
|
||||
waterRepository.addWater(water)
|
||||
}
|
||||
}
|
||||
fun deleteWater(item: Water) {
|
||||
viewModelScope.launch {
|
||||
waterRepository.deleteWater(item)
|
||||
water.postValue(null)
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ object DrawUtils {
|
||||
/**
|
||||
* Fuck Graphics
|
||||
*/
|
||||
fun drawArc(canvas: Canvas, percent: Int, pColor: Int) {
|
||||
fun drawArc(canvas: Canvas, percent: Float, pColor: Int) {
|
||||
canvas.width
|
||||
val spacing = 120f
|
||||
val r1 = RectF(
|
||||
|
13
app/src/main/res/drawable/ic_logo_small.xml
Normal file
13
app/src/main/res/drawable/ic_logo_small.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="324dp"
|
||||
android:height="324dp"
|
||||
android:viewportWidth="324"
|
||||
android:viewportHeight="324">
|
||||
<path
|
||||
android:pathData="M290,199.975C302.15,199.975 312,190.125 312,177.975V146.025C312,133.875 302.15,124.025 290,124.025H212.975C205.795,124.025 199.975,118.205 199.975,111.025V34C199.975,21.85 190.125,12 177.975,12H146.025C133.875,12 124.025,21.85 124.025,34V111.025C124.025,118.205 118.205,124.025 111.025,124.025H34C21.85,124.025 12,133.875 12,146.025V177.975C12,190.125 21.85,199.975 34,199.975H111.025C118.205,199.975 124.025,205.795 124.025,212.975V290C124.025,302.15 133.875,312 146.025,312H177.975C190.125,312 199.975,302.15 199.975,290V212.975C199.975,205.795 205.795,199.975 212.975,199.975H290Z"
|
||||
android:strokeWidth="23"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.5"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
Reference in New Issue
Block a user