Weight button, auto list update, better time formatting

This commit is contained in:
Daniele Verducci 2024-11-04 23:03:05 +01:00
parent aaa78139d6
commit 8e8966e906
8 changed files with 147 additions and 16 deletions

View File

@ -4,6 +4,7 @@ import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.view.View import android.view.View
import android.widget.NumberPicker import android.widget.NumberPicker
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
@ -23,9 +24,15 @@ class MainActivity : AppCompatActivity() {
lateinit var logbook: Logbook lateinit var logbook: Logbook
lateinit var adapter: LunaEventRecyclerAdapter lateinit var adapter: LunaEventRecyclerAdapter
lateinit var recyclerView: RecyclerView lateinit var recyclerView: RecyclerView
lateinit var handler: Handler
val updateListRunnable: Runnable = Runnable {
adapter.notifyDataSetChanged()
handler.postDelayed(updateListRunnable, 1000*30)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
handler = Handler(mainLooper)
// Load data // Load data
logbook = Logbook.load(this) logbook = Logbook.load(this)
@ -42,6 +49,7 @@ class MainActivity : AppCompatActivity() {
// Set listeners // Set listeners
findViewById<View>(R.id.button_bottle).setOnClickListener { askBabyBottleContent() } findViewById<View>(R.id.button_bottle).setOnClickListener { askBabyBottleContent() }
findViewById<View>(R.id.button_scale).setOnClickListener { askWeightValue() }
findViewById<View>(R.id.button_nipple_left).setOnClickListener { logEvent( findViewById<View>(R.id.button_nipple_left).setOnClickListener { logEvent(
LunaEvent( LunaEvent(
LunaEventType.BREASTFEEDING_LEFT_NIPPLE LunaEventType.BREASTFEEDING_LEFT_NIPPLE
@ -74,6 +82,13 @@ class MainActivity : AppCompatActivity() {
// Update list dates // Update list dates
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
handler.postDelayed(updateListRunnable, 1000*30)
}
override fun onStop() {
handler.removeCallbacks(updateListRunnable)
super.onStop()
} }
fun askBabyBottleContent() { fun askBabyBottleContent() {
@ -96,6 +111,26 @@ class MainActivity : AppCompatActivity() {
alertDialog.show() alertDialog.show()
} }
fun askWeightValue() {
// Show number picker dialog
val d = AlertDialog.Builder(this)
val dialogView = layoutInflater.inflate(R.layout.number_edit_dialog, null)
d.setTitle(R.string.log_weight_dialog_title)
d.setMessage(R.string.log_weight_dialog_description)
d.setView(dialogView)
val weightET = dialogView.findViewById<TextView>(R.id.dialog_number_edittext)
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
val weight = weightET.text.toString().toIntOrNull()
if (weight != null)
logEvent(LunaEvent(LunaEventType.WEIGHT, weight))
else
Toast.makeText(this, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
}
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
val alertDialog = d.create()
alertDialog.show()
}
fun logEvent(event: LunaEvent) { fun logEvent(event: LunaEvent) {
adapter.items.add(0, event) adapter.items.add(0, event)
adapter.notifyItemInserted(0) adapter.notifyItemInserted(0)

View File

@ -1,6 +1,7 @@
package it.danieleverducci.lunatracker.adapters package it.danieleverducci.lunatracker.adapters
import android.content.Context import android.content.Context
import android.text.format.DateFormat
import android.text.format.DateUtils import android.text.format.DateUtils
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -10,7 +11,6 @@ import androidx.recyclerview.widget.RecyclerView
import it.danieleverducci.lunatracker.entities.LunaEvent import it.danieleverducci.lunatracker.entities.LunaEvent
import it.danieleverducci.lunatracker.entities.LunaEventType import it.danieleverducci.lunatracker.entities.LunaEventType
import it.danieleverducci.lunatracker.R import it.danieleverducci.lunatracker.R
import java.text.DateFormat
import java.util.Date import java.util.Date
class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.LunaEventVH> { class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.LunaEventVH> {
@ -38,6 +38,7 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
holder.type.text = context.getString( holder.type.text = context.getString(
when (item.type) { when (item.type) {
LunaEventType.BABY_BOTTLE -> R.string.event_bottle_type LunaEventType.BABY_BOTTLE -> R.string.event_bottle_type
LunaEventType.WEIGHT -> R.string.event_scale_type
LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_type LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_type
LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type
LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type
@ -49,6 +50,7 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
holder.description.text = context.getString( holder.description.text = context.getString(
when (item.type) { when (item.type) {
LunaEventType.BABY_BOTTLE -> R.string.event_bottle_desc LunaEventType.BABY_BOTTLE -> R.string.event_bottle_desc
LunaEventType.WEIGHT -> R.string.event_scale_desc
LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_desc LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_desc
LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc
LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc
@ -58,18 +60,50 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
} }
) )
holder.quantity.text = if ((item.quantity ?: 0) > 0) item.quantity.toString() else "" holder.quantity.text = if ((item.quantity ?: 0) > 0) item.quantity.toString() else ""
// holder.time.text = DateUtils.getRelativeTimeSpanString(item.time * 1000) holder.time.text = formatTimeAgo(context, item.time)
holder.time.text = DateUtils.getRelativeTimeSpanString(
item.time * 1000,
System.currentTimeMillis(),
DateUtils.MINUTE_IN_MILLIS,
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH or DateUtils.FORMAT_SHOW_TIME)
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
return items.size return items.size
} }
/**
* Formats the provided unix timestamp in a string like "3 hours, 26 minutes ago)
*/
fun formatTimeAgo(context: Context, unixTime: Long): String {
val secondsDiff = (System.currentTimeMillis() / 1000) - unixTime
val minutesDiff = secondsDiff / 60
if (minutesDiff < 1)
return context.getString(R.string.now)
val hoursAgo = (secondsDiff / (60 * 60)).toInt()
val minutesAgo = (minutesDiff % 60).toInt()
if (hoursAgo > 24)
return DateFormat.getDateFormat(context).format(Date(unixTime*1000)) + "\n" +
DateFormat.getTimeFormat(context).format(Date(unixTime*1000))
var formattedTime = StringBuilder()
if (hoursAgo > 0) {
formattedTime.append(hoursAgo).append(" ")
if (hoursAgo.toInt() == 1)
formattedTime.append(context.getString(R.string.hour_ago))
else
formattedTime.append(context.getString(R.string.hours_ago))
}
if (formattedTime.isNotEmpty())
formattedTime.append(", ")
if (minutesAgo > 0) {
formattedTime.append(minutesAgo).append(" ")
if (minutesAgo.toInt() == 1)
formattedTime.append(context.getString(R.string.minute_ago))
else
formattedTime.append(context.getString(R.string.minutes_ago))
}
return formattedTime.toString()
}
class LunaEventVH: RecyclerView.ViewHolder { class LunaEventVH: RecyclerView.ViewHolder {
val type: TextView val type: TextView
val description: TextView val description: TextView

View File

@ -21,6 +21,7 @@ class LunaEvent(
val jo = JSONObject() val jo = JSONObject()
val type = when (type) { val type = when (type) {
LunaEventType.BABY_BOTTLE -> "BABY_BOTTLE" LunaEventType.BABY_BOTTLE -> "BABY_BOTTLE"
LunaEventType.WEIGHT -> "SCALE"
LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> "BREASTFEEDING_LEFT_NIPPLE" LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> "BREASTFEEDING_LEFT_NIPPLE"
LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> "BREASTFEEDING_BOTH_NIPPLE" LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> "BREASTFEEDING_BOTH_NIPPLE"
LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> "BREASTFEEDING_RIGHT_NIPPLE" LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> "BREASTFEEDING_RIGHT_NIPPLE"
@ -38,6 +39,7 @@ class LunaEvent(
fun fromJson(j: JSONObject): LunaEvent { fun fromJson(j: JSONObject): LunaEvent {
val type = when (j.getString("type")) { val type = when (j.getString("type")) {
"BABY_BOTTLE" -> LunaEventType.BABY_BOTTLE "BABY_BOTTLE" -> LunaEventType.BABY_BOTTLE
"SCALE" -> LunaEventType.WEIGHT
"BREASTFEEDING_LEFT_NIPPLE" -> LunaEventType.BREASTFEEDING_LEFT_NIPPLE "BREASTFEEDING_LEFT_NIPPLE" -> LunaEventType.BREASTFEEDING_LEFT_NIPPLE
"BREASTFEEDING_BOTH_NIPPLE" -> LunaEventType.BREASTFEEDING_BOTH_NIPPLE "BREASTFEEDING_BOTH_NIPPLE" -> LunaEventType.BREASTFEEDING_BOTH_NIPPLE
"BREASTFEEDING_RIGHT_NIPPLE" -> LunaEventType.BREASTFEEDING_RIGHT_NIPPLE "BREASTFEEDING_RIGHT_NIPPLE" -> LunaEventType.BREASTFEEDING_RIGHT_NIPPLE
@ -56,6 +58,7 @@ class LunaEvent(
enum class LunaEventType { enum class LunaEventType {
BABY_BOTTLE, BABY_BOTTLE,
WEIGHT,
BREASTFEEDING_LEFT_NIPPLE, BREASTFEEDING_LEFT_NIPPLE,
BREASTFEEDING_BOTH_NIPPLE, BREASTFEEDING_BOTH_NIPPLE,
BREASTFEEDING_RIGHT_NIPPLE, BREASTFEEDING_RIGHT_NIPPLE,

View File

@ -18,16 +18,35 @@
android:text="@string/log_an_event" android:text="@string/log_an_event"
android:gravity="center_horizontal"/> android:gravity="center_horizontal"/>
<TextView <LinearLayout
android:id="@+id/button_bottle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/button_bottle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:layout_margin="10dp" android:layout_margin="10dp"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textSize="50sp" android:textSize="50sp"
android:text="@string/event_bottle_type"/> android:text="@string/event_bottle_type"/>
<TextView
android:id="@+id/button_scale"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:gravity="center_horizontal"
android:textSize="50sp"
android:text="@string/event_scale_type"/>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center">
<EditText
android:id="@+id/dialog_number_edittext"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:inputType="number"
android:hint="0"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="g"/>
</LinearLayout>

View File

@ -4,10 +4,16 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center"
android:gravity="center_horizontal"> android:gravity="center">
<NumberPicker <NumberPicker
android:id="@+id/dialog_number_picker" android:id="@+id/dialog_number_picker"
android:layout_width="wrap_content" android:layout_width="150dp"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="ml"/>
</LinearLayout> </LinearLayout>

View File

@ -25,6 +25,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_horizontal"
android:text="Qty"/> android:text="Qty"/>
<TextView <TextView
@ -32,6 +33,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:gravity="center_horizontal"
android:textStyle="bold" android:textStyle="bold"
android:text="Time"/> android:text="Time"/>

View File

@ -7,7 +7,11 @@
<string name="log_bottle_dialog_title">Biberon</string> <string name="log_bottle_dialog_title">Biberon</string>
<string name="log_bottle_dialog_description">Inserisci la quantità contenuta nel biberon</string> <string name="log_bottle_dialog_description">Inserisci la quantità contenuta nel biberon</string>
<string name="log_weight_dialog_title">Pesata</string>
<string name="log_weight_dialog_description">Inserisci il peso rilevato</string>
<string name="event_bottle_type">🍼</string> <string name="event_bottle_type">🍼</string>
<string name="event_scale_type">⚖️</string>
<string name="event_breastfeeding_left_type">🤱 ←</string> <string name="event_breastfeeding_left_type">🤱 ←</string>
<string name="event_breastfeeding_both_type">🤱 ↔</string> <string name="event_breastfeeding_both_type">🤱 ↔</string>
<string name="event_breastfeeding_right_type">🤱 →</string> <string name="event_breastfeeding_right_type">🤱 →</string>
@ -16,6 +20,7 @@
<string name="event_unknown_type">-</string> <string name="event_unknown_type">-</string>
<string name="event_bottle_desc">Biberon</string> <string name="event_bottle_desc">Biberon</string>
<string name="event_scale_desc">Pesata</string>
<string name="event_breastfeeding_left_desc">Allatt. al seno (sx)</string> <string name="event_breastfeeding_left_desc">Allatt. al seno (sx)</string>
<string name="event_breastfeeding_both_desc">Allatt. al seno</string> <string name="event_breastfeeding_both_desc">Allatt. al seno</string>
<string name="event_breastfeeding_right_desc">Allatt. al seno (dx)</string> <string name="event_breastfeeding_right_desc">Allatt. al seno (dx)</string>
@ -24,5 +29,11 @@
<string name="event_unknown_desc"></string> <string name="event_unknown_desc"></string>
<string name="toast_event_added">Evento aggiunto!</string> <string name="toast_event_added">Evento aggiunto!</string>
<string name="toast_integer_error">Valore non valido. Inserire un numero intero.</string>
<string name="now">adesso</string>
<string name="hour_ago">ora</string>
<string name="hours_ago">ore</string>
<string name="minute_ago">min</string>
<string name="minutes_ago">min</string>
</resources> </resources>