From 8e8966e9064f5a0d6608059db05c1ce1856c1bcf Mon Sep 17 00:00:00 2001 From: Daniele Verducci Date: Mon, 4 Nov 2024 23:03:05 +0100 Subject: [PATCH] Weight button, auto list update, better time formatting --- .../lunatracker/MainActivity.kt | 35 ++++++++++++++ .../adapters/LunaEventRecyclerAdapter.kt | 48 ++++++++++++++++--- .../lunatracker/entities/LunaEvent.kt | 3 ++ app/src/main/res/layout/activity_main.xml | 33 ++++++++++--- .../main/res/layout/number_edit_dialog.xml | 21 ++++++++ .../main/res/layout/number_picker_dialog.xml | 10 +++- app/src/main/res/layout/row_luna_event.xml | 2 + app/src/main/res/values/strings.xml | 11 +++++ 8 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 app/src/main/res/layout/number_edit_dialog.xml diff --git a/app/src/main/java/it/danieleverducci/lunatracker/MainActivity.kt b/app/src/main/java/it/danieleverducci/lunatracker/MainActivity.kt index 664e4d2..5d511ec 100644 --- a/app/src/main/java/it/danieleverducci/lunatracker/MainActivity.kt +++ b/app/src/main/java/it/danieleverducci/lunatracker/MainActivity.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.os.Handler import android.view.View import android.widget.NumberPicker +import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity @@ -23,9 +24,15 @@ class MainActivity : AppCompatActivity() { lateinit var logbook: Logbook lateinit var adapter: LunaEventRecyclerAdapter lateinit var recyclerView: RecyclerView + lateinit var handler: Handler + val updateListRunnable: Runnable = Runnable { + adapter.notifyDataSetChanged() + handler.postDelayed(updateListRunnable, 1000*30) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + handler = Handler(mainLooper) // Load data logbook = Logbook.load(this) @@ -42,6 +49,7 @@ class MainActivity : AppCompatActivity() { // Set listeners findViewById(R.id.button_bottle).setOnClickListener { askBabyBottleContent() } + findViewById(R.id.button_scale).setOnClickListener { askWeightValue() } findViewById(R.id.button_nipple_left).setOnClickListener { logEvent( LunaEvent( LunaEventType.BREASTFEEDING_LEFT_NIPPLE @@ -74,6 +82,13 @@ class MainActivity : AppCompatActivity() { // Update list dates adapter.notifyDataSetChanged() + handler.postDelayed(updateListRunnable, 1000*30) + } + + override fun onStop() { + handler.removeCallbacks(updateListRunnable) + + super.onStop() } fun askBabyBottleContent() { @@ -96,6 +111,26 @@ class MainActivity : AppCompatActivity() { 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(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) { adapter.items.add(0, event) adapter.notifyItemInserted(0) diff --git a/app/src/main/java/it/danieleverducci/lunatracker/adapters/LunaEventRecyclerAdapter.kt b/app/src/main/java/it/danieleverducci/lunatracker/adapters/LunaEventRecyclerAdapter.kt index 8680f46..f5fe5bc 100644 --- a/app/src/main/java/it/danieleverducci/lunatracker/adapters/LunaEventRecyclerAdapter.kt +++ b/app/src/main/java/it/danieleverducci/lunatracker/adapters/LunaEventRecyclerAdapter.kt @@ -1,6 +1,7 @@ package it.danieleverducci.lunatracker.adapters import android.content.Context +import android.text.format.DateFormat import android.text.format.DateUtils import android.view.LayoutInflater import android.view.View @@ -10,7 +11,6 @@ import androidx.recyclerview.widget.RecyclerView import it.danieleverducci.lunatracker.entities.LunaEvent import it.danieleverducci.lunatracker.entities.LunaEventType import it.danieleverducci.lunatracker.R -import java.text.DateFormat import java.util.Date class LunaEventRecyclerAdapter: RecyclerView.Adapter { @@ -38,6 +38,7 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter R.string.event_bottle_type + LunaEventType.WEIGHT -> R.string.event_scale_type LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_type LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type @@ -49,6 +50,7 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter R.string.event_bottle_desc + LunaEventType.WEIGHT -> R.string.event_scale_desc LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_desc LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc @@ -58,18 +60,50 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter 0) item.quantity.toString() else "" - // holder.time.text = DateUtils.getRelativeTimeSpanString(item.time * 1000) - 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) + holder.time.text = formatTimeAgo(context, item.time) } override fun getItemCount(): Int { 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 { val type: TextView val description: TextView diff --git a/app/src/main/java/it/danieleverducci/lunatracker/entities/LunaEvent.kt b/app/src/main/java/it/danieleverducci/lunatracker/entities/LunaEvent.kt index 5e36b80..b8bf146 100644 --- a/app/src/main/java/it/danieleverducci/lunatracker/entities/LunaEvent.kt +++ b/app/src/main/java/it/danieleverducci/lunatracker/entities/LunaEvent.kt @@ -21,6 +21,7 @@ class LunaEvent( val jo = JSONObject() val type = when (type) { LunaEventType.BABY_BOTTLE -> "BABY_BOTTLE" + LunaEventType.WEIGHT -> "SCALE" LunaEventType.BREASTFEEDING_LEFT_NIPPLE -> "BREASTFEEDING_LEFT_NIPPLE" LunaEventType.BREASTFEEDING_BOTH_NIPPLE -> "BREASTFEEDING_BOTH_NIPPLE" LunaEventType.BREASTFEEDING_RIGHT_NIPPLE -> "BREASTFEEDING_RIGHT_NIPPLE" @@ -38,6 +39,7 @@ class LunaEvent( fun fromJson(j: JSONObject): LunaEvent { val type = when (j.getString("type")) { "BABY_BOTTLE" -> LunaEventType.BABY_BOTTLE + "SCALE" -> LunaEventType.WEIGHT "BREASTFEEDING_LEFT_NIPPLE" -> LunaEventType.BREASTFEEDING_LEFT_NIPPLE "BREASTFEEDING_BOTH_NIPPLE" -> LunaEventType.BREASTFEEDING_BOTH_NIPPLE "BREASTFEEDING_RIGHT_NIPPLE" -> LunaEventType.BREASTFEEDING_RIGHT_NIPPLE @@ -56,6 +58,7 @@ class LunaEvent( enum class LunaEventType { BABY_BOTTLE, + WEIGHT, BREASTFEEDING_LEFT_NIPPLE, BREASTFEEDING_BOTH_NIPPLE, BREASTFEEDING_RIGHT_NIPPLE, diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 052c90b..958db78 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -18,15 +18,34 @@ android:text="@string/log_an_event" android:gravity="center_horizontal"/> - + android:orientation="horizontal"> + + + + + + + + + + + + diff --git a/app/src/main/res/layout/number_picker_dialog.xml b/app/src/main/res/layout/number_picker_dialog.xml index 04ce9bf..c9d9128 100644 --- a/app/src/main/res/layout/number_picker_dialog.xml +++ b/app/src/main/res/layout/number_picker_dialog.xml @@ -4,10 +4,16 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" - android:gravity="center_horizontal"> + android:gravity="center"> + + diff --git a/app/src/main/res/layout/row_luna_event.xml b/app/src/main/res/layout/row_luna_event.xml index 6672ec9..2ff2ecc 100644 --- a/app/src/main/res/layout/row_luna_event.xml +++ b/app/src/main/res/layout/row_luna_event.xml @@ -25,6 +25,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" + android:gravity="center_horizontal" android:text="Qty"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index da02c6e..1724f1e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,7 +7,11 @@ Biberon Inserisci la quantità contenuta nel biberon + Pesata + Inserisci il peso rilevato + 🍼 + ⚖️ 🤱 ← 🤱 ↔ 🤱 → @@ -16,6 +20,7 @@ - Biberon + Pesata Allatt. al seno (sx) Allatt. al seno Allatt. al seno (dx) @@ -24,5 +29,11 @@ Evento aggiunto! + Valore non valido. Inserire un numero intero. + adesso + ora + ore + min + min \ No newline at end of file