1 Commits

Author SHA1 Message Date
88e9cb7deb LunaEvent: add sleep event 2025-11-14 22:41:57 +01:00
5 changed files with 69 additions and 85 deletions

View File

@@ -12,7 +12,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.NumberPicker
import android.widget.PopupWindow
@@ -331,7 +330,7 @@ class MainActivity : AppCompatActivity() {
alertDialog.show()
}
fun datePickerHelper(time: Long, dateTextView: TextView, onChange: (Long) -> Unit = {}): Calendar {
fun datePickerHelper(time: Long, dateTextView: TextView, onChange: () -> Unit = {}): Calendar {
dateTextView.text = DateUtils.formatDateTime(time)
val dateTime = Calendar.getInstance()
@@ -350,7 +349,7 @@ class MainActivity : AppCompatActivity() {
{ _, hour, minute ->
dateTime.set(year, month, day, hour, minute)
dateTextView.text = DateUtils.formatDateTime(dateTime.time.time / 1000)
onChange.invoke(dateTime.time.time / 1000)
onChange.invoke()
},
startHour,
startMinute,
@@ -374,6 +373,7 @@ class MainActivity : AppCompatActivity() {
}
fun addSleepEvent(event: LunaEvent) {
setToPreviousQuantity(event)
askSleepValue(event) { saveEvent(event) }
}
@@ -384,74 +384,57 @@ class MainActivity : AppCompatActivity() {
d.setMessage(event.getDialogMessage(this))
d.setView(dialogView)
val fromTextView = dialogView.findViewById<TextView>(R.id.dialog_date_from)
val toTextView = dialogView.findViewById<TextView>(R.id.dialog_date_to)
val durationTextView = dialogView.findViewById<TextView>(R.id.dialog_date_duration)
val durationPlus10Button = dialogView.findViewById<Button>(R.id.dialog_date_duration_plus10)
val durationMinus10Button = dialogView.findViewById<Button>(R.id.dialog_date_duration_minus10)
val durationNowButton = dialogView.findViewById<Button>(R.id.dialog_date_duration_now)
val datePicker = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
val currentDurationTextColor = durationTextView.currentTextColor
val invalidDurationTextColor = ContextCompat.getColor(this, R.color.danger)
var pickedFromTime = Calendar.getInstance()
var pickedToTime = Calendar.getInstance()
var duration = event.quantity
fun isValidTime(timeSeconds: Long, durationSeconds: Int): Boolean {
val now = Calendar.getInstance().time.time / 1000
return (timeSeconds + durationSeconds) <= now && durationSeconds < (12 * 60 * 60)
fun isValidTime(fromSeconds: Long, toSeconds: Long): Boolean {
if (fromSeconds < toSeconds) {
val durationSeconds = toSeconds - fromSeconds
// sleep between 0 seconds and 12 hours
return durationSeconds > 59 && durationSeconds < (12 * 60 * 60)
} else {
return false
}
}
val onDateChange = { time: Long ->
val onDateChange = {
val fromSeconds = pickedFromTime.time.time / 1000
val toSeconds = pickedToTime.time.time / 1000
val invalidDateText = getString(R.string.toast_date_error)
durationTextView.text = DateUtils.formatTimeDuration(applicationContext, toSeconds - fromSeconds, invalidDateText)
if (isValidTime(fromSeconds, toSeconds)) {
// valid duration: set default color
durationTextView.setTextColor(currentDurationTextColor)
if (duration == 0) {
// baby is sleeping
durationTextView.text = "💤"
} else {
durationTextView.text = DateUtils.formatTimeDuration(applicationContext, duration.toLong())
if (!isValidTime(time, duration)) {
durationTextView.setTextColor(invalidDurationTextColor)
}
// invalid duration: set danger color
durationTextView.setTextColor(ContextCompat.getColor(this, R.color.danger))
}
}
val pickedDateTime = datePickerHelper(event.time, datePicker, onDateChange)
pickedFromTime = datePickerHelper(event.time, fromTextView, onDateChange)
pickedToTime = datePickerHelper(event.time + event.quantity, toTextView, onDateChange)
onDateChange(pickedDateTime.time.time / 1000)
durationPlus10Button.setOnClickListener {
duration += 10 * 60
onDateChange(pickedDateTime.time.time / 1000)
}
durationMinus10Button.setOnClickListener {
if (duration > 10 * 60) {
duration -= 10 * 60
} else {
duration = 0
}
onDateChange(pickedDateTime.time.time / 1000)
}
durationNowButton.setOnClickListener {
val now = Calendar.getInstance().time.time / 1000
val start = pickedDateTime.time.time / 1000
if (now > start) {
duration = (now - start).toInt()
onDateChange(pickedDateTime.time.time / 1000)
}
}
onDateChange()
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
val time = pickedDateTime.time.time / 1000
val fromSeconds = pickedFromTime.time.time / 1000
val toSeconds = pickedToTime.time.time / 1000
if (isValidTime(time, duration)) {
event.time = time
event.quantity = duration
if (isValidTime(fromSeconds, toSeconds)) {
event.time = fromSeconds
event.quantity = (toSeconds - fromSeconds).toInt()
onPositive()
dialogInterface.dismiss()
} else {
Toast.makeText(this, R.string.toast_date_error, Toast.LENGTH_SHORT).show()
}
dialogInterface.dismiss()
}
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i ->

View File

@@ -13,6 +13,10 @@ class DateUtils {
* Used for the duration to the next/previous event in the event details dialog.
*/
fun formatTimeDuration(context: Context, secondsDiff: Long): String {
return formatTimeDuration(context, secondsDiff, context.getString(R.string.now))
}
fun formatTimeDuration(context: Context, secondsDiff: Long, fallbackText: String): String {
var seconds = secondsDiff
val years = (seconds / (365 * 24 * 60 * 60F)).toLong()
@@ -62,8 +66,10 @@ class DateUtils {
return format(days, hours, R.string.day_ago, R.string.days_ago, R.string.hour_ago, R.string.hours_ago)
} else if (hours > 0) {
return format(hours, minutes, R.string.hour_ago, R.string.hours_ago, R.string.minute_ago, R.string.minutes_ago)
} else {
} else if (minutes > 0) {
return format(minutes, seconds, R.string.minute_ago, R.string.minute_ago, R.string.second_ago, R.string.seconds_ago)
} else {
return fallbackText
}
}

View File

@@ -92,11 +92,6 @@ class NumericUtils (val context: Context) {
else -> ""
}
)
} else {
formatted.append(when (event.type) {
LunaEvent.TYPE_SLEEP -> "💤" // baby is sleeping
else -> ""
})
}
return formatted.toString()
}

View File

@@ -7,12 +7,25 @@
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/dialog_date_duration"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="sleeping emoji"/>
android:gravity="center"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<TextView
android:layout_width="40sp"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="From"/>
<TextView
android:id="@+id/dialog_date_from"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
@@ -21,37 +34,24 @@
android:layout_marginTop="20dp"
android:orientation="horizontal">
<Button
android:id="@+id/dialog_date_duration_minus10"
android:layout_width="wrap_content"
<TextView
android:layout_width="40sp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_weight="1"
android:text="-10"/>
android:layout_marginEnd="10dp"
android:text="To"/>
<Button
android:id="@+id/dialog_date_duration_now"
<TextView
android:id="@+id/dialog_date_to"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="0dp"
android:layout_weight="1"
android:text="now"/>
<Button
android:id="@+id/dialog_date_duration_plus10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_weight="1"
android:text="+10"/>
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:id="@+id/dialog_date_picker"
android:id="@+id/dialog_date_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"/>
android:layout_marginTop="20dp"
android:text="0"/>
</LinearLayout>

View File

@@ -116,7 +116,7 @@
<string name="log_temperature_dialog_description">Select the temperature:</string>
<string name="log_unknown_dialog_description"></string>
<string name="log_weight_dialog_description">Insert the weight:</string>
<string name="log_sleep_dialog_description">Set sleep duration:</string>
<string name="log_sleep_dialog_description">Select sleep range:</string>
<string name="measurement_unit_liquid_base_metric" translatable="false">ml</string>
<string name="measurement_unit_weight_base_metric" translatable="false">g</string>