Compare commits
1 Commits
master
...
4e9eeff6aa
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e9eeff6aa |
19
README.md
19
README.md
@@ -13,24 +13,7 @@ Dedicated to my daughter Luna.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Contributions
|
## Thanks for the valuable contributions to:
|
||||||
|
|
||||||
### Why isn't this hosted on GitHub?
|
|
||||||
|
|
||||||
I'm using a private git server just because I'm worried for the vast majority of open source code being hosted in a server property of Microsoft and being used to train theirs AI.
|
|
||||||
I didn't find a better option, BTW the Gitea project is working on implementing federation, so soon it will be possible to contribute using any other gitea server, selfhosted or not.
|
|
||||||
|
|
||||||
### How to contribute
|
|
||||||
|
|
||||||
The project is open to contribution, but with some limits:
|
|
||||||
|
|
||||||
- I'm sorry I can't accept AI-generated contributions. Reviewing a contribution requires time and effort from my side, while generating code with AI requires very little time and produces non reliable code that must be reviewed in detail. This is effectively shifting the work on my side, and in a forced way. If you feel you need a feature but you're not able to implement it by yourself, I prefer you to create an issue in the repository so I can implement it when I can, in a more mantainable way.
|
|
||||||
- I prefer to make project-wide changes (i.e. updating Android target, app name and icon, release number...) by myself.
|
|
||||||
|
|
||||||
To contribute, you'll have to create an account on this git instance. Unfortunately, I had to disable registration to avoid huge waves of fake accounts created by bots.
|
|
||||||
You can request an account writing to daniele.verducci@ichibi.eu
|
|
||||||
|
|
||||||
### Thanks for the valuable contributions to:
|
|
||||||
|
|
||||||
- Chepycou (French translation)
|
- Chepycou (French translation)
|
||||||
- Daniel Neubauer (German translation)
|
- Daniel Neubauer (German translation)
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ android {
|
|||||||
applicationId = "it.danieleverducci.lunatracker"
|
applicationId = "it.danieleverducci.lunatracker"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 7
|
versionCode = 6
|
||||||
versionName = "0.9"
|
versionName = "0.8"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@@ -60,4 +60,4 @@ dependencies {
|
|||||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||||
debugImplementation(libs.androidx.ui.tooling)
|
debugImplementation(libs.androidx.ui.tooling)
|
||||||
debugImplementation(libs.androidx.ui.test.manifest)
|
debugImplementation(libs.androidx.ui.test.manifest)
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import android.content.DialogInterface
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import android.text.Editable
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -21,6 +22,7 @@ import android.widget.Toast
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.widget.doOnTextChanged
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
@@ -29,6 +31,7 @@ import com.thegrizzlylabs.sardineandroid.impl.SardineException
|
|||||||
import it.danieleverducci.lunatracker.adapters.LunaEventRecyclerAdapter
|
import it.danieleverducci.lunatracker.adapters.LunaEventRecyclerAdapter
|
||||||
import it.danieleverducci.lunatracker.entities.Logbook
|
import it.danieleverducci.lunatracker.entities.Logbook
|
||||||
import it.danieleverducci.lunatracker.entities.LunaEvent
|
import it.danieleverducci.lunatracker.entities.LunaEvent
|
||||||
|
import it.danieleverducci.lunatracker.entities.LunaEvent.Companion.TYPE_BABY_BOTTLE
|
||||||
import it.danieleverducci.lunatracker.repository.FileLogbookRepository
|
import it.danieleverducci.lunatracker.repository.FileLogbookRepository
|
||||||
import it.danieleverducci.lunatracker.repository.LocalSettingsRepository
|
import it.danieleverducci.lunatracker.repository.LocalSettingsRepository
|
||||||
import it.danieleverducci.lunatracker.repository.LogbookListObtainedListener
|
import it.danieleverducci.lunatracker.repository.LogbookListObtainedListener
|
||||||
@@ -132,7 +135,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val adapter = LunaEventRecyclerAdapter(this, items)
|
val adapter = LunaEventRecyclerAdapter(this, items)
|
||||||
adapter.onItemClickListener = object: LunaEventRecyclerAdapter.OnItemClickListener {
|
adapter.onItemClickListener = object: LunaEventRecyclerAdapter.OnItemClickListener {
|
||||||
override fun onItemClick(event: LunaEvent) {
|
override fun onItemClick(event: LunaEvent) {
|
||||||
showEventDetailDialog(event, items)
|
showEventDetailDialog(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recyclerView.adapter = adapter
|
recyclerView.adapter = adapter
|
||||||
@@ -195,25 +198,75 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onStop()
|
super.onStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun askBabyBottleContent() {
|
fun getAllEvents(): ArrayList<LunaEvent> {
|
||||||
// Show number picker dialog
|
return logbook?.logs ?: arrayListOf()
|
||||||
val localSettings = LocalSettingsRepository(this)
|
}
|
||||||
|
|
||||||
|
fun askBabyBottleContent(existingEvent: LunaEvent? = null, onEnd: (() -> Unit)? = null) {
|
||||||
|
val isNewEvent = (existingEvent != null)
|
||||||
|
val event = if (existingEvent == null) {
|
||||||
|
LunaEvent(TYPE_BABY_BOTTLE)
|
||||||
|
} else {
|
||||||
|
existingEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
val previous = getPreviousSameEvent(event, getAllEvents())
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.number_picker_dialog, null)
|
val dialogView = layoutInflater.inflate(R.layout.number_picker_dialog, null)
|
||||||
d.setTitle(R.string.log_bottle_dialog_title)
|
d.setTitle(R.string.log_bottle_dialog_title)
|
||||||
d.setMessage(R.string.log_bottle_dialog_description)
|
d.setMessage(R.string.log_bottle_dialog_description)
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
|
|
||||||
val numberPicker = dialogView.findViewById<NumberPicker>(R.id.dialog_number_picker)
|
val numberPicker = dialogView.findViewById<NumberPicker>(R.id.dialog_number_picker)
|
||||||
numberPicker.minValue = 1 // "10"
|
numberPicker.minValue = 1 // "10"
|
||||||
numberPicker.maxValue = 25 // "250
|
numberPicker.maxValue = 25 // "250
|
||||||
numberPicker.displayedValues = ((10..250 step 10).map { it.toString() }.toTypedArray())
|
numberPicker.displayedValues = ((10..250 step 10).map { it.toString() }.toTypedArray())
|
||||||
numberPicker.wrapSelectorWheel = false
|
numberPicker.wrapSelectorWheel = false
|
||||||
numberPicker.value = localSettings.loadBabyBottleContent()
|
if (previous != null) {
|
||||||
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
numberPicker.value = previous.quantity / 10
|
||||||
logEvent(LunaEvent(LunaEvent.TYPE_BABY_BOTTLE, numberPicker.value * 10))
|
|
||||||
localSettings.saveBabyBottleContent(numberPicker.value)
|
|
||||||
}
|
}
|
||||||
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
|
|
||||||
|
val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
||||||
|
dateTextView.text =
|
||||||
|
String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
|
||||||
|
|
||||||
|
val pickedDateTime = Calendar.getInstance()
|
||||||
|
val currentDateTime = Calendar.getInstance()
|
||||||
|
currentDateTime.time = Date(event.time * 1000)
|
||||||
|
dateTextView.setOnClickListener {
|
||||||
|
// Show datetime picker
|
||||||
|
val startYear = currentDateTime.get(Calendar.YEAR)
|
||||||
|
val startMonth = currentDateTime.get(Calendar.MONTH)
|
||||||
|
val startDay = currentDateTime.get(Calendar.DAY_OF_MONTH)
|
||||||
|
val startHour = currentDateTime.get(Calendar.HOUR_OF_DAY)
|
||||||
|
val startMinute = currentDateTime.get(Calendar.MINUTE)
|
||||||
|
|
||||||
|
DatePickerDialog(this, { _, year, month, day ->
|
||||||
|
TimePickerDialog(this, { _, hour, minute ->
|
||||||
|
pickedDateTime.set(year, month, day, hour, minute)
|
||||||
|
val time = pickedDateTime.time.time / 1000
|
||||||
|
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(time))
|
||||||
|
}, startHour, startMinute, android.text.format.DateFormat.is24HourFormat(this@MainActivity)).show()
|
||||||
|
}, startYear, startMonth, startDay).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||||
|
event.quantity = numberPicker.value * 10
|
||||||
|
event.time = pickedDateTime.time.time / 1000 // Seconds since epoch
|
||||||
|
if (isNewEvent) {
|
||||||
|
logEvent(event)
|
||||||
|
}
|
||||||
|
logbook?.sort()
|
||||||
|
recyclerView.adapter?.notifyDataSetChanged()
|
||||||
|
saveLogbook()
|
||||||
|
onEnd?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
onEnd?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
val alertDialog = d.create()
|
val alertDialog = d.create()
|
||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
@@ -262,7 +315,14 @@ class MainActivity : AppCompatActivity() {
|
|||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun askPukeValue() {
|
fun askPukeValue(existingEvent: LunaEvent? = null, onEnd: (() -> Unit)? = null) {
|
||||||
|
val isNewEvent = (existingEvent != null)
|
||||||
|
val event = if (existingEvent == null) {
|
||||||
|
LunaEvent(LunaEvent.TYPE_PUKE)
|
||||||
|
} else {
|
||||||
|
existingEvent
|
||||||
|
}
|
||||||
|
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.puke_dialog, null)
|
val dialogView = layoutInflater.inflate(R.layout.puke_dialog, null)
|
||||||
d.setTitle(R.string.log_puke_dialog_title)
|
d.setTitle(R.string.log_puke_dialog_title)
|
||||||
@@ -271,42 +331,162 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
val spinner = dialogView.findViewById<Spinner>(R.id.dialog_puke_value)
|
val spinner = dialogView.findViewById<Spinner>(R.id.dialog_puke_value)
|
||||||
spinner.adapter = ArrayAdapter.createFromResource(this, R.array.AmountLabels, android.R.layout.simple_spinner_dropdown_item)
|
spinner.adapter = ArrayAdapter.createFromResource(this, R.array.AmountLabels, android.R.layout.simple_spinner_dropdown_item)
|
||||||
spinner.setSelection(1)
|
spinner.setSelection(event.quantity)
|
||||||
|
|
||||||
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||||
val pos = spinner.selectedItemPosition
|
event.quantity = spinner.selectedItemPosition
|
||||||
logEvent(LunaEvent(LunaEvent.TYPE_PUKE, pos + 1))
|
if (isNewEvent) {
|
||||||
|
logEvent(event)
|
||||||
|
}
|
||||||
|
onEnd?.invoke()
|
||||||
|
}
|
||||||
|
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
onEnd?.invoke
|
||||||
}
|
}
|
||||||
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
|
|
||||||
val alertDialog = d.create()
|
val alertDialog = d.create()
|
||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun askNotes(lunaEvent: LunaEvent) {
|
// Ask to edit events to be edited (only affects date)
|
||||||
|
fun askPlain(existingEvent: LunaEvent? = null, onEnd: (() -> Unit)? = null) {
|
||||||
|
val isNewEvent = (existingEvent != null)
|
||||||
|
val event = if (existingEvent == null) {
|
||||||
|
LunaEvent(LunaEvent.TYPE_NOTE)
|
||||||
|
} else {
|
||||||
|
existingEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
val d = AlertDialog.Builder(this)
|
||||||
|
val dialogView = layoutInflater.inflate(R.layout.dialog_plain_event, null)
|
||||||
|
d.setTitle(event.getTypeDescription(this))
|
||||||
|
d.setMessage(event.getDialogMessage(this))
|
||||||
|
d.setView(dialogView)
|
||||||
|
|
||||||
|
val dateET = dialogView.findViewById<TextView>(R.id.notes_date_picker)
|
||||||
|
|
||||||
|
val pickedDateTime = Calendar.getInstance()
|
||||||
|
val currentDateTime = Calendar.getInstance()
|
||||||
|
currentDateTime.time = Date(event.time * 1000)
|
||||||
|
|
||||||
|
dateET.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
|
||||||
|
dateET.setOnClickListener {
|
||||||
|
// Show datetime picker
|
||||||
|
val startYear = currentDateTime.get(Calendar.YEAR)
|
||||||
|
val startMonth = currentDateTime.get(Calendar.MONTH)
|
||||||
|
val startDay = currentDateTime.get(Calendar.DAY_OF_MONTH)
|
||||||
|
val startHour = currentDateTime.get(Calendar.HOUR_OF_DAY)
|
||||||
|
val startMinute = currentDateTime.get(Calendar.MINUTE)
|
||||||
|
|
||||||
|
DatePickerDialog(this, { _, year, month, day ->
|
||||||
|
TimePickerDialog(this, { _, hour, minute ->
|
||||||
|
pickedDateTime.set(year, month, day, hour, minute)
|
||||||
|
val time = pickedDateTime.time.time / 1000
|
||||||
|
dateET.setText(String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(time)))
|
||||||
|
}, startHour, startMinute, android.text.format.DateFormat.is24HourFormat(this@MainActivity)).show()
|
||||||
|
}, startYear, startMonth, startDay).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||||
|
// Save event and move it to the right position in the logbook
|
||||||
|
event.time = pickedDateTime.time.time / 1000 // Seconds since epoch
|
||||||
|
if (isNewEvent) {
|
||||||
|
logEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
logbook?.sort()
|
||||||
|
recyclerView.adapter?.notifyDataSetChanged()
|
||||||
|
saveLogbook()
|
||||||
|
|
||||||
|
onEnd?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
onEnd?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
val alertDialog = d.create()
|
||||||
|
alertDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun askNotes(existingEvent: LunaEvent? = null, onEnd: (() -> Unit)? = null) {
|
||||||
|
val isNewEvent = (existingEvent != null)
|
||||||
|
val event = if (existingEvent == null) {
|
||||||
|
LunaEvent(LunaEvent.TYPE_NOTE)
|
||||||
|
} else {
|
||||||
|
existingEvent
|
||||||
|
}
|
||||||
|
val useQuantity = (event.type != LunaEvent.TYPE_NOTE && event.type != LunaEvent.TYPE_CUSTOM)
|
||||||
|
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_notes, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_notes, null)
|
||||||
d.setTitle(lunaEvent.getTypeDescription(this))
|
d.setTitle(event.getTypeDescription(this))
|
||||||
d.setMessage(lunaEvent.getDialogMessage(this))
|
d.setMessage(event.getDialogMessage(this))
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
val notesET = dialogView.findViewById<EditText>(R.id.notes_edittext)
|
val notesET = dialogView.findViewById<EditText>(R.id.notes_edittext)
|
||||||
val qtyET = dialogView.findViewById<EditText>(R.id.notes_qty_edittext)
|
val qtyET = dialogView.findViewById<EditText>(R.id.notes_qty_edittext)
|
||||||
if (lunaEvent.type == LunaEvent.TYPE_NOTE || lunaEvent.type == LunaEvent.TYPE_CUSTOM)
|
val dateET = dialogView.findViewById<TextView>(R.id.notes_date_picker)
|
||||||
|
|
||||||
|
val pickedDateTime = Calendar.getInstance()
|
||||||
|
val currentDateTime = Calendar.getInstance()
|
||||||
|
currentDateTime.time = Date(event.time * 1000)
|
||||||
|
|
||||||
|
dateET.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
|
||||||
|
dateET.setOnClickListener {
|
||||||
|
// Show datetime picker
|
||||||
|
val startYear = currentDateTime.get(Calendar.YEAR)
|
||||||
|
val startMonth = currentDateTime.get(Calendar.MONTH)
|
||||||
|
val startDay = currentDateTime.get(Calendar.DAY_OF_MONTH)
|
||||||
|
val startHour = currentDateTime.get(Calendar.HOUR_OF_DAY)
|
||||||
|
val startMinute = currentDateTime.get(Calendar.MINUTE)
|
||||||
|
|
||||||
|
DatePickerDialog(this, { _, year, month, day ->
|
||||||
|
TimePickerDialog(this, { _, hour, minute ->
|
||||||
|
pickedDateTime.set(year, month, day, hour, minute)
|
||||||
|
val time = pickedDateTime.time.time / 1000
|
||||||
|
dateET.setText(String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(time)))
|
||||||
|
}, startHour, startMinute, android.text.format.DateFormat.is24HourFormat(this@MainActivity)).show()
|
||||||
|
}, startYear, startMonth, startDay).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
notesET.setText(event.notes)
|
||||||
|
|
||||||
|
if (useQuantity) {
|
||||||
|
qtyET.setText(event.quantity.toString())
|
||||||
|
} else {
|
||||||
qtyET.visibility = View.GONE
|
qtyET.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||||
val qtyStr = qtyET.text.toString()
|
if (useQuantity) {
|
||||||
if (qtyStr.isNotEmpty()) {
|
val qty = qtyET.text.toString().toIntOrNull()
|
||||||
val qty = qtyStr.toIntOrNull()
|
if (qty != null) {
|
||||||
if (qty == null) {
|
event.quantity = qty
|
||||||
|
} else {
|
||||||
Toast.makeText(this, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
|
||||||
|
onEnd?.invoke()
|
||||||
return@setPositiveButton
|
return@setPositiveButton
|
||||||
}
|
}
|
||||||
lunaEvent.quantity = qty
|
|
||||||
}
|
}
|
||||||
val notes = notesET.text.toString()
|
|
||||||
lunaEvent.notes = notes
|
event.notes = notesET.text.toString()
|
||||||
logEvent(lunaEvent)
|
event.time = pickedDateTime.time.time / 1000 // Seconds since epoch
|
||||||
|
|
||||||
|
if (isNewEvent) {
|
||||||
|
logEvent(event)
|
||||||
|
}
|
||||||
|
logbook?.sort()
|
||||||
|
recyclerView.adapter?.notifyDataSetChanged()
|
||||||
|
saveLogbook()
|
||||||
|
onEnd?.invoke()
|
||||||
}
|
}
|
||||||
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
|
|
||||||
|
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
onEnd?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
val alertDialog = d.create()
|
val alertDialog = d.create()
|
||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
@@ -359,55 +539,57 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return nextEvent
|
return nextEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showEventDetailDialog(event: LunaEvent, items: ArrayList<LunaEvent>) {
|
fun showEventDetailDialog(event: LunaEvent) {
|
||||||
// Do not update list while the detail is shown, to avoid changing the object below while it is changed by the user
|
// Do not update list while the detail is shown, to avoid changing the object below while it is changed by the user
|
||||||
pauseLogbookUpdate = true
|
pauseLogbookUpdate = true
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
d.setTitle(R.string.dialog_event_detail_title)
|
d.setTitle(R.string.dialog_event_detail_title)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_event_detail, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_event_detail, null)
|
||||||
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_emoji).text = event.getTypeEmoji(this)
|
val emojiTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_emoji)
|
||||||
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_description).text = event.getTypeDescription(this)
|
val descriptionTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_description)
|
||||||
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_quantity).text =
|
val quantityTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_quantity)
|
||||||
NumericUtils(this).formatEventQuantity(event)
|
val notesTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_notes)
|
||||||
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_notes).text = event.notes
|
|
||||||
|
|
||||||
val currentDateTime = Calendar.getInstance()
|
emojiTextView.text = event.getTypeEmoji(this)
|
||||||
currentDateTime.time = Date(event.time * 1000)
|
descriptionTextView.text = event.getTypeDescription(this)
|
||||||
|
quantityTextView.text = NumericUtils(this).formatEventQuantity(event)
|
||||||
|
notesTextView.text = event.notes
|
||||||
|
|
||||||
val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date)
|
val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date)
|
||||||
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
|
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
|
||||||
dateTextView.setOnClickListener {
|
|
||||||
// Show datetime picker
|
|
||||||
val startYear = currentDateTime.get(Calendar.YEAR)
|
|
||||||
val startMonth = currentDateTime.get(Calendar.MONTH)
|
|
||||||
val startDay = currentDateTime.get(Calendar.DAY_OF_MONTH)
|
|
||||||
val startHour = currentDateTime.get(Calendar.HOUR_OF_DAY)
|
|
||||||
val startMinute = currentDateTime.get(Calendar.MINUTE)
|
|
||||||
|
|
||||||
DatePickerDialog(this, { _, year, month, day ->
|
|
||||||
TimePickerDialog(this, { _, hour, minute ->
|
|
||||||
val pickedDateTime = Calendar.getInstance()
|
|
||||||
pickedDateTime.set(year, month, day, hour, minute)
|
|
||||||
// Save event and move it to the right position in the logbook
|
|
||||||
event.time = pickedDateTime.time.time / 1000 // Seconds since epoch
|
|
||||||
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
|
|
||||||
logbook?.sort()
|
|
||||||
recyclerView.adapter?.notifyDataSetChanged()
|
|
||||||
saveLogbook()
|
|
||||||
}, startHour, startMinute, android.text.format.DateFormat.is24HourFormat(this@MainActivity)).show()
|
|
||||||
}, startYear, startMonth, startDay).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
d.setPositiveButton(R.string.dialog_event_detail_close_button) { dialogInterface, i -> dialogInterface.dismiss() }
|
d.setPositiveButton(R.string.dialog_event_detail_close_button) { dialogInterface, i -> dialogInterface.dismiss() }
|
||||||
d.setNeutralButton(R.string.dialog_event_detail_delete_button) { dialogInterface, i -> deleteEvent(event) }
|
d.setNeutralButton(R.string.dialog_event_detail_delete_button) { dialogInterface, i -> deleteEvent(event) }
|
||||||
|
d.setNegativeButton(R.string.dialog_event_detail_edit_button) { dialogInterface, i ->
|
||||||
|
Log.d("MainActivity", "negative button pressed: ${event.type}")
|
||||||
|
when (event.type) {
|
||||||
|
TYPE_BABY_BOTTLE -> askBabyBottleContent(event, { showEventDetailDialog(event) })
|
||||||
|
LunaEvent.TYPE_WEIGHT -> {}
|
||||||
|
LunaEvent.TYPE_BREASTFEEDING_LEFT_NIPPLE,
|
||||||
|
LunaEvent.TYPE_BREASTFEEDING_BOTH_NIPPLE,
|
||||||
|
LunaEvent.TYPE_BREASTFEEDING_RIGHT_NIPPLE,
|
||||||
|
LunaEvent.TYPE_ENEMA,
|
||||||
|
LunaEvent.TYPE_BATH,
|
||||||
|
LunaEvent.TYPE_COLIC,
|
||||||
|
LunaEvent.TYPE_DIAPERCHANGE_POO,
|
||||||
|
LunaEvent.TYPE_DIAPERCHANGE_PEE -> { askPlain(event, { showEventDetailDialog(event) }) }
|
||||||
|
LunaEvent.TYPE_MEDICINE -> askNotes(event, { showEventDetailDialog(event) })
|
||||||
|
LunaEvent.TYPE_NOTE -> askNotes(event, { showEventDetailDialog(event) })
|
||||||
|
LunaEvent.TYPE_TEMPERATURE, //todo
|
||||||
|
LunaEvent.TYPE_FOOD -> askNotes(event, { showEventDetailDialog(event) })
|
||||||
|
LunaEvent.TYPE_PUKE -> askPukeValue(event, { showEventDetailDialog(event) })
|
||||||
|
LunaEvent.TYPE_CUSTOM -> {} // todo?
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
val alertDialog = d.create()
|
val alertDialog = d.create()
|
||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(ContextCompat.getColor(this, R.color.danger))
|
alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(ContextCompat.getColor(this, R.color.danger))
|
||||||
alertDialog.setOnDismissListener({
|
alertDialog.setOnDismissListener {
|
||||||
// Resume logbook update
|
// Resume logbook update
|
||||||
pauseLogbookUpdate = false
|
pauseLogbookUpdate = false
|
||||||
})
|
}
|
||||||
|
|
||||||
// show optional signature
|
// show optional signature
|
||||||
if (event.signature.isNotEmpty()) {
|
if (event.signature.isNotEmpty()) {
|
||||||
@@ -420,8 +602,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous)
|
val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous)
|
||||||
val nextTextView = dialogView.findViewById<TextView>(R.id.dialog_event_next)
|
val nextTextView = dialogView.findViewById<TextView>(R.id.dialog_event_next)
|
||||||
val nextEvent = getNextSameEvent(event, items)
|
val allEvents = getAllEvents()
|
||||||
val previousEvent = getPreviousSameEvent(event, items)
|
val nextEvent = getNextSameEvent(event, allEvents)
|
||||||
|
val previousEvent = getPreviousSameEvent(event, allEvents)
|
||||||
|
|
||||||
if (previousEvent != null) {
|
if (previousEvent != null) {
|
||||||
val emoji = previousEvent.getTypeEmoji(applicationContext)
|
val emoji = previousEvent.getTypeEmoji(applicationContext)
|
||||||
@@ -429,7 +612,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
previousTextView.text = String.format("⬅️ %s %s", emoji, time)
|
previousTextView.text = String.format("⬅️ %s %s", emoji, time)
|
||||||
previousTextView.setOnClickListener {
|
previousTextView.setOnClickListener {
|
||||||
alertDialog.cancel()
|
alertDialog.cancel()
|
||||||
showEventDetailDialog(previousEvent, items)
|
showEventDetailDialog(previousEvent)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
previousTextView.visibility = View.GONE
|
previousTextView.visibility = View.GONE
|
||||||
@@ -441,7 +624,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
nextTextView.text = String.format("%s %s ➡️", time, emoji)
|
nextTextView.text = String.format("%s %s ➡️", time, emoji)
|
||||||
nextTextView.setOnClickListener {
|
nextTextView.setOnClickListener {
|
||||||
alertDialog.cancel()
|
alertDialog.cancel()
|
||||||
showEventDetailDialog(nextEvent, items)
|
showEventDetailDialog(nextEvent)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nextTextView.visibility = View.GONE
|
nextTextView.visibility = View.GONE
|
||||||
|
|||||||
@@ -23,14 +23,6 @@ class LocalSettingsRepository(val context: Context) {
|
|||||||
sharedPreferences = context.getSharedPreferences(SHARED_PREFS_FILE_NAME, MODE_PRIVATE)
|
sharedPreferences = context.getSharedPreferences(SHARED_PREFS_FILE_NAME, MODE_PRIVATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveBabyBottleContent(content: Int) {
|
|
||||||
sharedPreferences.edit { putInt(SHARED_PREFS_BB_CONTENT, content) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadBabyBottleContent(): Int {
|
|
||||||
return sharedPreferences.getInt(SHARED_PREFS_BB_CONTENT, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveSignature(content: String) {
|
fun saveSignature(content: String) {
|
||||||
sharedPreferences.edit { putString(SHARED_PREFS_SIGNATURE, content) }
|
sharedPreferences.edit { putString(SHARED_PREFS_SIGNATURE, content) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class NumericUtils (val context: Context) {
|
|||||||
LunaEvent.TYPE_TEMPERATURE ->
|
LunaEvent.TYPE_TEMPERATURE ->
|
||||||
(item.quantity / 10.0f).toString()
|
(item.quantity / 10.0f).toString()
|
||||||
LunaEvent.TYPE_PUKE ->
|
LunaEvent.TYPE_PUKE ->
|
||||||
context.resources.getStringArray(R.array.AmountLabels)[item.quantity - 1]
|
context.resources.getStringArray(R.array.AmountLabels)[item.quantity]
|
||||||
else ->
|
else ->
|
||||||
item.quantity
|
item.quantity
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@@ -37,8 +36,7 @@
|
|||||||
android:drawableTint="@color/accent"
|
android:drawableTint="@color/accent"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="@string/dialog_event_detail_datetime_icon"
|
android:text="@string/dialog_event_detail_datetime_icon" />
|
||||||
app:drawableEndCompat="@drawable/ic_edit" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/dialog_event_detail_type_quantity"
|
android:id="@+id/dialog_event_detail_type_quantity"
|
||||||
|
|||||||
@@ -24,4 +24,11 @@
|
|||||||
android:hint="@string/log_notes_dialog_note_hint"
|
android:hint="@string/log_notes_dialog_note_hint"
|
||||||
android:background="@drawable/textview_background"/>
|
android:background="@drawable/textview_background"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/notes_date_picker"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginTop="20dp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -3,17 +3,33 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
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:orientation="vertical">
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<NumberPicker
|
<LinearLayout
|
||||||
android:id="@+id/dialog_number_picker"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="150dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<NumberPicker
|
||||||
|
android:id="@+id/dialog_number_picker"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:text="ml"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/dialog_date_picker"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_gravity="center"
|
||||||
android:text="ml"/>
|
android:layout_marginEnd="20dp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
<string name="log_puke_dialog_title">Puke</string>
|
<string name="log_puke_dialog_title">Puke</string>
|
||||||
<string name="log_puke_dialog_description">Select the amount</string>
|
<string name="log_puke_dialog_description">Select the amount</string>
|
||||||
|
|
||||||
|
<string name="dialog_event_detail_edit_button">Edit</string>
|
||||||
|
|
||||||
<string name="event_bottle_type" translatable="false">🍼</string>
|
<string name="event_bottle_type" translatable="false">🍼</string>
|
||||||
<string name="event_food_type" translatable="false">🥣</string>
|
<string name="event_food_type" translatable="false">🥣</string>
|
||||||
<string name="event_scale_type" translatable="false">⚖️</string>
|
<string name="event_scale_type" translatable="false">⚖️</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user