forked from penguin86/luna-tracker
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
744e4f2e99 | ||
|
|
ab0037df7a | ||
|
|
9ad9aa7754 | ||
|
|
5109e15a09 | ||
|
|
9c3373ab35 | ||
|
|
5cd14cd726 | ||
|
|
98045da201 | ||
|
|
718af91315 | ||
|
|
ac6b6c7a25 | ||
|
|
6fe0135bef | ||
|
|
c7f2d4cf3f | ||
|
|
d39a0426b0 | ||
|
|
10c59175f4 | ||
|
|
ef1420b313 | ||
|
|
4ae44aa261 | ||
|
|
81fba8e2b5 | ||
|
|
01e7ad07c8 | ||
|
|
3ccd2db7b1 | ||
|
|
b6823bbdfb | ||
|
|
b3ff9f4bb9 | ||
|
|
ee5b9fa24b | ||
|
|
cd523f8282 | ||
|
|
06180f95a8 | ||
|
|
dbfc7fb866 | ||
|
|
0e655371c7 | ||
|
|
d776b479fa | ||
|
|
1613aeb3f4 | ||
|
|
e378f1e6ea | ||
|
|
70800ee850 | ||
|
|
984bcc1698 | ||
|
|
79275f5704 | ||
|
|
ad5bb5537b | ||
|
|
85896d0f97 | ||
|
|
386586ccae | ||
|
|
4fc327342d | ||
|
|
500d58eb74 | ||
|
|
1368c09c58 | ||
|
|
24a73969be | ||
|
|
5d0b2af665 | ||
|
|
8c906369df |
@@ -13,7 +13,24 @@ Dedicated to my daughter Luna.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Thanks for the valuable contributions to:
|
## Contributions
|
||||||
|
|
||||||
|
### 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)
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ plugins {
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "it.danieleverducci.lunatracker"
|
namespace = "it.danieleverducci.lunatracker"
|
||||||
compileSdk = 34
|
compileSdk = 36
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "it.danieleverducci.lunatracker"
|
applicationId = "it.danieleverducci.lunatracker"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 36
|
||||||
versionCode = 7
|
versionCode = 7
|
||||||
versionName = "0.9"
|
versionName = "0.9"
|
||||||
|
|
||||||
@@ -31,6 +31,12 @@ android {
|
|||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
dependenciesInfo {
|
||||||
|
// Disables dependency metadata when building APKs.
|
||||||
|
includeInApk = false
|
||||||
|
// Disables dependency metadata when building Android App Bundles.
|
||||||
|
includeInBundle = false
|
||||||
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
}
|
}
|
||||||
@@ -40,7 +46,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation(libs.androidx.core.ktx)
|
implementation(libs.androidx.core.ktx)
|
||||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
@@ -51,7 +56,7 @@ dependencies {
|
|||||||
implementation(libs.androidx.material3)
|
implementation(libs.androidx.material3)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
implementation(libs.androidx.recyclerview)
|
implementation(libs.androidx.recyclerview)
|
||||||
implementation("com.github.thegrizzlylabs:sardine-android:v0.9")
|
implementation(libs.sardine.android)
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
|
|||||||
@@ -6,13 +6,16 @@ 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
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.Button
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.NumberPicker
|
import android.widget.NumberPicker
|
||||||
import android.widget.PopupWindow
|
import android.widget.PopupWindow
|
||||||
import android.widget.Spinner
|
import android.widget.Spinner
|
||||||
@@ -49,8 +52,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
const val TAG = "MainActivity"
|
const val TAG = "MainActivity"
|
||||||
const val UPDATE_EVERY_SECS: Long = 30
|
const val UPDATE_EVERY_SECS: Long = 30
|
||||||
const val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false
|
const val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false
|
||||||
|
// list of all events
|
||||||
|
var allEvents = arrayListOf<LunaEvent>()
|
||||||
|
var currentPopupItems = listOf<LunaEvent.Type>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lateinit var settingsRepository : LocalSettingsRepository
|
||||||
var logbook: Logbook? = null
|
var logbook: Logbook? = null
|
||||||
var pauseLogbookUpdate = false
|
var pauseLogbookUpdate = false
|
||||||
lateinit var progressIndicator: LinearProgressIndicator
|
lateinit var progressIndicator: LinearProgressIndicator
|
||||||
@@ -71,6 +78,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
handler = Handler(mainLooper)
|
handler = Handler(mainLooper)
|
||||||
|
settingsRepository = LocalSettingsRepository(this@MainActivity)
|
||||||
|
|
||||||
// Show view
|
// Show view
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
@@ -84,27 +92,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
findViewById<View>(R.id.logbooks_add_button).setOnClickListener {
|
findViewById<View>(R.id.logbooks_add_button).setOnClickListener {
|
||||||
showAddLogbookDialog(true)
|
showAddLogbookDialog(true)
|
||||||
}
|
}
|
||||||
findViewById<View>(R.id.button_bottle).setOnClickListener {
|
|
||||||
addBabyBottleEvent()
|
|
||||||
}
|
|
||||||
findViewById<View>(R.id.button_food).setOnClickListener {
|
|
||||||
addNoteEvent(LunaEvent(LunaEvent.TYPE_FOOD))
|
|
||||||
}
|
|
||||||
findViewById<View>(R.id.button_nipple_left).setOnClickListener {
|
|
||||||
addPlainEvent(LunaEvent(LunaEvent.TYPE_BREASTFEEDING_LEFT_NIPPLE))
|
|
||||||
}
|
|
||||||
findViewById<View>(R.id.button_nipple_both).setOnClickListener {
|
|
||||||
addPlainEvent(LunaEvent(LunaEvent.TYPE_BREASTFEEDING_BOTH_NIPPLE))
|
|
||||||
}
|
|
||||||
findViewById<View>(R.id.button_nipple_right).setOnClickListener {
|
|
||||||
addPlainEvent(LunaEvent(LunaEvent.TYPE_BREASTFEEDING_RIGHT_NIPPLE))
|
|
||||||
}
|
|
||||||
findViewById<View>(R.id.button_change_poo).setOnClickListener {
|
|
||||||
addAmountEvent(LunaEvent(LunaEvent.TYPE_DIAPERCHANGE_POO))
|
|
||||||
}
|
|
||||||
findViewById<View>(R.id.button_change_pee).setOnClickListener {
|
|
||||||
addAmountEvent(LunaEvent(LunaEvent.TYPE_DIAPERCHANGE_PEE))
|
|
||||||
}
|
|
||||||
val moreButton = findViewById<View>(R.id.button_more)
|
val moreButton = findViewById<View>(R.id.button_more)
|
||||||
moreButton.setOnClickListener {
|
moreButton.setOnClickListener {
|
||||||
showOverflowPopupWindow(moreButton)
|
showOverflowPopupWindow(moreButton)
|
||||||
@@ -120,9 +108,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
loadLogbookList()
|
loadLogbookList()
|
||||||
}
|
}
|
||||||
findViewById<View>(R.id.button_sync).setOnClickListener {
|
findViewById<View>(R.id.button_sync).setOnClickListener {
|
||||||
|
if (logbook != null) {
|
||||||
|
loadLogbook(logbook!!.name)
|
||||||
|
} else {
|
||||||
loadLogbookList()
|
loadLogbookList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setListAdapter(items: ArrayList<LunaEvent>) {
|
private fun setListAdapter(items: ArrayList<LunaEvent>) {
|
||||||
val adapter = LunaEventRecyclerAdapter(this, items)
|
val adapter = LunaEventRecyclerAdapter(this, items)
|
||||||
@@ -144,13 +136,83 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (logbook == null)
|
if (logbook == null)
|
||||||
Log.w(TAG, "showLogbook(): logbook is null!")
|
Log.w(TAG, "showLogbook(): logbook is null!")
|
||||||
|
|
||||||
setListAdapter(logbook?.logs ?: arrayListOf())
|
allEvents = logbook?.logs ?: arrayListOf()
|
||||||
|
setListAdapter(allEvents)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun populateHeaderMenu() {
|
||||||
|
val dynamicMenu = settingsRepository.loadDynamicMenu()
|
||||||
|
val eventTypeStats = mutableMapOf<LunaEvent.Type, Int>()
|
||||||
|
|
||||||
|
if (dynamicMenu) {
|
||||||
|
// populate frequency map from all events of the last two weeks
|
||||||
|
val lastWeekTime = (System.currentTimeMillis() / 1000) - (14 * 24 * 60 * 60)
|
||||||
|
allEvents.forEach {
|
||||||
|
if (it.time > lastWeekTime) {
|
||||||
|
eventTypeStats[it.type] = 1 + (eventTypeStats[it.type] ?: 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort all event types by frequency and ordinal
|
||||||
|
val eventTypesSorted = LunaEvent.Type.entries.toList().sortedWith(
|
||||||
|
compareBy({ -1 * (eventTypeStats[it] ?: 0) }, { it.ordinal })
|
||||||
|
).filter { it != LunaEvent.Type.UNKNOWN }
|
||||||
|
|
||||||
|
val usedEventCount = eventTypeStats.count { it.value > 0 }
|
||||||
|
val maxButtonCount = if (dynamicMenu) { usedEventCount } else { 7 }
|
||||||
|
|
||||||
|
val row1 = findViewById<View>(R.id.linear_layout_row1)
|
||||||
|
val row1Button1 = findViewById<TextView>(R.id.button1_row1)
|
||||||
|
val row1Button2 = findViewById<TextView>(R.id.button2_row1)
|
||||||
|
|
||||||
|
val row2 = findViewById<View>(R.id.linear_layout_row2)
|
||||||
|
val row2Button1 = findViewById<TextView>(R.id.button1_row2)
|
||||||
|
val row2Button2 = findViewById<TextView>(R.id.button2_row2)
|
||||||
|
val row2Button3 = findViewById<TextView>(R.id.button3_row2)
|
||||||
|
|
||||||
|
val row3 = findViewById<View>(R.id.linear_layout_row3)
|
||||||
|
val row3Button1 = findViewById<TextView>(R.id.button1_row3)
|
||||||
|
val row3Button2 = findViewById<TextView>(R.id.button2_row3)
|
||||||
|
|
||||||
|
// hide all rows/buttons (except row 3)
|
||||||
|
for (view in listOf(row1, row1Button1, row1Button2,
|
||||||
|
row2, row2Button1, row2Button2, row2Button3,
|
||||||
|
row3, row3Button1, row3Button2)) {
|
||||||
|
view.visibility = View.GONE
|
||||||
|
}
|
||||||
|
row3.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
var showCounter = 0
|
||||||
|
|
||||||
|
fun show(vararg tvs: TextView) {
|
||||||
|
for (tv in tvs) {
|
||||||
|
val type = eventTypesSorted[showCounter]
|
||||||
|
tv.text = LunaEvent.getHeaderEmoji(applicationContext, type)
|
||||||
|
tv.setOnClickListener { showCreateDialog(type) }
|
||||||
|
tv.visibility = View.VISIBLE
|
||||||
|
// show parent row
|
||||||
|
(tv.parent as View).visibility = View.VISIBLE
|
||||||
|
showCounter += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when (maxButtonCount) {
|
||||||
|
0 -> { } // ignore - show empty row3
|
||||||
|
1 -> show(row3Button1)
|
||||||
|
2 -> show(row3Button1, row3Button2)
|
||||||
|
3 -> show(row1Button1, row3Button1)
|
||||||
|
4, 5, 6 -> show(row1Button1, row1Button2, row3Button1, row3Button2)
|
||||||
|
else -> show(row1Button1, row1Button2, row2Button1, row2Button2, row2Button3, row3Button1, row3Button2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// store left over events for popup menu
|
||||||
|
currentPopupItems = eventTypesSorted.subList(showCounter, eventTypesSorted.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
|
||||||
val settingsRepository = LocalSettingsRepository(this)
|
|
||||||
if (settingsRepository.loadDataRepository() == LocalSettingsRepository.DATA_REPO.WEBDAV) {
|
if (settingsRepository.loadDataRepository() == LocalSettingsRepository.DATA_REPO.WEBDAV) {
|
||||||
val webDavCredentials = settingsRepository.loadWebdavCredentials()
|
val webDavCredentials = settingsRepository.loadWebdavCredentials()
|
||||||
if (webDavCredentials == null) {
|
if (webDavCredentials == null) {
|
||||||
@@ -167,12 +229,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
signature = settingsRepository.loadSignature()
|
signature = settingsRepository.loadSignature()
|
||||||
|
|
||||||
val noBreastfeeding = settingsRepository.loadNoBreastfeeding()
|
|
||||||
findViewById<View>(R.id.layout_nipples).visibility = when (noBreastfeeding) {
|
|
||||||
true -> View.GONE
|
|
||||||
false -> View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update list dates
|
// Update list dates
|
||||||
recyclerView.adapter?.notifyDataSetChanged()
|
recyclerView.adapter?.notifyDataSetChanged()
|
||||||
|
|
||||||
@@ -191,12 +247,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onStop()
|
super.onStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllEvents(): ArrayList<LunaEvent> {
|
fun addBabyBottleEvent(event: LunaEvent) {
|
||||||
return logbook?.logs ?: arrayListOf()
|
setToPreviousQuantity(event)
|
||||||
}
|
|
||||||
|
|
||||||
fun addBabyBottleEvent() {
|
|
||||||
val event = LunaEvent(LunaEvent.TYPE_BABY_BOTTLE)
|
|
||||||
askBabyBottleContent(event, true) {
|
askBabyBottleContent(event, true) {
|
||||||
saveEvent(event)
|
saveEvent(event)
|
||||||
}
|
}
|
||||||
@@ -205,19 +257,22 @@ class MainActivity : AppCompatActivity() {
|
|||||||
fun askBabyBottleContent(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
fun askBabyBottleContent(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_bottle, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_bottle, null)
|
||||||
d.setTitle(event.getTypeDescription(this))
|
d.setTitle(event.getDialogTitle(this))
|
||||||
d.setMessage(event.getDialogMessage(this))
|
d.setMessage(event.getDialogMessage(this))
|
||||||
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 = 34 // "340
|
||||||
numberPicker.displayedValues = ((10..250 step 10).map { it.toString() }.toTypedArray())
|
numberPicker.displayedValues = ((10..340 step 10).map { it.toString() }.toTypedArray())
|
||||||
numberPicker.wrapSelectorWheel = false
|
numberPicker.wrapSelectorWheel = false
|
||||||
numberPicker.value = event.quantity / 10
|
numberPicker.value = event.quantity / 10
|
||||||
|
|
||||||
|
val numberPickerUnit = dialogView.findViewById<TextView>(R.id.dialog_number_picker_unit)
|
||||||
|
numberPickerUnit.text = NumericUtils(this).measurement_unit_liquid_base
|
||||||
|
|
||||||
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
||||||
val pickedTime = datePickerHelper(event.time, dateTV)
|
val pickedTime = dateTimePicker(event.time, dateTV)
|
||||||
|
|
||||||
if (!showTime) {
|
if (!showTime) {
|
||||||
dateTV.visibility = View.GONE
|
dateTV.visibility = View.GONE
|
||||||
@@ -239,6 +294,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addWeightEvent(event: LunaEvent) {
|
fun addWeightEvent(event: LunaEvent) {
|
||||||
|
setToPreviousQuantity(event)
|
||||||
askWeightValue(event, true) { saveEvent(event) }
|
askWeightValue(event, true) { saveEvent(event) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,15 +302,18 @@ class MainActivity : AppCompatActivity() {
|
|||||||
// Show number picker dialog
|
// Show number picker dialog
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_weight, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_weight, null)
|
||||||
d.setTitle(event.getTypeDescription(this))
|
d.setTitle(event.getDialogTitle(this))
|
||||||
d.setMessage(event.getDialogMessage(this))
|
d.setMessage(event.getDialogMessage(this))
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
|
|
||||||
val weightET = dialogView.findViewById<EditText>(R.id.dialog_number_edittext)
|
val weightET = dialogView.findViewById<EditText>(R.id.dialog_number_edittext)
|
||||||
weightET.setText(event.quantity.toString())
|
weightET.setText(event.quantity.toString())
|
||||||
|
|
||||||
|
val unitTV = dialogView.findViewById<TextView>(R.id.dialog_number_unit)
|
||||||
|
unitTV.text = NumericUtils(this).measurement_unit_weight_base
|
||||||
|
|
||||||
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
||||||
val pickedTime = datePickerHelper(event.time, dateTV)
|
val pickedTime = dateTimePicker(event.time, dateTV)
|
||||||
|
|
||||||
if (!showTime) {
|
if (!showTime) {
|
||||||
dateTV.visibility = View.GONE
|
dateTV.visibility = View.GONE
|
||||||
@@ -281,7 +340,55 @@ class MainActivity : AppCompatActivity() {
|
|||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addHeightEvent(event: LunaEvent) {
|
||||||
|
setToPreviousQuantity(event)
|
||||||
|
askHeightValue(event, true) { saveEvent(event) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun askHeightValue(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
||||||
|
// Show number picker dialog
|
||||||
|
val d = AlertDialog.Builder(this)
|
||||||
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_height, null)
|
||||||
|
d.setTitle(event.getDialogTitle(this))
|
||||||
|
d.setMessage(event.getDialogMessage(this))
|
||||||
|
d.setView(dialogView)
|
||||||
|
|
||||||
|
val heightET = dialogView.findViewById<EditText>(R.id.dialog_number_edittext)
|
||||||
|
heightET.setText(event.quantity.toString())
|
||||||
|
|
||||||
|
val unitTV = dialogView.findViewById<TextView>(R.id.dialog_number_unit)
|
||||||
|
unitTV.text = NumericUtils(this).measurement_unit_height_base
|
||||||
|
|
||||||
|
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
||||||
|
val pickedTime = dateTimePicker(event.time, dateTV)
|
||||||
|
|
||||||
|
if (!showTime) {
|
||||||
|
dateTV.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||||
|
val height = heightET.text.toString().toIntOrNull()
|
||||||
|
if (height != null) {
|
||||||
|
event.time = pickedTime.time.time / 1000
|
||||||
|
event.quantity = height
|
||||||
|
onPositive()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
val alertDialog = d.create()
|
||||||
|
alertDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
fun addTemperatureEvent(event: LunaEvent) {
|
fun addTemperatureEvent(event: LunaEvent) {
|
||||||
|
setToPreviousQuantity(event)
|
||||||
askTemperatureValue(event, true) { saveEvent(event) }
|
askTemperatureValue(event, true) { saveEvent(event) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,12 +396,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
// Show number picker dialog
|
// Show number picker dialog
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_temperature, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_temperature, null)
|
||||||
d.setTitle(event.getTypeDescription(this))
|
d.setTitle(event.getDialogTitle(this))
|
||||||
d.setMessage(event.getDialogMessage(this))
|
d.setMessage(event.getDialogMessage(this))
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
|
|
||||||
val tempSlider = dialogView.findViewById<Slider>(R.id.dialog_temperature_value)
|
val tempSlider = dialogView.findViewById<Slider>(R.id.dialog_temperature_value)
|
||||||
val range = NumericUtils(this).getValidEventQuantityRange(LunaEvent.TYPE_TEMPERATURE)!!
|
val range = NumericUtils(this).getValidEventQuantityRange(LunaEvent.Type.TEMPERATURE)!!
|
||||||
tempSlider.valueFrom = range.first.toFloat()
|
tempSlider.valueFrom = range.first.toFloat()
|
||||||
tempSlider.valueTo = range.second.toFloat()
|
tempSlider.valueTo = range.second.toFloat()
|
||||||
tempSlider.value = if (event.quantity == 0) {
|
tempSlider.value = if (event.quantity == 0) {
|
||||||
@@ -304,7 +411,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
||||||
val pickedTime = datePickerHelper(event.time, dateTV)
|
val pickedTime = dateTimePicker(event.time, dateTV)
|
||||||
if (!showTime) {
|
if (!showTime) {
|
||||||
dateTV.visibility = View.GONE
|
dateTV.visibility = View.GONE
|
||||||
}
|
}
|
||||||
@@ -328,7 +435,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun datePickerHelper(time: Long, dateTextView: TextView): Calendar {
|
// Pick a date/time.
|
||||||
|
fun dateTimePicker(time: Long, dateTextView: TextView, onChange: (Long) -> Unit = {}): Calendar {
|
||||||
dateTextView.text = DateUtils.formatDateTime(time)
|
dateTextView.text = DateUtils.formatDateTime(time)
|
||||||
|
|
||||||
val dateTime = Calendar.getInstance()
|
val dateTime = Calendar.getInstance()
|
||||||
@@ -347,6 +455,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
{ _, hour, minute ->
|
{ _, hour, minute ->
|
||||||
dateTime.set(year, month, day, hour, minute)
|
dateTime.set(year, month, day, hour, minute)
|
||||||
dateTextView.text = DateUtils.formatDateTime(dateTime.time.time / 1000)
|
dateTextView.text = DateUtils.formatDateTime(dateTime.time.time / 1000)
|
||||||
|
onChange.invoke(dateTime.time.time / 1000)
|
||||||
},
|
},
|
||||||
startHour,
|
startHour,
|
||||||
startMinute,
|
startMinute,
|
||||||
@@ -358,25 +467,134 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return dateTime
|
return dateTime
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveEvent(event: LunaEvent) {
|
fun addDurationEvent(event: LunaEvent) {
|
||||||
if (!getAllEvents().contains(event)) {
|
askDurationEvent(event, true) { saveEvent(event) }
|
||||||
// new event
|
|
||||||
logEvent(event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logbook?.sort()
|
fun askDurationEvent(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
||||||
recyclerView.adapter?.notifyDataSetChanged()
|
val d = AlertDialog.Builder(this)
|
||||||
saveLogbook()
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_duration, null)
|
||||||
|
d.setTitle(event.getDialogTitle(this))
|
||||||
|
d.setView(dialogView)
|
||||||
|
|
||||||
|
val durationTV = dialogView.findViewById<TextView>(R.id.dialog_date_duration)
|
||||||
|
val datePickerBeginTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker_begin)
|
||||||
|
val datePickerEndTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker_end)
|
||||||
|
val dateDelimiterTV = dialogView.findViewById<TextView>(R.id.dialog_date_range_delimiter)
|
||||||
|
val durationButtons = dialogView.findViewById<LinearLayout>(R.id.duration_buttons)
|
||||||
|
val durationNowButton = dialogView.findViewById<Button>(R.id.dialog_date_duration_now)
|
||||||
|
val durationClearButton = dialogView.findViewById<Button>(R.id.dialog_date_duration_clear)
|
||||||
|
|
||||||
|
val currentDurationTextColor = durationTV.currentTextColor
|
||||||
|
val invalidDurationTextColor = ContextCompat.getColor(this, R.color.danger)
|
||||||
|
|
||||||
|
// in seconds
|
||||||
|
var durationStart = event.getStartTime()
|
||||||
|
var durationEnd = event.getEndTime()
|
||||||
|
|
||||||
|
fun isValidTime(timeUnix: Long): Boolean {
|
||||||
|
val now = System.currentTimeMillis() / 1000
|
||||||
|
return timeUnix in 1..now
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isValidTimeSpan(timeBeginUnix: Long, timeEndUnix: Long): Boolean {
|
||||||
|
return (timeBeginUnix <= timeEndUnix) && (timeEndUnix - timeBeginUnix) < (24 * 60 * 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateFields() {
|
||||||
|
datePickerBeginTV.text = DateUtils.formatDateTime(durationStart)
|
||||||
|
datePickerEndTV.text = DateUtils.formatDateTime(durationEnd)
|
||||||
|
|
||||||
|
dateTimePicker(durationStart, datePickerBeginTV) { pickedTime: Long ->
|
||||||
|
durationStart = pickedTime
|
||||||
|
if (datePickerEndTV.visibility == View.GONE) {
|
||||||
|
durationEnd = pickedTime
|
||||||
|
}
|
||||||
|
updateFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
dateTimePicker(durationEnd, datePickerEndTV) { pickedTime: Long ->
|
||||||
|
durationEnd = pickedTime
|
||||||
|
updateFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
durationTV.setTextColor(currentDurationTextColor)
|
||||||
|
val duration = durationEnd - durationStart
|
||||||
|
if (duration == 0L) {
|
||||||
|
// event is ongoing
|
||||||
|
durationTV.text = "💤"
|
||||||
|
dateDelimiterTV.visibility = View.GONE
|
||||||
|
datePickerEndTV.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
durationTV.text = DateUtils.formatTimeDuration(applicationContext, duration)
|
||||||
|
if (!isValidTimeSpan(durationStart, durationEnd)) {
|
||||||
|
durationTV.setTextColor(invalidDurationTextColor)
|
||||||
|
}
|
||||||
|
dateDelimiterTV.visibility = View.VISIBLE
|
||||||
|
datePickerEndTV.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
val colorBegin = if (isValidTime(durationStart)) { currentDurationTextColor } else { invalidDurationTextColor }
|
||||||
|
datePickerBeginTV.setTextColor(colorBegin)
|
||||||
|
|
||||||
|
val colorEnd = if (isValidTime(durationEnd)) { currentDurationTextColor } else { invalidDurationTextColor }
|
||||||
|
datePickerEndTV.setTextColor(colorEnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showTime) {
|
||||||
|
dateDelimiterTV.visibility = View.GONE
|
||||||
|
datePickerEndTV.visibility = View.GONE
|
||||||
|
durationTV.visibility = View.GONE
|
||||||
|
durationButtons.visibility = View.GONE
|
||||||
|
//d.setMessage("")
|
||||||
|
} else {
|
||||||
|
dateDelimiterTV.visibility = View.VISIBLE
|
||||||
|
datePickerEndTV.visibility = View.VISIBLE
|
||||||
|
durationTV.visibility = View.VISIBLE
|
||||||
|
durationButtons.visibility = View.VISIBLE
|
||||||
|
d.setMessage(event.getDialogMessage(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFields()
|
||||||
|
|
||||||
|
durationClearButton.setOnClickListener {
|
||||||
|
durationEnd = durationStart
|
||||||
|
updateFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
durationNowButton.setOnClickListener {
|
||||||
|
durationEnd = System.currentTimeMillis() / 1000
|
||||||
|
updateFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||||
|
if (isValidTime(durationStart) && isValidTime(durationEnd) && isValidTimeSpan(durationStart, durationEnd)) {
|
||||||
|
event.time = durationStart
|
||||||
|
event.quantity = (durationEnd - durationStart).toInt()
|
||||||
|
onPositive()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.toast_date_error, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
val alertDialog = d.create()
|
||||||
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAmountEvent(event: LunaEvent) {
|
fun addAmountEvent(event: LunaEvent) {
|
||||||
|
setToPreviousQuantity(event)
|
||||||
askAmountValue(event, true) { saveEvent(event) }
|
askAmountValue(event, true) { saveEvent(event) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun askAmountValue(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
fun askAmountValue(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_amount, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_amount, null)
|
||||||
d.setTitle(event.getTypeDescription(this))
|
d.setTitle(event.getDialogTitle(this))
|
||||||
d.setMessage(event.getDialogMessage(this))
|
d.setMessage(event.getDialogMessage(this))
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
|
|
||||||
@@ -386,11 +604,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
R.array.AmountLabels,
|
R.array.AmountLabels,
|
||||||
android.R.layout.simple_spinner_dropdown_item
|
android.R.layout.simple_spinner_dropdown_item
|
||||||
)
|
)
|
||||||
// set pre-selected item and ensure the quantity to index is in bounds
|
|
||||||
spinner.setSelection(event.quantity.coerceIn(0, spinner.count - 1))
|
spinner.setSelection(event.quantity.coerceIn(0, spinner.count - 1))
|
||||||
|
|
||||||
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
||||||
val pickedTime = datePickerHelper(event.time, dateTV)
|
val pickedTime = dateTimePicker(event.time, dateTV)
|
||||||
if (!showTime) {
|
if (!showTime) {
|
||||||
dateTV.visibility = View.GONE
|
dateTV.visibility = View.GONE
|
||||||
}
|
}
|
||||||
@@ -418,12 +636,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
fun askDateValue(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
fun askDateValue(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_plain, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_plain, null)
|
||||||
d.setTitle(event.getTypeDescription(this))
|
d.setTitle(event.getDialogTitle(this))
|
||||||
d.setMessage(event.getDialogMessage(this))
|
d.setMessage(event.getDialogMessage(this))
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
|
|
||||||
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
||||||
val pickedDateTime = datePickerHelper(event.time, dateTV)
|
val pickedDateTime = dateTimePicker(event.time, dateTV)
|
||||||
if (!showTime) {
|
if (!showTime) {
|
||||||
dateTV.visibility = View.GONE
|
dateTV.visibility = View.GONE
|
||||||
}
|
}
|
||||||
@@ -447,23 +665,60 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun askNotes(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
fun askNotes(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
||||||
val useQuantity = (event.type != LunaEvent.TYPE_NOTE && event.type != LunaEvent.TYPE_CUSTOM)
|
val useQuantity = (event.type != LunaEvent.Type.NOTE)
|
||||||
|
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_notes, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_notes, null)
|
||||||
d.setTitle(event.getTypeDescription(this))
|
d.setTitle(event.getDialogTitle(this))
|
||||||
d.setMessage(event.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)
|
||||||
|
|
||||||
val dateTV = dialogView.findViewById<TextView>(R.id.notes_date_picker)
|
val dateTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker)
|
||||||
val pickedTime = datePickerHelper(event.time, dateTV)
|
val pickedTime = dateTimePicker(event.time, dateTV)
|
||||||
|
|
||||||
if (!showTime) {
|
if (!showTime) {
|
||||||
dateTV.visibility = View.GONE
|
dateTV.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val nextTextView = dialogView.findViewById<TextView>(R.id.notes_template_next)
|
||||||
|
val prevTextView = dialogView.findViewById<TextView>(R.id.notes_template_prev)
|
||||||
|
val templates = allEvents.filter { it.type == event.type }.distinctBy { it.notes }.sortedBy { it.time }
|
||||||
|
|
||||||
|
fun updateContent(current: LunaEvent) {
|
||||||
|
val prevEvent = getPreviousSameEvent(current, templates)
|
||||||
|
var nextEvent = getNextSameEvent(current, templates)
|
||||||
|
|
||||||
|
notesET.setText(current.notes)
|
||||||
|
|
||||||
|
if (nextEvent == null && current != event) {
|
||||||
|
nextEvent = event
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextEvent != null) {
|
||||||
|
nextTextView.setOnClickListener {
|
||||||
|
notesET.setText(nextEvent.notes)
|
||||||
|
updateContent(nextEvent)
|
||||||
|
}
|
||||||
|
nextTextView.alpha = 1.0f
|
||||||
|
} else {
|
||||||
|
nextTextView.setOnClickListener {}
|
||||||
|
nextTextView.alpha = 0.5f
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevEvent != null) {
|
||||||
|
prevTextView.setOnClickListener {
|
||||||
|
notesET.setText(prevEvent.notes)
|
||||||
|
updateContent(prevEvent)
|
||||||
|
}
|
||||||
|
prevTextView.alpha = 1.0f
|
||||||
|
} else {
|
||||||
|
prevTextView.setOnClickListener {}
|
||||||
|
prevTextView.alpha = 0.5f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
notesET.setText(event.notes)
|
notesET.setText(event.notes)
|
||||||
|
|
||||||
if (useQuantity) {
|
if (useQuantity) {
|
||||||
@@ -472,8 +727,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
qtyET.visibility = View.GONE
|
qtyET.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateContent(event)
|
||||||
|
|
||||||
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||||
val notes = notesET.text.toString()
|
val notes = notesET.text.toString().trim()
|
||||||
|
|
||||||
if (useQuantity) {
|
if (useQuantity) {
|
||||||
val quantity = qtyET.text.toString().toIntOrNull()
|
val quantity = qtyET.text.toString().toIntOrNull()
|
||||||
@@ -483,7 +740,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
event.quantity = quantity
|
event.quantity = quantity
|
||||||
onPositive()
|
onPositive()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(applicationContext, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -507,7 +764,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
d.setTitle(R.string.trim_logbook_dialog_title)
|
d.setTitle(R.string.trim_logbook_dialog_title)
|
||||||
d.setMessage(
|
d.setMessage(
|
||||||
when (LocalSettingsRepository(this).loadDataRepository()) {
|
when (settingsRepository.loadDataRepository()) {
|
||||||
LocalSettingsRepository.DATA_REPO.WEBDAV -> R.string.trim_logbook_dialog_message_dav
|
LocalSettingsRepository.DATA_REPO.WEBDAV -> R.string.trim_logbook_dialog_message_dav
|
||||||
else -> R.string.trim_logbook_dialog_message_local
|
else -> R.string.trim_logbook_dialog_message_local
|
||||||
}
|
}
|
||||||
@@ -523,7 +780,14 @@ class MainActivity : AppCompatActivity() {
|
|||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPreviousSameEvent(event: LunaEvent, items: ArrayList<LunaEvent>): LunaEvent? {
|
fun setToPreviousQuantity(event: LunaEvent) {
|
||||||
|
val prev = getPreviousSameEvent(event, allEvents)
|
||||||
|
if (prev != null) {
|
||||||
|
event.quantity = prev.quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPreviousSameEvent(event: LunaEvent, items: List<LunaEvent>): LunaEvent? {
|
||||||
var previousEvent: LunaEvent? = null
|
var previousEvent: LunaEvent? = null
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
if (item.type == event.type && item.time < event.time) {
|
if (item.type == event.type && item.time < event.time) {
|
||||||
@@ -537,7 +801,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return previousEvent
|
return previousEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNextSameEvent(event: LunaEvent, items: ArrayList<LunaEvent>): LunaEvent? {
|
fun getNextSameEvent(event: LunaEvent, items: List<LunaEvent>): LunaEvent? {
|
||||||
var nextEvent: LunaEvent? = null
|
var nextEvent: LunaEvent? = null
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
if (item.type == event.type && item.time > event.time) {
|
if (item.type == event.type && item.time > event.time) {
|
||||||
@@ -554,6 +818,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
fun showEventDetailDialog(originalEvent: LunaEvent) {
|
fun showEventDetailDialog(originalEvent: LunaEvent) {
|
||||||
val event = LunaEvent(originalEvent)
|
val event = LunaEvent(originalEvent)
|
||||||
|
|
||||||
|
fun eventValuesChanged(): Boolean {
|
||||||
|
return (event.time != originalEvent.time
|
||||||
|
|| event.quantity != originalEvent.quantity
|
||||||
|
|| event.notes != originalEvent.notes)
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
|
||||||
@@ -564,38 +834,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val emojiTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_emoji)
|
val emojiTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_emoji)
|
||||||
val descriptionTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_description)
|
val descriptionTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_description)
|
||||||
val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date)
|
val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date)
|
||||||
|
val dateEndTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date_end)
|
||||||
val quantityTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_quantity)
|
val quantityTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_quantity)
|
||||||
val notesTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_notes)
|
val notesTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_notes)
|
||||||
|
|
||||||
emojiTextView.text = event.getTypeEmoji(this)
|
emojiTextView.text = event.getHeaderEmoji(this)
|
||||||
descriptionTextView.text = event.getTypeDescription(this)
|
descriptionTextView.text = event.getDialogTitle(this)
|
||||||
|
|
||||||
val pickedTime = datePickerHelper(event.time, dateTextView)
|
|
||||||
val updateValues = {
|
|
||||||
quantityTextView.text = NumericUtils(this).formatEventQuantity(event)
|
|
||||||
notesTextView.text = event.notes
|
|
||||||
}
|
|
||||||
updateValues()
|
|
||||||
|
|
||||||
quantityTextView.setOnClickListener {
|
|
||||||
when (event.type) {
|
|
||||||
LunaEvent.TYPE_BABY_BOTTLE -> askBabyBottleContent(event, false, updateValues)
|
|
||||||
LunaEvent.TYPE_WEIGHT -> askWeightValue(event, false, updateValues)
|
|
||||||
LunaEvent.TYPE_DIAPERCHANGE_POO,
|
|
||||||
LunaEvent.TYPE_DIAPERCHANGE_PEE,
|
|
||||||
LunaEvent.TYPE_PUKE -> askAmountValue(event, false, updateValues)
|
|
||||||
LunaEvent.TYPE_TEMPERATURE -> askTemperatureValue(event, false, updateValues)
|
|
||||||
LunaEvent.TYPE_NOTE -> askNotes(event, false, updateValues)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notesTextView.setOnClickListener {
|
|
||||||
when (event.type) {
|
|
||||||
LunaEvent.TYPE_FOOD,
|
|
||||||
LunaEvent.TYPE_MEDICINE,
|
|
||||||
LunaEvent.TYPE_NOTE -> askNotes(event, false, updateValues)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
|
|
||||||
@@ -604,12 +848,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
dialogInterface.dismiss()
|
dialogInterface.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
d.setPositiveButton(R.string.dialog_event_detail_close_button) { dialogInterface, i ->
|
d.setNegativeButton(R.string.dialog_event_detail_save_button) { dialogInterface, i ->
|
||||||
event.time = pickedTime.time.time / 1000
|
if (eventValuesChanged()) {
|
||||||
|
|
||||||
if (event.time != originalEvent.time
|
|
||||||
|| event.quantity != originalEvent.quantity
|
|
||||||
|| event.notes != originalEvent.notes) {
|
|
||||||
originalEvent.time = event.time
|
originalEvent.time = event.time
|
||||||
originalEvent.quantity = event.quantity
|
originalEvent.quantity = event.quantity
|
||||||
originalEvent.notes = event.notes
|
originalEvent.notes = event.notes
|
||||||
@@ -619,6 +859,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
dialogInterface.dismiss()
|
dialogInterface.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.setPositiveButton(R.string.dialog_event_detail_close_button) { dialogInterface, i ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
val alertDialog = d.create()
|
val alertDialog = d.create()
|
||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
|
|
||||||
@@ -631,6 +875,59 @@ class MainActivity : AppCompatActivity() {
|
|||||||
pauseLogbookUpdate = false
|
pauseLogbookUpdate = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val updateValues = {
|
||||||
|
quantityTextView.text = NumericUtils(this).formatEventQuantity(event)
|
||||||
|
notesTextView.text = event.notes
|
||||||
|
if (event.type == LunaEvent.Type.SLEEP && event.quantity > 0) {
|
||||||
|
dateEndTextView.text = DateUtils.formatDateTime(event.getEndTime())
|
||||||
|
dateEndTextView.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
dateEndTextView.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).visibility = if (eventValuesChanged()) {
|
||||||
|
View.VISIBLE
|
||||||
|
} else {
|
||||||
|
View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateValues()
|
||||||
|
|
||||||
|
dateTimePicker(event.time, dateTextView, { newTime: Long ->
|
||||||
|
event.time = newTime
|
||||||
|
updateValues()
|
||||||
|
})
|
||||||
|
|
||||||
|
quantityTextView.setOnClickListener {
|
||||||
|
when (event.type) {
|
||||||
|
LunaEvent.Type.BABY_BOTTLE -> askBabyBottleContent(event, false, updateValues)
|
||||||
|
LunaEvent.Type.WEIGHT -> askWeightValue(event, false, updateValues)
|
||||||
|
LunaEvent.Type.HEIGHT -> askHeightValue(event, false, updateValues)
|
||||||
|
LunaEvent.Type.DIAPERCHANGE_POO,
|
||||||
|
LunaEvent.Type.DIAPERCHANGE_PEE,
|
||||||
|
LunaEvent.Type.PUKE -> askAmountValue(event, false, updateValues)
|
||||||
|
LunaEvent.Type.TEMPERATURE -> askTemperatureValue(event, false, updateValues)
|
||||||
|
LunaEvent.Type.FOOD,
|
||||||
|
LunaEvent.Type.MEDICINE,
|
||||||
|
LunaEvent.Type.NOTE -> askNotes(event, false, updateValues)
|
||||||
|
LunaEvent.Type.SLEEP -> askDurationEvent(event, false, updateValues)
|
||||||
|
else -> {
|
||||||
|
Log.w(TAG, "Unexpected type: ${event.type}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notesTextView.setOnClickListener {
|
||||||
|
when (event.type) {
|
||||||
|
LunaEvent.Type.FOOD,
|
||||||
|
LunaEvent.Type.MEDICINE,
|
||||||
|
LunaEvent.Type.NOTE -> askNotes(event, false, updateValues)
|
||||||
|
else -> {
|
||||||
|
Log.w(TAG, "Unexpected type: ${event.type}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// show optional signature
|
// show optional signature
|
||||||
if (event.signature.isNotEmpty()) {
|
if (event.signature.isNotEmpty()) {
|
||||||
val signatureTextEdit = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_signature)
|
val signatureTextEdit = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_signature)
|
||||||
@@ -638,14 +935,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
signatureTextEdit.visibility = View.VISIBLE
|
signatureTextEdit.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
val allEvents = getAllEvents()
|
|
||||||
|
|
||||||
// create link to prevent event of the same type
|
// create link to prevent event of the same type
|
||||||
val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous)
|
val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous)
|
||||||
val previousEvent = getPreviousSameEvent(event, allEvents)
|
val previousEvent = getPreviousSameEvent(event, allEvents)
|
||||||
if (previousEvent != null) {
|
if (previousEvent != null) {
|
||||||
val emoji = previousEvent.getTypeEmoji(applicationContext)
|
val emoji = previousEvent.getHeaderEmoji(applicationContext)
|
||||||
val time = DateUtils.formatTimeDuration(applicationContext, event.time - previousEvent.time)
|
val time = DateUtils.formatTimeDuration(applicationContext, event.getStartTime() - previousEvent.getEndTime())
|
||||||
previousTextView.text = String.format("⬅️ %s %s", emoji, time)
|
previousTextView.text = String.format("⬅️ %s %s", emoji, time)
|
||||||
previousTextView.setOnClickListener {
|
previousTextView.setOnClickListener {
|
||||||
alertDialog.cancel()
|
alertDialog.cancel()
|
||||||
@@ -659,8 +954,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val nextTextView = dialogView.findViewById<TextView>(R.id.dialog_event_next)
|
val nextTextView = dialogView.findViewById<TextView>(R.id.dialog_event_next)
|
||||||
val nextEvent = getNextSameEvent(event, allEvents)
|
val nextEvent = getNextSameEvent(event, allEvents)
|
||||||
if (nextEvent != null) {
|
if (nextEvent != null) {
|
||||||
val emoji = nextEvent.getTypeEmoji(applicationContext)
|
val emoji = nextEvent.getHeaderEmoji(applicationContext)
|
||||||
val time = DateUtils.formatTimeDuration(applicationContext, nextEvent.time - event.time)
|
val time = DateUtils.formatTimeDuration(applicationContext, nextEvent.getStartTime() - event.getEndTime())
|
||||||
nextTextView.text = String.format("%s %s ➡️", time, emoji)
|
nextTextView.text = String.format("%s %s ➡️", time, emoji)
|
||||||
nextTextView.setOnClickListener {
|
nextTextView.setOnClickListener {
|
||||||
alertDialog.cancel()
|
alertDialog.cancel()
|
||||||
@@ -705,7 +1000,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val spinner = findViewById<Spinner>(R.id.logbooks_spinner)
|
val spinner = findViewById<Spinner>(R.id.logbooks_spinner)
|
||||||
val sAdapter = ArrayAdapter<String>(this@MainActivity, android.R.layout.simple_spinner_item)
|
val sAdapter = ArrayAdapter<String>(this@MainActivity, android.R.layout.simple_spinner_item)
|
||||||
sAdapter.setDropDownViewResource(R.layout.row_logbook_spinner)
|
sAdapter.setDropDownViewResource(R.layout.row_logbook_spinner)
|
||||||
for (ln in logbooksNames) {
|
|
||||||
|
val selectedLogbook = settingsRepository.loadSelectedLogbook()
|
||||||
|
logbooksNames.forEach { ln ->
|
||||||
sAdapter.add(
|
sAdapter.add(
|
||||||
ln.ifEmpty { getString(R.string.default_logbook_name) }
|
ln.ifEmpty { getString(R.string.default_logbook_name) }
|
||||||
)
|
)
|
||||||
@@ -718,14 +1015,20 @@ class MainActivity : AppCompatActivity() {
|
|||||||
position: Int,
|
position: Int,
|
||||||
id: Long
|
id: Long
|
||||||
) {
|
) {
|
||||||
|
val logbookName = logbooksNames[position]
|
||||||
// Changed logbook: empty list
|
// Changed logbook: empty list
|
||||||
setListAdapter(arrayListOf())
|
setListAdapter(arrayListOf())
|
||||||
// Load logbook
|
// Load logbook
|
||||||
loadLogbook(logbooksNames.get(position))
|
loadLogbook(logbookName)
|
||||||
|
// Save logbook selection
|
||||||
|
settingsRepository.saveSelectedLogbook(logbookName)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val selected = logbooksNames.indexOf(selectedLogbook)
|
||||||
|
if (selected > 0) spinner.setSelection(selected)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,7 +1075,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
runOnUiThread({
|
runOnUiThread({
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
loadLogbookList()
|
loadLogbookList()
|
||||||
Toast.makeText(applicationContext, getString(R.string.logbook_created) + logbookName, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@MainActivity, getString(R.string.logbook_created) + logbookName, Toast.LENGTH_SHORT).show()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,9 +1131,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
logbook = lb
|
logbook = lb
|
||||||
showLogbook()
|
showLogbook()
|
||||||
|
|
||||||
|
populateHeaderMenu()
|
||||||
|
|
||||||
if (DEBUG_CHECK_LOGBOOK_CONSISTENCY) {
|
if (DEBUG_CHECK_LOGBOOK_CONSISTENCY) {
|
||||||
for (e in logbook?.logs ?: listOf()) {
|
for (e in logbook?.logs ?: listOf()) {
|
||||||
val em = e.getTypeEmoji(this@MainActivity)
|
val em = e.getHeaderEmoji(this@MainActivity)
|
||||||
if (em == getString(R.string.event_unknown_type)) {
|
if (em == getString(R.string.event_unknown_type)) {
|
||||||
Log.e(TAG, "UNKNOWN: ${e.type}")
|
Log.e(TAG, "UNKNOWN: ${e.type}")
|
||||||
}
|
}
|
||||||
@@ -885,23 +1190,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun logEvent(event: LunaEvent) {
|
|
||||||
savingEvent(true)
|
|
||||||
|
|
||||||
event.signature = signature
|
|
||||||
|
|
||||||
setLoading(true)
|
|
||||||
logbook?.logs?.add(0, event)
|
|
||||||
recyclerView.adapter?.notifyItemInserted(0)
|
|
||||||
recyclerView.smoothScrollToPosition(0)
|
|
||||||
saveLogbook(event)
|
|
||||||
|
|
||||||
// Check logbook size to avoid OOM errors
|
|
||||||
if (logbook?.isTooBig() == true) {
|
|
||||||
askToTrimLogbook()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteEvent(event: LunaEvent) {
|
fun deleteEvent(event: LunaEvent) {
|
||||||
// Update view
|
// Update view
|
||||||
savingEvent(true)
|
savingEvent(true)
|
||||||
@@ -913,6 +1201,32 @@ class MainActivity : AppCompatActivity() {
|
|||||||
saveLogbook()
|
saveLogbook()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun saveEvent(event: LunaEvent) {
|
||||||
|
if (allEvents.contains(event)) {
|
||||||
|
// event was modified
|
||||||
|
logbook?.sort()
|
||||||
|
recyclerView.adapter?.notifyDataSetChanged()
|
||||||
|
saveLogbook()
|
||||||
|
} else {
|
||||||
|
// add new event
|
||||||
|
savingEvent(true)
|
||||||
|
setLoading(true)
|
||||||
|
if (signature.isNotEmpty()) {
|
||||||
|
event.signature = signature
|
||||||
|
}
|
||||||
|
logbook?.logs?.add(0, event)
|
||||||
|
logbook?.sort()
|
||||||
|
recyclerView.adapter?.notifyDataSetChanged()
|
||||||
|
recyclerView.smoothScrollToPosition(0)
|
||||||
|
saveLogbook(event)
|
||||||
|
|
||||||
|
// Check logbook size to avoid OOM errors
|
||||||
|
if (logbook?.isTooBig() == true) {
|
||||||
|
askToTrimLogbook()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the logbook. If saving while adding an event, please specify the event so in case
|
* Saves the logbook. If saving while adding an event, please specify the event so in case
|
||||||
* of error can be removed from the list.
|
* of error can be removed from the list.
|
||||||
@@ -929,7 +1243,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext,
|
this@MainActivity,
|
||||||
if (lastEventAdded != null)
|
if (lastEventAdded != null)
|
||||||
R.string.toast_event_added
|
R.string.toast_event_added
|
||||||
else
|
else
|
||||||
@@ -937,6 +1251,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
savingEvent(false)
|
savingEvent(false)
|
||||||
|
|
||||||
|
populateHeaderMenu()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -991,7 +1307,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
runOnUiThread({
|
runOnUiThread({
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
||||||
Toast.makeText(applicationContext, R.string.toast_event_add_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@MainActivity, R.string.toast_event_add_error, Toast.LENGTH_SHORT).show()
|
||||||
recyclerView.adapter?.notifyDataSetChanged()
|
recyclerView.adapter?.notifyDataSetChanged()
|
||||||
savingEvent(false)
|
savingEvent(false)
|
||||||
})
|
})
|
||||||
@@ -1015,6 +1331,30 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showCreateDialog(type: LunaEvent.Type) {
|
||||||
|
val event = LunaEvent(type)
|
||||||
|
when (type) {
|
||||||
|
LunaEvent.Type.BABY_BOTTLE -> addBabyBottleEvent(event)
|
||||||
|
LunaEvent.Type.WEIGHT -> addWeightEvent(event)
|
||||||
|
LunaEvent.Type.HEIGHT -> addHeightEvent(event)
|
||||||
|
LunaEvent.Type.BREASTFEEDING_LEFT_NIPPLE -> addPlainEvent(event)
|
||||||
|
LunaEvent.Type.BREASTFEEDING_BOTH_NIPPLE -> addPlainEvent(event)
|
||||||
|
LunaEvent.Type.BREASTFEEDING_RIGHT_NIPPLE -> addPlainEvent(event)
|
||||||
|
LunaEvent.Type.DIAPERCHANGE_POO -> addAmountEvent(event)
|
||||||
|
LunaEvent.Type.DIAPERCHANGE_PEE -> addAmountEvent(event)
|
||||||
|
LunaEvent.Type.MEDICINE -> addNoteEvent(event)
|
||||||
|
LunaEvent.Type.ENEMA -> addNoteEvent(event)
|
||||||
|
LunaEvent.Type.NOTE -> addNoteEvent(event)
|
||||||
|
LunaEvent.Type.COLIC -> addPlainEvent(event)
|
||||||
|
LunaEvent.Type.TEMPERATURE -> addTemperatureEvent(event)
|
||||||
|
LunaEvent.Type.FOOD -> addNoteEvent(event)
|
||||||
|
LunaEvent.Type.PUKE -> addAmountEvent(event)
|
||||||
|
LunaEvent.Type.BATH -> addPlainEvent(event)
|
||||||
|
LunaEvent.Type.SLEEP -> addDurationEvent(event)
|
||||||
|
LunaEvent.Type.UNKNOWN -> {} // ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showOverflowPopupWindow(anchor: View) {
|
private fun showOverflowPopupWindow(anchor: View) {
|
||||||
if (showingOverflowPopupWindow)
|
if (showingOverflowPopupWindow)
|
||||||
return
|
return
|
||||||
@@ -1023,37 +1363,19 @@ class MainActivity : AppCompatActivity() {
|
|||||||
isOutsideTouchable = true
|
isOutsideTouchable = true
|
||||||
val inflater = LayoutInflater.from(anchor.context)
|
val inflater = LayoutInflater.from(anchor.context)
|
||||||
contentView = inflater.inflate(R.layout.more_events_popup, null)
|
contentView = inflater.inflate(R.layout.more_events_popup, null)
|
||||||
contentView.findViewById<View>(R.id.button_medicine).setOnClickListener {
|
|
||||||
addNoteEvent(LunaEvent(LunaEvent.TYPE_MEDICINE))
|
val linearLayout = contentView.findViewById<LinearLayout>(R.id.layout_list)
|
||||||
|
|
||||||
|
// Add buttons to create other events
|
||||||
|
for (type in currentPopupItems) {
|
||||||
|
val view = layoutInflater.inflate(R.layout.more_events_popup_item, linearLayout, false)
|
||||||
|
val textView = view.findViewById<TextView>(R.id.tv)
|
||||||
|
textView.text = LunaEvent.getPopupItemTitle(applicationContext, type)
|
||||||
|
textView.setOnClickListener {
|
||||||
|
showCreateDialog(type)
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
contentView.findViewById<View>(R.id.button_enema).setOnClickListener {
|
linearLayout.addView(textView)
|
||||||
addPlainEvent(LunaEvent(LunaEvent.TYPE_ENEMA))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
contentView.findViewById<View>(R.id.button_note).setOnClickListener {
|
|
||||||
addNoteEvent(LunaEvent(LunaEvent.TYPE_NOTE))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
contentView.findViewById<View>(R.id.button_temperature).setOnClickListener {
|
|
||||||
addTemperatureEvent(LunaEvent(LunaEvent.TYPE_TEMPERATURE))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
contentView.findViewById<View>(R.id.button_puke).setOnClickListener {
|
|
||||||
addAmountEvent(LunaEvent(LunaEvent.TYPE_PUKE))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
contentView.findViewById<View>(R.id.button_colic).setOnClickListener {
|
|
||||||
addPlainEvent(LunaEvent(LunaEvent.TYPE_COLIC))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
contentView.findViewById<View>(R.id.button_scale).setOnClickListener {
|
|
||||||
addWeightEvent(LunaEvent(LunaEvent.TYPE_WEIGHT))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
contentView.findViewById<View>(R.id.button_bath).setOnClickListener {
|
|
||||||
addPlainEvent(LunaEvent(LunaEvent.TYPE_BATH))
|
|
||||||
dismiss()
|
|
||||||
}
|
}
|
||||||
}.also { popupWindow ->
|
}.also { popupWindow ->
|
||||||
popupWindow.setOnDismissListener({
|
popupWindow.setOnDismissListener({
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.RadioButton
|
import android.widget.RadioButton
|
||||||
|
import android.widget.Spinner
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
@@ -24,7 +25,7 @@ open class SettingsActivity : AppCompatActivity() {
|
|||||||
protected lateinit var textViewWebDAVUser: TextView
|
protected lateinit var textViewWebDAVUser: TextView
|
||||||
protected lateinit var textViewWebDAVPass: TextView
|
protected lateinit var textViewWebDAVPass: TextView
|
||||||
protected lateinit var progressIndicator: LinearProgressIndicator
|
protected lateinit var progressIndicator: LinearProgressIndicator
|
||||||
protected lateinit var switchNoBreastfeeding: SwitchMaterial
|
protected lateinit var switchDynamicMenu: SwitchMaterial
|
||||||
protected lateinit var textViewSignature: EditText
|
protected lateinit var textViewSignature: EditText
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -37,7 +38,7 @@ open class SettingsActivity : AppCompatActivity() {
|
|||||||
textViewWebDAVUser = findViewById(R.id.settings_data_webdav_user)
|
textViewWebDAVUser = findViewById(R.id.settings_data_webdav_user)
|
||||||
textViewWebDAVPass = findViewById(R.id.settings_data_webdav_pass)
|
textViewWebDAVPass = findViewById(R.id.settings_data_webdav_pass)
|
||||||
progressIndicator = findViewById(R.id.progress_indicator)
|
progressIndicator = findViewById(R.id.progress_indicator)
|
||||||
switchNoBreastfeeding = findViewById(R.id.switch_no_breastfeeding)
|
switchDynamicMenu = findViewById(R.id.switch_dynamic_menu)
|
||||||
textViewSignature = findViewById(R.id.settings_signature)
|
textViewSignature = findViewById(R.id.settings_signature)
|
||||||
|
|
||||||
findViewById<View>(R.id.settings_save).setOnClickListener({
|
findViewById<View>(R.id.settings_save).setOnClickListener({
|
||||||
@@ -54,7 +55,7 @@ open class SettingsActivity : AppCompatActivity() {
|
|||||||
fun loadSettings() {
|
fun loadSettings() {
|
||||||
val dataRepo = settingsRepository.loadDataRepository()
|
val dataRepo = settingsRepository.loadDataRepository()
|
||||||
val webDavCredentials = settingsRepository.loadWebdavCredentials()
|
val webDavCredentials = settingsRepository.loadWebdavCredentials()
|
||||||
val noBreastfeeding = settingsRepository.loadNoBreastfeeding()
|
val dynamicMenu = settingsRepository.loadDynamicMenu()
|
||||||
val signature = settingsRepository.loadSignature()
|
val signature = settingsRepository.loadSignature()
|
||||||
|
|
||||||
when (dataRepo) {
|
when (dataRepo) {
|
||||||
@@ -63,7 +64,7 @@ open class SettingsActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
textViewSignature.setText(signature)
|
textViewSignature.setText(signature)
|
||||||
switchNoBreastfeeding.isChecked = noBreastfeeding
|
switchDynamicMenu.isChecked = dynamicMenu
|
||||||
|
|
||||||
if (webDavCredentials != null) {
|
if (webDavCredentials != null) {
|
||||||
textViewWebDAVUrl.text = webDavCredentials[0]
|
textViewWebDAVUrl.text = webDavCredentials[0]
|
||||||
@@ -160,7 +161,7 @@ open class SettingsActivity : AppCompatActivity() {
|
|||||||
if (radioDataWebDAV.isChecked) LocalSettingsRepository.DATA_REPO.WEBDAV
|
if (radioDataWebDAV.isChecked) LocalSettingsRepository.DATA_REPO.WEBDAV
|
||||||
else LocalSettingsRepository.DATA_REPO.LOCAL_FILE
|
else LocalSettingsRepository.DATA_REPO.LOCAL_FILE
|
||||||
)
|
)
|
||||||
settingsRepository.saveNoBreastfeeding(switchNoBreastfeeding.isChecked)
|
settingsRepository.saveDynamicMenu(switchDynamicMenu.isChecked)
|
||||||
settingsRepository.saveSignature(textViewSignature.text.toString())
|
settingsRepository.saveSignature(textViewSignature.text.toString())
|
||||||
settingsRepository.saveWebdavCredentials(
|
settingsRepository.saveWebdavCredentials(
|
||||||
textViewWebDAVUrl.text.toString(),
|
textViewWebDAVUrl.text.toString(),
|
||||||
|
|||||||
+22
-10
@@ -52,19 +52,18 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
|
|||||||
)
|
)
|
||||||
holder.quantity.setTextColor(ContextCompat.getColor(context, R.color.textColor))
|
holder.quantity.setTextColor(ContextCompat.getColor(context, R.color.textColor))
|
||||||
// Contents
|
// Contents
|
||||||
holder.type.text = item.getTypeEmoji(context)
|
holder.type.text = item.getHeaderEmoji(context)
|
||||||
holder.description.text = when (item.type) {
|
holder.description.text = when (item.type) {
|
||||||
LunaEvent.TYPE_MEDICINE -> item.notes
|
LunaEvent.Type.MEDICINE -> item.notes
|
||||||
LunaEvent.TYPE_NOTE -> item.notes
|
LunaEvent.Type.NOTE -> item.notes
|
||||||
LunaEvent.TYPE_CUSTOM -> item.notes
|
else -> item.getRowItemTitle(context)
|
||||||
else -> item.getTypeDescription(context)
|
|
||||||
}
|
}
|
||||||
holder.time.text = DateUtils.formatTimeAgo(context, item.time)
|
holder.time.text = DateUtils.formatTimeAgo(context, item.getEndTime())
|
||||||
var quantityText = numericUtils.formatEventQuantity(item)
|
var quantityText = numericUtils.formatEventQuantity(item)
|
||||||
|
|
||||||
// if the event is weight, show difference with the last one
|
// if the event is weight, show difference with the last one
|
||||||
if (item.type == LunaEvent.TYPE_WEIGHT) {
|
if (item.type == LunaEvent.Type.WEIGHT) {
|
||||||
val lastWeight = getPreviousWeightEvent(position)
|
val lastWeight = getPreviousEvent(position, LunaEvent.Type.WEIGHT)
|
||||||
if (lastWeight != null) {
|
if (lastWeight != null) {
|
||||||
val differenceInWeight = item.quantity - lastWeight.quantity
|
val differenceInWeight = item.quantity - lastWeight.quantity
|
||||||
val sign = if (differenceInWeight > 0) "+" else ""
|
val sign = if (differenceInWeight > 0) "+" else ""
|
||||||
@@ -75,6 +74,19 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the event is height, show difference with the last one
|
||||||
|
if (item.type == LunaEvent.Type.HEIGHT) {
|
||||||
|
val lastHeight = getPreviousEvent(position, LunaEvent.Type.HEIGHT)
|
||||||
|
if (lastHeight != null) {
|
||||||
|
val differenceInHeight = item.quantity - lastHeight.quantity
|
||||||
|
val sign = if (differenceInHeight > 0) "+" else ""
|
||||||
|
quantityText += "\n($sign$differenceInHeight)"
|
||||||
|
if (differenceInHeight < 0) {
|
||||||
|
holder.quantity.setTextColor(ContextCompat.getColor(context, R.color.danger))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
holder.quantity.text = quantityText
|
holder.quantity.text = quantityText
|
||||||
|
|
||||||
// Listeners
|
// Listeners
|
||||||
@@ -89,12 +101,12 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
|
|||||||
return items.size
|
return items.size
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPreviousWeightEvent(startFromPosition: Int): LunaEvent? {
|
private fun getPreviousEvent(startFromPosition: Int, type: LunaEvent.Type): LunaEvent? {
|
||||||
if (startFromPosition == items.size - 1)
|
if (startFromPosition == items.size - 1)
|
||||||
return null
|
return null
|
||||||
for (pos in startFromPosition + 1 until items.size) {
|
for (pos in startFromPosition + 1 until items.size) {
|
||||||
val item = items.get(pos)
|
val item = items.get(pos)
|
||||||
if (item.type != LunaEvent.TYPE_WEIGHT)
|
if (item.type != type)
|
||||||
continue
|
continue
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,24 +12,25 @@ import java.util.Date
|
|||||||
* release, it is simply ignored by previous ones).
|
* release, it is simply ignored by previous ones).
|
||||||
*/
|
*/
|
||||||
class LunaEvent: Comparable<LunaEvent> {
|
class LunaEvent: Comparable<LunaEvent> {
|
||||||
|
enum class Type {
|
||||||
companion object {
|
BABY_BOTTLE,
|
||||||
const val TYPE_BABY_BOTTLE = "BABY_BOTTLE"
|
FOOD,
|
||||||
const val TYPE_WEIGHT = "WEIGHT"
|
BREASTFEEDING_LEFT_NIPPLE,
|
||||||
const val TYPE_BREASTFEEDING_LEFT_NIPPLE = "BREASTFEEDING_LEFT_NIPPLE"
|
BREASTFEEDING_BOTH_NIPPLE,
|
||||||
const val TYPE_BREASTFEEDING_BOTH_NIPPLE = "BREASTFEEDING_BOTH_NIPPLE"
|
BREASTFEEDING_RIGHT_NIPPLE,
|
||||||
const val TYPE_BREASTFEEDING_RIGHT_NIPPLE = "BREASTFEEDING_RIGHT_NIPPLE"
|
DIAPERCHANGE_POO,
|
||||||
const val TYPE_DIAPERCHANGE_POO = "DIAPERCHANGE_POO"
|
DIAPERCHANGE_PEE,
|
||||||
const val TYPE_DIAPERCHANGE_PEE = "DIAPERCHANGE_PEE"
|
SLEEP,
|
||||||
const val TYPE_MEDICINE = "MEDICINE"
|
WEIGHT,
|
||||||
const val TYPE_ENEMA = "ENEMA"
|
HEIGHT,
|
||||||
const val TYPE_NOTE = "NOTE"
|
MEDICINE,
|
||||||
const val TYPE_CUSTOM = "CUSTOM"
|
ENEMA,
|
||||||
const val TYPE_COLIC = "COLIC"
|
NOTE,
|
||||||
const val TYPE_TEMPERATURE = "TEMPERATURE"
|
COLIC,
|
||||||
const val TYPE_FOOD = "FOOD"
|
TEMPERATURE,
|
||||||
const val TYPE_PUKE = "PUKE"
|
PUKE,
|
||||||
const val TYPE_BATH = "BATH"
|
BATH,
|
||||||
|
UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
private val jo: JSONObject
|
private val jo: JSONObject
|
||||||
@@ -39,16 +40,24 @@ class LunaEvent: Comparable<LunaEvent> {
|
|||||||
set(value) {
|
set(value) {
|
||||||
jo.put("time", value)
|
jo.put("time", value)
|
||||||
}
|
}
|
||||||
var type: String
|
var type: Type
|
||||||
get(): String = jo.getString("type")
|
get(): Type {
|
||||||
|
return try {
|
||||||
|
Type.valueOf(jo.getString("type"))
|
||||||
|
} catch (_: Exception) {
|
||||||
|
Type.UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
jo.put("type", value)
|
jo.put("type", value.name)
|
||||||
}
|
}
|
||||||
var quantity: Int
|
var quantity: Int
|
||||||
get() = jo.optInt("quantity", -1)
|
get() = jo.optInt("quantity")
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value >= 0)
|
if (value > 0)
|
||||||
jo.put("quantity", value)
|
jo.put("quantity", value)
|
||||||
|
else
|
||||||
|
jo.remove("quantity")
|
||||||
}
|
}
|
||||||
var notes: String
|
var notes: String
|
||||||
get(): String = jo.optString("notes")
|
get(): String = jo.optString("notes")
|
||||||
@@ -78,78 +87,45 @@ class LunaEvent: Comparable<LunaEvent> {
|
|||||||
this.signature = event.signature
|
this.signature = event.signature
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(type: String) {
|
constructor(type: Type) {
|
||||||
this.jo = JSONObject()
|
this.jo = JSONObject()
|
||||||
this.time = System.currentTimeMillis() / 1000
|
this.time = System.currentTimeMillis() / 1000
|
||||||
this.type = type
|
this.type = type
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(type: String, quantity: Int) {
|
constructor(type: Type, quantity: Int) {
|
||||||
this.jo = JSONObject()
|
this.jo = JSONObject()
|
||||||
this.time = System.currentTimeMillis() / 1000
|
this.time = System.currentTimeMillis() / 1000
|
||||||
this.type = type
|
this.type = type
|
||||||
this.quantity = quantity
|
this.quantity = quantity
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTypeEmoji(context: Context): String {
|
fun getHeaderEmoji(context: Context): String {
|
||||||
return context.getString(
|
return getHeaderEmoji(context, type)
|
||||||
when (type) {
|
|
||||||
TYPE_BABY_BOTTLE -> R.string.event_bottle_type
|
|
||||||
TYPE_WEIGHT -> R.string.event_weight_type
|
|
||||||
TYPE_BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_type
|
|
||||||
TYPE_BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type
|
|
||||||
TYPE_BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type
|
|
||||||
TYPE_DIAPERCHANGE_POO -> R.string.event_diaperchange_poo_type
|
|
||||||
TYPE_DIAPERCHANGE_PEE -> R.string.event_diaperchange_pee_type
|
|
||||||
TYPE_MEDICINE -> R.string.event_medicine_type
|
|
||||||
TYPE_ENEMA -> R.string.event_enema_type
|
|
||||||
TYPE_NOTE -> R.string.event_note_type
|
|
||||||
TYPE_TEMPERATURE -> R.string.event_temperature_type
|
|
||||||
TYPE_COLIC -> R.string.event_colic_type
|
|
||||||
TYPE_FOOD -> R.string.event_food_type
|
|
||||||
TYPE_PUKE -> R.string.event_puke_type
|
|
||||||
TYPE_BATH -> R.string.event_bath_type
|
|
||||||
else -> R.string.event_unknown_type
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTypeDescription(context: Context): String {
|
fun getDialogTitle(context: Context): String {
|
||||||
return context.getString(
|
return getDialogTitle(context, type)
|
||||||
when (type) {
|
|
||||||
TYPE_BABY_BOTTLE -> R.string.event_bottle_desc
|
|
||||||
TYPE_WEIGHT -> R.string.event_weight_desc
|
|
||||||
TYPE_BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_desc
|
|
||||||
TYPE_BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc
|
|
||||||
TYPE_BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc
|
|
||||||
TYPE_DIAPERCHANGE_POO -> R.string.event_diaperchange_poo_desc
|
|
||||||
TYPE_DIAPERCHANGE_PEE -> R.string.event_diaperchange_pee_desc
|
|
||||||
TYPE_MEDICINE -> R.string.event_medicine_desc
|
|
||||||
TYPE_ENEMA -> R.string.event_enema_desc
|
|
||||||
TYPE_NOTE -> R.string.event_note_desc
|
|
||||||
TYPE_TEMPERATURE -> R.string.event_temperature_desc
|
|
||||||
TYPE_COLIC -> R.string.event_colic_desc
|
|
||||||
TYPE_FOOD -> R.string.event_food_desc
|
|
||||||
TYPE_PUKE -> R.string.event_puke_desc
|
|
||||||
TYPE_BATH -> R.string.event_bath_desc
|
|
||||||
else -> R.string.event_unknown_desc
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDialogMessage(context: Context): String? {
|
fun getRowItemTitle(context: Context): String {
|
||||||
return context.getString(
|
return getPopupItemTitle(context, type).split(" ", limit = 2).last() // remove emoji
|
||||||
when(type) {
|
}
|
||||||
TYPE_BABY_BOTTLE -> R.string.log_bottle_dialog_description
|
|
||||||
TYPE_MEDICINE -> R.string.log_medicine_dialog_description
|
fun getDialogMessage(context: Context): String {
|
||||||
TYPE_TEMPERATURE -> R.string.log_temperature_dialog_description
|
return getDialogMessage(context, type)
|
||||||
TYPE_DIAPERCHANGE_POO,
|
}
|
||||||
TYPE_DIAPERCHANGE_PEE,
|
|
||||||
TYPE_PUKE -> R.string.log_amount_dialog_description
|
fun getStartTime(): Long {
|
||||||
TYPE_WEIGHT -> R.string.log_weight_dialog_description
|
return time
|
||||||
else -> R.string.log_unknown_dialog_description
|
}
|
||||||
|
|
||||||
|
fun getEndTime(): Long {
|
||||||
|
return if (type == Type.SLEEP) {
|
||||||
|
time + quantity
|
||||||
|
} else {
|
||||||
|
time
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toJson(): JSONObject {
|
fun toJson(): JSONObject {
|
||||||
@@ -163,4 +139,99 @@ class LunaEvent: Comparable<LunaEvent> {
|
|||||||
override fun compareTo(other: LunaEvent): Int {
|
override fun compareTo(other: LunaEvent): Int {
|
||||||
return (this.time - other.time).toInt()
|
return (this.time - other.time).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getHeaderEmoji(context: Context, type: Type): String {
|
||||||
|
return context.getString(
|
||||||
|
when (type) {
|
||||||
|
Type.BABY_BOTTLE -> R.string.event_bottle_type
|
||||||
|
Type.WEIGHT -> R.string.event_weight_type
|
||||||
|
Type.HEIGHT -> R.string.event_height_type
|
||||||
|
Type.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_type
|
||||||
|
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type
|
||||||
|
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type
|
||||||
|
Type.DIAPERCHANGE_POO -> R.string.event_diaperchange_poo_type
|
||||||
|
Type.DIAPERCHANGE_PEE -> R.string.event_diaperchange_pee_type
|
||||||
|
Type.MEDICINE -> R.string.event_medicine_type
|
||||||
|
Type.ENEMA -> R.string.event_enema_type
|
||||||
|
Type.NOTE -> R.string.event_note_type
|
||||||
|
Type.TEMPERATURE -> R.string.event_temperature_type
|
||||||
|
Type.COLIC -> R.string.event_colic_type
|
||||||
|
Type.FOOD -> R.string.event_food_type
|
||||||
|
Type.PUKE -> R.string.event_puke_type
|
||||||
|
Type.BATH -> R.string.event_bath_type
|
||||||
|
Type.SLEEP -> R.string.event_sleep_type
|
||||||
|
Type.UNKNOWN -> R.string.event_unknown_type
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDialogMessage(context: Context, type: Type): String {
|
||||||
|
return context.getString(
|
||||||
|
when (type) {
|
||||||
|
Type.BABY_BOTTLE -> R.string.log_bottle_dialog_description
|
||||||
|
Type.MEDICINE -> R.string.log_medicine_dialog_description
|
||||||
|
Type.TEMPERATURE -> R.string.log_temperature_dialog_description
|
||||||
|
Type.DIAPERCHANGE_POO,
|
||||||
|
Type.DIAPERCHANGE_PEE,
|
||||||
|
Type.PUKE -> R.string.log_amount_dialog_description
|
||||||
|
Type.WEIGHT -> R.string.log_weight_dialog_description
|
||||||
|
Type.HEIGHT -> R.string.log_height_dialog_description
|
||||||
|
Type.SLEEP -> R.string.log_duration_dialog_description
|
||||||
|
else -> R.string.log_unknown_dialog_description
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDialogTitle(context: Context, type: Type): String {
|
||||||
|
return context.getString(
|
||||||
|
when (type) {
|
||||||
|
Type.BABY_BOTTLE -> R.string.event_bottle_desc
|
||||||
|
Type.WEIGHT -> R.string.event_weight_desc
|
||||||
|
Type.HEIGHT -> R.string.event_height_desc
|
||||||
|
Type.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_desc
|
||||||
|
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc
|
||||||
|
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc
|
||||||
|
Type.DIAPERCHANGE_POO -> R.string.event_diaperchange_poo_desc
|
||||||
|
Type.DIAPERCHANGE_PEE -> R.string.event_diaperchange_pee_desc
|
||||||
|
Type.MEDICINE -> R.string.event_medicine_desc
|
||||||
|
Type.ENEMA -> R.string.event_enema_desc
|
||||||
|
Type.NOTE -> R.string.event_note_desc
|
||||||
|
Type.TEMPERATURE -> R.string.event_temperature_desc
|
||||||
|
Type.COLIC -> R.string.event_colic_desc
|
||||||
|
Type.FOOD -> R.string.event_food_desc
|
||||||
|
Type.PUKE -> R.string.event_puke_desc
|
||||||
|
Type.BATH -> R.string.event_bath_desc
|
||||||
|
Type.SLEEP -> R.string.event_sleep_desc
|
||||||
|
Type.UNKNOWN -> R.string.event_unknown_desc
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entries for for popup list
|
||||||
|
fun getPopupItemTitle(context: Context, type: Type): String {
|
||||||
|
return context.getString(
|
||||||
|
when (type) {
|
||||||
|
Type.BABY_BOTTLE -> R.string.event_type_item_bottle
|
||||||
|
Type.WEIGHT -> R.string.event_type_item_weight
|
||||||
|
Type.HEIGHT -> R.string.event_type_item_height
|
||||||
|
Type.BREASTFEEDING_LEFT_NIPPLE -> R.string.event_type_item_breastfeeding_left
|
||||||
|
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_type_item_breastfeeding_both
|
||||||
|
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_type_item_breastfeeding_right
|
||||||
|
Type.DIAPERCHANGE_POO -> R.string.event_type_item_diaperchange_poo
|
||||||
|
Type.DIAPERCHANGE_PEE -> R.string.event_type_item_diaperchange_pee
|
||||||
|
Type.MEDICINE -> R.string.event_type_item_medicine
|
||||||
|
Type.ENEMA -> R.string.event_type_item_enema
|
||||||
|
Type.NOTE -> R.string.event_type_item_note
|
||||||
|
Type.TEMPERATURE -> R.string.event_type_item_temperature
|
||||||
|
Type.COLIC -> R.string.event_type_item_colic
|
||||||
|
Type.FOOD -> R.string.event_type_item_food
|
||||||
|
Type.PUKE -> R.string.event_type_item_puke
|
||||||
|
Type.BATH -> R.string.event_type_item_bath
|
||||||
|
Type.SLEEP -> R.string.event_type_item_sleep
|
||||||
|
Type.UNKNOWN -> R.string.event_type_item_unknown
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+16
-5
@@ -13,8 +13,9 @@ class LocalSettingsRepository(val context: Context) {
|
|||||||
const val SHARED_PREFS_DAV_URL = "webdav_url"
|
const val SHARED_PREFS_DAV_URL = "webdav_url"
|
||||||
const val SHARED_PREFS_DAV_USER = "webdav_user"
|
const val SHARED_PREFS_DAV_USER = "webdav_user"
|
||||||
const val SHARED_PREFS_DAV_PASS = "webdav_password"
|
const val SHARED_PREFS_DAV_PASS = "webdav_password"
|
||||||
const val SHARED_PREFS_NO_BREASTFEEDING = "no_breastfeeding"
|
const val SHARED_PREFS_DYNAMIC_MENU = "dynamic_menu"
|
||||||
const val SHARED_PREFS_SIGNATURE = "signature"
|
const val SHARED_PREFS_SIGNATURE = "signature"
|
||||||
|
const val SHARED_PREFS_SELECTED_LOGBOOK = "selected_logbook"
|
||||||
}
|
}
|
||||||
enum class DATA_REPO {LOCAL_FILE, WEBDAV}
|
enum class DATA_REPO {LOCAL_FILE, WEBDAV}
|
||||||
val sharedPreferences: SharedPreferences
|
val sharedPreferences: SharedPreferences
|
||||||
@@ -31,12 +32,12 @@ class LocalSettingsRepository(val context: Context) {
|
|||||||
return sharedPreferences.getString(SHARED_PREFS_SIGNATURE, "") ?: ""
|
return sharedPreferences.getString(SHARED_PREFS_SIGNATURE, "") ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveNoBreastfeeding(content: Boolean) {
|
fun saveDynamicMenu(content: Boolean) {
|
||||||
sharedPreferences.edit { putBoolean(SHARED_PREFS_NO_BREASTFEEDING, content) }
|
sharedPreferences.edit { putBoolean(SHARED_PREFS_DYNAMIC_MENU, content) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadNoBreastfeeding(): Boolean {
|
fun loadDynamicMenu(): Boolean {
|
||||||
return sharedPreferences.getBoolean(SHARED_PREFS_NO_BREASTFEEDING, false)
|
return sharedPreferences.getBoolean(SHARED_PREFS_DYNAMIC_MENU, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveDataRepository(repo: DATA_REPO) {
|
fun saveDataRepository(repo: DATA_REPO) {
|
||||||
@@ -76,4 +77,14 @@ class LocalSettingsRepository(val context: Context) {
|
|||||||
return null
|
return null
|
||||||
return arrayOf(url, user, pass)
|
return arrayOf(url, user, pass)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun saveSelectedLogbook(selectedLogbookName: String) {
|
||||||
|
sharedPreferences.edit (commit = true) {
|
||||||
|
putString(SHARED_PREFS_SELECTED_LOGBOOK, selectedLogbookName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadSelectedLogbook() : String? {
|
||||||
|
return sharedPreferences.getString(SHARED_PREFS_SELECTED_LOGBOOK, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,15 @@ import java.util.Date
|
|||||||
class DateUtils {
|
class DateUtils {
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
* Format time duration in seconds as e.g. "2 hours, 1 min".
|
* Format time duration in seconds as e.g. "2 hours, 1 min", rounded to minutes.
|
||||||
* Used for the duration to the next/previous event in the event details dialog.
|
* Used for the duration to the next/previous event in the event details dialog.
|
||||||
*/
|
*/
|
||||||
fun formatTimeDuration(context: Context, secondsDiff: Long): String {
|
fun formatTimeDuration(context: Context, secondsDiff: Long): String {
|
||||||
|
val adjusted = (secondsDiff + 30) - (secondsDiff + 30) % 60
|
||||||
|
return formatTimeDurationExact(context, adjusted)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatTimeDurationExact(context: Context, secondsDiff: Long): String {
|
||||||
var seconds = secondsDiff
|
var seconds = secondsDiff
|
||||||
|
|
||||||
val years = (seconds / (365 * 24 * 60 * 60F)).toLong()
|
val years = (seconds / (365 * 24 * 60 * 60F)).toLong()
|
||||||
@@ -56,16 +61,14 @@ class DateUtils {
|
|||||||
return builder.toString()
|
return builder.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (years > 0) {
|
if (years != 0L) {
|
||||||
return format(years, days, R.string.year_ago, R.string.years_ago, R.string.day_ago, R.string.days_ago)
|
return format(years, days, R.string.year_ago, R.string.years_ago, R.string.day_ago, R.string.days_ago)
|
||||||
} else if (days > 0) {
|
} else if (days != 0L) {
|
||||||
return format(days, hours, R.string.day_ago, R.string.days_ago, R.string.hour_ago, R.string.hours_ago)
|
return format(days, hours, R.string.day_ago, R.string.days_ago, R.string.hour_ago, R.string.hours_ago)
|
||||||
} else if (hours > 0) {
|
} else if (hours != 0L) {
|
||||||
return format(hours, minutes, R.string.hour_ago, R.string.hours_ago, R.string.minute_ago, R.string.minutes_ago)
|
return format(hours, minutes, R.string.hour_ago, R.string.hours_ago, R.string.minute_ago, R.string.minutes_ago)
|
||||||
} 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 {
|
} else {
|
||||||
return context.getString(R.string.now)
|
return format(minutes, seconds, R.string.minute_ago, R.string.minute_ago, R.string.second_ago, R.string.seconds_ago)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ import android.os.Build
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import it.danieleverducci.lunatracker.R
|
import it.danieleverducci.lunatracker.R
|
||||||
import it.danieleverducci.lunatracker.entities.LunaEvent
|
import it.danieleverducci.lunatracker.entities.LunaEvent
|
||||||
|
import utils.DateUtils.Companion.formatTimeDuration
|
||||||
import java.text.NumberFormat
|
import java.text.NumberFormat
|
||||||
|
|
||||||
class NumericUtils (val context: Context) {
|
class NumericUtils (val context: Context) {
|
||||||
val numberFormat: NumberFormat
|
|
||||||
val measurement_unit_liquid_base: String
|
val measurement_unit_liquid_base: String
|
||||||
val measurement_unit_weight_base: String
|
val measurement_unit_weight_base: String
|
||||||
val measurement_unit_weight_tiny: String
|
val measurement_unit_weight_tiny: String
|
||||||
|
val measurement_unit_height_base: String
|
||||||
val measurement_unit_temperature_base: String
|
val measurement_unit_temperature_base: String
|
||||||
|
|
||||||
private fun isMetricSystem(): Boolean {
|
private fun isMetricSystem(): Boolean {
|
||||||
@@ -34,7 +35,6 @@ class NumericUtils (val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.numberFormat = NumberFormat.getInstance()
|
|
||||||
this.measurement_unit_liquid_base = context.getString(
|
this.measurement_unit_liquid_base = context.getString(
|
||||||
if (isMetricSystem())
|
if (isMetricSystem())
|
||||||
R.string.measurement_unit_liquid_base_metric
|
R.string.measurement_unit_liquid_base_metric
|
||||||
@@ -53,6 +53,12 @@ class NumericUtils (val context: Context) {
|
|||||||
else
|
else
|
||||||
R.string.measurement_unit_weight_tiny_imperial
|
R.string.measurement_unit_weight_tiny_imperial
|
||||||
)
|
)
|
||||||
|
this.measurement_unit_height_base = context.getString(
|
||||||
|
if (isMetricSystem())
|
||||||
|
R.string.measurement_unit_height_base_metric
|
||||||
|
else
|
||||||
|
R.string.measurement_unit_height_base_imperial
|
||||||
|
)
|
||||||
this.measurement_unit_temperature_base = context.getString(
|
this.measurement_unit_temperature_base = context.getString(
|
||||||
if (isMetricSystem())
|
if (isMetricSystem())
|
||||||
R.string.measurement_unit_temperature_base_metric
|
R.string.measurement_unit_temperature_base_metric
|
||||||
@@ -62,45 +68,55 @@ class NumericUtils (val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun formatEventQuantity(event: LunaEvent): String {
|
fun formatEventQuantity(event: LunaEvent): String {
|
||||||
|
return formatEventQuantity(event.type, event.quantity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatEventQuantity(type: LunaEvent.Type, quantity: Int): String {
|
||||||
val formatted = StringBuilder()
|
val formatted = StringBuilder()
|
||||||
if (event.quantity >= 0) {
|
if (quantity > 0) {
|
||||||
formatted.append(when (event.type) {
|
formatted.append(when (type) {
|
||||||
LunaEvent.TYPE_TEMPERATURE ->
|
LunaEvent.Type.TEMPERATURE ->
|
||||||
(event.quantity / 10.0f).toString()
|
(quantity / 10.0f).toString()
|
||||||
LunaEvent.TYPE_DIAPERCHANGE_POO,
|
LunaEvent.Type.DIAPERCHANGE_POO,
|
||||||
LunaEvent.TYPE_DIAPERCHANGE_PEE,
|
LunaEvent.Type.DIAPERCHANGE_PEE,
|
||||||
LunaEvent.TYPE_PUKE -> {
|
LunaEvent.Type.PUKE -> {
|
||||||
val array = context.resources.getStringArray(R.array.AmountLabels)
|
val array = context.resources.getStringArray(R.array.AmountLabels)
|
||||||
return array.getOrElse(event.quantity) {
|
return array.getOrElse(quantity) {
|
||||||
Log.e("NumericUtils", "Invalid index ${event.quantity}")
|
Log.e("NumericUtils", "Invalid index $quantity")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else ->
|
LunaEvent.Type.SLEEP -> formatTimeDuration(context, quantity.toLong())
|
||||||
event.quantity
|
else -> quantity
|
||||||
})
|
})
|
||||||
|
|
||||||
formatted.append(" ")
|
formatted.append(" ")
|
||||||
formatted.append(
|
formatted.append(
|
||||||
when (event.type) {
|
when (type) {
|
||||||
LunaEvent.TYPE_BABY_BOTTLE -> measurement_unit_liquid_base
|
LunaEvent.Type.BABY_BOTTLE -> measurement_unit_liquid_base
|
||||||
LunaEvent.TYPE_WEIGHT -> measurement_unit_weight_base
|
LunaEvent.Type.WEIGHT -> measurement_unit_weight_base
|
||||||
LunaEvent.TYPE_MEDICINE -> measurement_unit_weight_tiny
|
LunaEvent.Type.HEIGHT -> measurement_unit_height_base
|
||||||
LunaEvent.TYPE_TEMPERATURE -> measurement_unit_temperature_base
|
LunaEvent.Type.MEDICINE -> measurement_unit_weight_tiny
|
||||||
|
LunaEvent.Type.TEMPERATURE -> measurement_unit_temperature_base
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
formatted.append(when (type) {
|
||||||
|
LunaEvent.Type.SLEEP -> "💤" // baby is sleeping
|
||||||
|
else -> ""
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return formatted.toString()
|
return formatted.toString().trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a valid quantity range for the event type.
|
* Returns a valid quantity range for the event type.
|
||||||
* @return min, max, normal
|
* @return min, max, normal
|
||||||
*/
|
*/
|
||||||
fun getValidEventQuantityRange(lunaEventType: String): Triple<Int, Int, Int>? {
|
fun getValidEventQuantityRange(lunaEventType: LunaEvent.Type): Triple<Int, Int, Int>? {
|
||||||
return when (lunaEventType) {
|
return when (lunaEventType) {
|
||||||
LunaEvent.TYPE_TEMPERATURE -> {
|
LunaEvent.Type.TEMPERATURE -> {
|
||||||
if (isMetricSystem())
|
if (isMetricSystem())
|
||||||
Triple(
|
Triple(
|
||||||
context.resources.getInteger(R.integer.human_body_temp_min_metric),
|
context.resources.getInteger(R.integer.human_body_temp_min_metric),
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
||||||
@@ -86,15 +86,16 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/linear_layout_row1"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/button_bottle"
|
android:id="@+id/button1_row1"
|
||||||
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="1"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:background="@drawable/button_background"
|
android:background="@drawable/button_background"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
@@ -102,7 +103,7 @@
|
|||||||
android:text="@string/event_bottle_type"/>
|
android:text="@string/event_bottle_type"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/button_food"
|
android:id="@+id/button2_row1"
|
||||||
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"
|
||||||
@@ -115,80 +116,77 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/linear_layout_row2"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/layout_nipples">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_nipple_left"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/button_background"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:text="🤱⬅️"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_nipple_both"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/button_background"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:text="🤱↔️"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_nipple_right"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/button_background"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:text="🤱➡️️"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/button_change_poo"
|
android:id="@+id/button1_row2"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:layout_weight="2"
|
|
||||||
android:background="@drawable/button_background"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:text="🚼 💩"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_change_pee"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:layout_weight="2"
|
|
||||||
android:background="@drawable/button_background"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:text="🚼 💧"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/button_more"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@drawable/button_background"
|
android:background="@drawable/button_background"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:src="@drawable/ic_more"
|
android:textSize="30sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/button2_row2"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/button_background"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:textSize="30sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/button3_row2"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/button_background"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:textSize="30sp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linear_layout_row3"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/button1_row3"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:background="@drawable/button_background"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:textSize="30sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/button2_row3"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:background="@drawable/button_background"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:textSize="30sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/button_more"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/button_background"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:textSize="30sp"
|
||||||
|
android:text="☰"
|
||||||
app:tint="@android:color/darker_gray"/>
|
app:tint="@android:color/darker_gray"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -261,6 +259,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:text="@string/no_connection_explain"/>
|
android:text="@string/no_connection_explain"/>
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="20dp"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:text="@string/settings_signature_desc"/>
|
android:text="@string/settings_signature_desc"/>
|
||||||
|
|
||||||
@@ -149,13 +149,13 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="@string/settings_no_breastfeeding" />
|
android:text="@string/settings_dynamic_menu" />
|
||||||
|
|
||||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
android:id="@+id/switch_no_breastfeeding"
|
android:id="@+id/switch_dynamic_menu"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
@@ -166,9 +166,9 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="20dp"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:text="@string/settings_no_breastfeeding_desc"/>
|
android:text="@string/settings_dynamic_menu_desc"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?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"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/dialog_amount_value"
|
||||||
|
android:layout_width="250dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="16dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_date_picker"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/dialog_number_picker_unit"
|
||||||
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_marginStart="10dp"
|
||||||
@@ -30,6 +31,6 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_marginEnd="20dp"/>
|
android:layout_marginTop="20dp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<?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"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_date_duration"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:text="💤"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/duration_buttons"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/dialog_date_duration_now"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/dialog_duration_button_now"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/dialog_date_duration_clear"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/dialog_duration_button_clear"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_date_picker_begin"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_date_range_delimiter"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="-"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_date_picker_end"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?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:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/dialog_number_edittext"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="number"
|
||||||
|
android:hint="0"
|
||||||
|
android:background="@drawable/textview_background"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_number_unit"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:text="cm"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_date_picker"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginTop="20dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -24,11 +24,34 @@
|
|||||||
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"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/notes_date_picker"
|
android:id="@+id/notes_template_prev"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18dp"
|
||||||
|
android:text="⬅️"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/notes_template_next"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18dp"
|
||||||
|
android:text="➡️"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<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_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_marginTop="20dp"/>
|
android:layout_marginTop="15dp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -3,14 +3,13 @@
|
|||||||
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:gravity="center"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/dialog_date_picker"
|
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_gravity="center"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:layout_marginEnd="20dp"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
android:id="@+id/dialog_date_picker"
|
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_gravity="center"
|
android:layout_marginTop="20dp"/>
|
||||||
android:layout_marginEnd="20dp"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
android:background="@drawable/textview_background"/>
|
android:background="@drawable/textview_background"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/dialog_number_unit"
|
||||||
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_marginStart="10dp"
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -46,6 +45,18 @@
|
|||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:text="@string/dialog_event_detail_quantity"/>
|
android:text="@string/dialog_event_detail_quantity"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_event_detail_type_date_end"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:drawableTint="@color/accent"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="200dp"
|
android:layout_height="200dp"
|
||||||
|
|||||||
@@ -6,89 +6,11 @@
|
|||||||
android:background="@color/transparent">
|
android:background="@color/transparent">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
<!-- Buttons are inserted dynamically -->
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_medicine"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:background="@drawable/dropdown_list_item_background"
|
|
||||||
style="@style/OverflowMenuText"
|
|
||||||
android:text="@string/overflow_event_medicine"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_note"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:background="@drawable/dropdown_list_item_background"
|
|
||||||
style="@style/OverflowMenuText"
|
|
||||||
android:text="@string/overflow_event_note"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_temperature"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:background="@drawable/dropdown_list_item_background"
|
|
||||||
style="@style/OverflowMenuText"
|
|
||||||
android:text="@string/overflow_event_temperature"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_puke"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:background="@drawable/dropdown_list_item_background"
|
|
||||||
style="@style/OverflowMenuText"
|
|
||||||
android:text="@string/overflow_event_puke"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_colic"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:background="@drawable/dropdown_list_item_background"
|
|
||||||
style="@style/OverflowMenuText"
|
|
||||||
android:text="@string/overflow_event_colic"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_scale"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:background="@drawable/dropdown_list_item_background"
|
|
||||||
style="@style/OverflowMenuText"
|
|
||||||
android:text="@string/overflow_event_weight"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_bath"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:background="@drawable/dropdown_list_item_background"
|
|
||||||
style="@style/OverflowMenuText"
|
|
||||||
android:text="@string/overflow_event_bath"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/button_enema"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:background="@drawable/dropdown_list_item_background"
|
|
||||||
style="@style/OverflowMenuText"
|
|
||||||
android:text="@string/overflow_event_enema"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:background="@drawable/dropdown_list_item_background"
|
||||||
|
style="@style/OverflowMenuText"
|
||||||
|
android:text="Item Template"/>
|
||||||
@@ -18,13 +18,6 @@
|
|||||||
<string name="event_colic_desc">Blähungskolik</string>
|
<string name="event_colic_desc">Blähungskolik</string>
|
||||||
<string name="event_unknown_desc"></string>
|
<string name="event_unknown_desc"></string>
|
||||||
|
|
||||||
<string name="overflow_event_weight">⚖️ Gewicht</string>
|
|
||||||
<string name="overflow_event_medicine">💊 Medikament</string>
|
|
||||||
<string name="overflow_event_enema">🪠 Einlauf</string>
|
|
||||||
<string name="overflow_event_note">📝 Notiz</string>
|
|
||||||
<string name="overflow_event_temperature">🌡️ Temperatur</string>
|
|
||||||
<string name="overflow_event_colic">💨 Blähungskolik</string>
|
|
||||||
|
|
||||||
<string name="toast_event_added">Ereignis gespeichert</string>
|
<string name="toast_event_added">Ereignis gespeichert</string>
|
||||||
<string name="toast_logbook_saved">Logbuch gespeichert</string>
|
<string name="toast_logbook_saved">Logbuch gespeichert</string>
|
||||||
<string name="toast_event_add_error">Ereignis konnte nicht protokolliert werden</string>
|
<string name="toast_event_add_error">Ereignis konnte nicht protokolliert werden</string>
|
||||||
@@ -42,7 +35,6 @@
|
|||||||
<string name="no_connection_retry">Erneut versuchen</string>
|
<string name="no_connection_retry">Erneut versuchen</string>
|
||||||
|
|
||||||
<string name="settings_title">Einstellungen</string>
|
<string name="settings_title">Einstellungen</string>
|
||||||
<string name="settings_no_breastfeeding">Kein Stillen</string>
|
|
||||||
<string name="settings_storage">Speicherort für Daten auswählen</string>
|
<string name="settings_storage">Speicherort für Daten auswählen</string>
|
||||||
<string name="settings_storage_local">Auf dem Gerät</string>
|
<string name="settings_storage_local">Auf dem Gerät</string>
|
||||||
<string name="settings_storage_local_desc">Datenschutzfreundlichste Lösung: Deine Daten verlassen dein Gerät nicht</string>
|
<string name="settings_storage_local_desc">Datenschutzfreundlichste Lösung: Deine Daten verlassen dein Gerät nicht</string>
|
||||||
|
|||||||
@@ -18,13 +18,6 @@
|
|||||||
<string name="event_colic_desc">Colique gazeuse</string>
|
<string name="event_colic_desc">Colique gazeuse</string>
|
||||||
<string name="event_unknown_desc"></string>
|
<string name="event_unknown_desc"></string>
|
||||||
|
|
||||||
<string name="overflow_event_weight">⚖️ Poids</string>
|
|
||||||
<string name="overflow_event_medicine">💊 Médicament</string>
|
|
||||||
<string name="overflow_event_enema">🪠 Lavement</string>
|
|
||||||
<string name="overflow_event_note">📝 Note</string>
|
|
||||||
<string name="overflow_event_temperature">🌡️ Température</string>
|
|
||||||
<string name="overflow_event_colic">💨 Colique gazeuse</string>
|
|
||||||
|
|
||||||
<string name="toast_event_added">Entrée ajoutée</string>
|
<string name="toast_event_added">Entrée ajoutée</string>
|
||||||
<string name="toast_logbook_saved">Journal ajouté</string>
|
<string name="toast_logbook_saved">Journal ajouté</string>
|
||||||
<string name="toast_event_add_error">Impossible d\'enregistrer cette entrée</string>
|
<string name="toast_event_add_error">Impossible d\'enregistrer cette entrée</string>
|
||||||
|
|||||||
@@ -3,13 +3,6 @@
|
|||||||
<string name="title">🌜 LunaTracker 🌛</string>
|
<string name="title">🌜 LunaTracker 🌛</string>
|
||||||
<string name="logbook">Diario di bordo</string>
|
<string name="logbook">Diario di bordo</string>
|
||||||
|
|
||||||
<string name="overflow_event_weight">⚖️ Peso</string>
|
|
||||||
<string name="overflow_event_medicine">💊 Medicina</string>
|
|
||||||
<string name="overflow_event_enema">🪠 Clistere</string>
|
|
||||||
<string name="overflow_event_note">📝 Nota</string>
|
|
||||||
<string name="overflow_event_temperature">🌡️ Temperatura</string>
|
|
||||||
<string name="overflow_event_colic">💨 Colichette</string>
|
|
||||||
|
|
||||||
<string name="event_bottle_desc">Biberon</string>
|
<string name="event_bottle_desc">Biberon</string>
|
||||||
<string name="event_food_desc">Cibo</string>
|
<string name="event_food_desc">Cibo</string>
|
||||||
<string name="event_weight_desc">Pesata</string>
|
<string name="event_weight_desc">Pesata</string>
|
||||||
|
|||||||
@@ -3,12 +3,14 @@
|
|||||||
<string name="title">🌜 LunaTracker 🌛</string>
|
<string name="title">🌜 LunaTracker 🌛</string>
|
||||||
<string name="logbook">Logged events</string>
|
<string name="logbook">Logged events</string>
|
||||||
|
|
||||||
|
<!-- menu header items -->
|
||||||
<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_weight_type" translatable="false">⚖️</string>
|
<string name="event_weight_type" translatable="false">⚖️</string>
|
||||||
<string name="event_breastfeeding_left_type" translatable="false">🤱 ←</string>
|
<string name="event_height_type" translatable="false">📏</string>
|
||||||
<string name="event_breastfeeding_both_type" translatable="false">🤱 ↔</string>
|
<string name="event_breastfeeding_left_type" translatable="false">🤱⬅️</string>
|
||||||
<string name="event_breastfeeding_right_type" translatable="false">🤱 →</string>
|
<string name="event_breastfeeding_both_type" translatable="false">🤱↔️</string>
|
||||||
|
<string name="event_breastfeeding_right_type" translatable="false">🤱➡️️</string>
|
||||||
<string name="event_diaperchange_poo_type" translatable="false">🚼 💩</string>
|
<string name="event_diaperchange_poo_type" translatable="false">🚼 💩</string>
|
||||||
<string name="event_diaperchange_pee_type" translatable="false">🚼 💧</string>
|
<string name="event_diaperchange_pee_type" translatable="false">🚼 💧</string>
|
||||||
<string name="event_medicine_type" translatable="false">💊</string>
|
<string name="event_medicine_type" translatable="false">💊</string>
|
||||||
@@ -18,16 +20,39 @@
|
|||||||
<string name="event_colic_type" translatable="false">💨</string>
|
<string name="event_colic_type" translatable="false">💨</string>
|
||||||
<string name="event_puke_type" translatable="false">🤮</string>
|
<string name="event_puke_type" translatable="false">🤮</string>
|
||||||
<string name="event_bath_type" translatable="false">🛁</string>
|
<string name="event_bath_type" translatable="false">🛁</string>
|
||||||
<string name="event_unknown_type" translatable="false">\?</string>
|
<string name="event_sleep_type" translatable="false">💤</string>
|
||||||
|
<string name="event_unknown_type" translatable="false">❓</string>
|
||||||
|
|
||||||
<string name="event_bottle_desc">Baby bottle</string>
|
<!-- dropdown menu item -->
|
||||||
|
<string name="event_type_item_bottle">🍼 Bottle</string>
|
||||||
|
<string name="event_type_item_food">🥣 Food</string>
|
||||||
|
<string name="event_type_item_weight">⚖️ Weight</string>
|
||||||
|
<string name="event_type_item_height">📏 Height</string>
|
||||||
|
<string name="event_type_item_breastfeeding_left">🤱⬅️ Nursing</string>
|
||||||
|
<string name="event_type_item_breastfeeding_both">🤱↔️ Nursing</string>
|
||||||
|
<string name="event_type_item_breastfeeding_right">🤱➡️️ Nursing</string>
|
||||||
|
<string name="event_type_item_diaperchange_poo">🚼💩 Diaper</string>
|
||||||
|
<string name="event_type_item_diaperchange_pee">🚼💧 Diaper</string>
|
||||||
|
<string name="event_type_item_medicine">💊 Medicine</string>
|
||||||
|
<string name="event_type_item_enema">🪠 Enema</string>
|
||||||
|
<string name="event_type_item_note">📝 Note</string>
|
||||||
|
<string name="event_type_item_temperature">🌡️ Temperature</string>
|
||||||
|
<string name="event_type_item_colic">💨 Colic</string>
|
||||||
|
<string name="event_type_item_puke">🤮 Puke</string>
|
||||||
|
<string name="event_type_item_sleep">💤 Sleep</string>
|
||||||
|
<string name="event_type_item_bath">🛁 Bath</string>
|
||||||
|
<string name="event_type_item_unknown">❓ Unknown</string>
|
||||||
|
|
||||||
|
<!-- dialog titles -->
|
||||||
|
<string name="event_bottle_desc">Milk Bottle</string>
|
||||||
<string name="event_food_desc">Food</string>
|
<string name="event_food_desc">Food</string>
|
||||||
<string name="event_weight_desc">Weight</string>
|
<string name="event_weight_desc">Weight</string>
|
||||||
<string name="event_breastfeeding_left_desc">Breastfeeding (left)</string>
|
<string name="event_height_desc">Height</string>
|
||||||
<string name="event_breastfeeding_both_desc">Breastfeeding</string>
|
<string name="event_breastfeeding_left_desc">Nursing (left)</string>
|
||||||
<string name="event_breastfeeding_right_desc">Breastfeeding (right)</string>
|
<string name="event_breastfeeding_both_desc">Nursing (both)</string>
|
||||||
<string name="event_diaperchange_poo_desc">Diaper chg (poo)</string>
|
<string name="event_breastfeeding_right_desc">Nursing (right)</string>
|
||||||
<string name="event_diaperchange_pee_desc">Diaper chg (pee)</string>
|
<string name="event_diaperchange_poo_desc">Diaper Change (poo)</string>
|
||||||
|
<string name="event_diaperchange_pee_desc">Diaper Change (pee)</string>
|
||||||
<string name="event_medicine_desc">Medicine</string>
|
<string name="event_medicine_desc">Medicine</string>
|
||||||
<string name="event_enema_desc">Enema</string>
|
<string name="event_enema_desc">Enema</string>
|
||||||
<string name="event_note_desc">Note</string>
|
<string name="event_note_desc">Note</string>
|
||||||
@@ -35,21 +60,14 @@
|
|||||||
<string name="event_colic_desc">Gaseous colic</string>
|
<string name="event_colic_desc">Gaseous colic</string>
|
||||||
<string name="event_puke_desc">Puke</string>
|
<string name="event_puke_desc">Puke</string>
|
||||||
<string name="event_bath_desc">Bath</string>
|
<string name="event_bath_desc">Bath</string>
|
||||||
<string name="event_unknown_desc"></string>
|
<string name="event_sleep_desc">Sleep</string>
|
||||||
|
<string name="event_unknown_desc">Unknown</string>
|
||||||
<string name="overflow_event_weight">⚖️ Weight</string>
|
|
||||||
<string name="overflow_event_medicine">💊 Medicine</string>
|
|
||||||
<string name="overflow_event_enema">🪠 Enema</string>
|
|
||||||
<string name="overflow_event_note">📝 Note</string>
|
|
||||||
<string name="overflow_event_temperature">🌡️ Temperature</string>
|
|
||||||
<string name="overflow_event_colic">💨 Gaseous colic</string>
|
|
||||||
<string name="overflow_event_puke">🤮 Puke</string>
|
|
||||||
<string name="overflow_event_bath">🛁 Bath</string>
|
|
||||||
|
|
||||||
<string name="toast_event_added">Event logged</string>
|
<string name="toast_event_added">Event logged</string>
|
||||||
<string name="toast_logbook_saved">Logbook saved</string>
|
<string name="toast_logbook_saved">Logbook saved</string>
|
||||||
<string name="toast_event_add_error">Unable to log the event</string>
|
<string name="toast_event_add_error">Unable to log the event</string>
|
||||||
<string name="toast_integer_error">Invalid value. Insert an integer.</string>
|
<string name="toast_integer_error">Invalid value. Insert an integer.</string>
|
||||||
|
<string name="toast_date_error">Invalid date.</string>
|
||||||
|
|
||||||
<string name="now">now</string>
|
<string name="now">now</string>
|
||||||
<string name="second_ago">sec</string>
|
<string name="second_ago">sec</string>
|
||||||
@@ -73,6 +91,8 @@
|
|||||||
<string name="no_connection_go_to_settings">Settings</string>
|
<string name="no_connection_go_to_settings">Settings</string>
|
||||||
<string name="no_connection_retry">Retry</string>
|
<string name="no_connection_retry">Retry</string>
|
||||||
|
|
||||||
|
<string name="settings_dynamic_menu">Dynamic Menu</string>
|
||||||
|
<string name="settings_dynamic_menu_desc">Populate the header menu with the most used events.</string>
|
||||||
<string name="settings_title">Settings</string>
|
<string name="settings_title">Settings</string>
|
||||||
<string name="settings_signature">Signature</string>
|
<string name="settings_signature">Signature</string>
|
||||||
<string name="settings_signature_desc">Attach a signature to each event you create and for others to see. Useful if multiple people add events.</string>
|
<string name="settings_signature_desc">Attach a signature to each event you create and for others to see. Useful if multiple people add events.</string>
|
||||||
@@ -91,8 +111,6 @@
|
|||||||
<string name="settings_webdav_error_generic">Error while trying to access WebDAV:</string>
|
<string name="settings_webdav_error_generic">Error while trying to access WebDAV:</string>
|
||||||
<string name="settings_webdav_creation_error_generic">Unable to save a file on the WebDAV server:</string>
|
<string name="settings_webdav_creation_error_generic">Unable to save a file on the WebDAV server:</string>
|
||||||
<string name="settings_webdav_creation_ok">Successfully connected with the WebDAV server</string>
|
<string name="settings_webdav_creation_ok">Successfully connected with the WebDAV server</string>
|
||||||
<string name="settings_no_breastfeeding">No Breastfeeding</string>
|
|
||||||
<string name="settings_no_breastfeeding_desc">Hide the Breastfeeding buttons for when they are not needed.</string>
|
|
||||||
<string name="settings_json_error">There\'s a save file on the server, but it is corrupted or unreadable. Please delete it </string>
|
<string name="settings_json_error">There\'s a save file on the server, but it is corrupted or unreadable. Please delete it </string>
|
||||||
<string name="settings_generic_error">Error: </string>
|
<string name="settings_generic_error">Error: </string>
|
||||||
<string name="settings_webdav_upload_error">Error while uploading local logbook %1$s to webdav: %2$s</string>
|
<string name="settings_webdav_upload_error">Error while uploading local logbook %1$s to webdav: %2$s</string>
|
||||||
@@ -112,27 +130,44 @@
|
|||||||
<string name="log_temperature_dialog_description">Select the temperature:</string>
|
<string name="log_temperature_dialog_description">Select the temperature:</string>
|
||||||
<string name="log_unknown_dialog_description"></string>
|
<string name="log_unknown_dialog_description"></string>
|
||||||
<string name="log_weight_dialog_description">Insert the weight:</string>
|
<string name="log_weight_dialog_description">Insert the weight:</string>
|
||||||
|
<string name="log_height_dialog_description">Insert the height:</string>
|
||||||
|
<string name="log_duration_dialog_description">Set duration:</string>
|
||||||
|
|
||||||
<string name="measurement_unit_liquid_base_metric" translatable="false">ml</string>
|
<string name="measurement_unit_liquid_base_metric" translatable="false">ml</string>
|
||||||
<string name="measurement_unit_weight_base_metric" translatable="false">g</string>
|
<string name="measurement_unit_weight_base_metric" translatable="false">g</string>
|
||||||
<string name="measurement_unit_weight_tiny_metric" translatable="false">mg</string>
|
<string name="measurement_unit_weight_tiny_metric" translatable="false">mg</string>
|
||||||
|
<string name="measurement_unit_height_base_metric" translatable="false">cm</string>
|
||||||
<string name="measurement_unit_liquid_base_imperial" translatable="false">fl oz.</string>
|
<string name="measurement_unit_liquid_base_imperial" translatable="false">fl oz.</string>
|
||||||
<string name="measurement_unit_weight_base_imperial" translatable="false">oz</string>
|
<string name="measurement_unit_weight_base_imperial" translatable="false">oz</string>
|
||||||
<string name="measurement_unit_weight_tiny_imperial" translatable="false">gr</string>
|
<string name="measurement_unit_weight_tiny_imperial" translatable="false">gr</string>
|
||||||
|
<string name="measurement_unit_height_base_imperial" translatable="false">in</string>
|
||||||
<string name="measurement_unit_temperature_base_imperial" translatable="false">°F</string>
|
<string name="measurement_unit_temperature_base_imperial" translatable="false">°F</string>
|
||||||
<string name="measurement_unit_temperature_base_metric" translatable="false">°C</string>
|
<string name="measurement_unit_temperature_base_metric" translatable="false">°C</string>
|
||||||
|
|
||||||
|
<string name="statistics_bottle_events">Bottle Events</string>
|
||||||
|
<string name="statistics_bottle_sum">Bottle Per Day</string>
|
||||||
|
<string name="statistics_medicine_events">Medicine Events</string>
|
||||||
|
<string name="statistics_sleep_sum">Sleep Per Day</string>
|
||||||
|
<string name="statistics_sleep_events">Sleep Events</string>
|
||||||
|
<string name="statistics_sleep_pattern">Sleep Pattern</string>
|
||||||
|
|
||||||
<string name="row_luna_event_description">Description</string>
|
<string name="row_luna_event_description">Description</string>
|
||||||
<string name="row_luna_event_quantity">Qty</string>
|
<string name="row_luna_event_quantity">Qty</string>
|
||||||
<string name="row_luna_event_time">Time</string>
|
<string name="row_luna_event_time">Time</string>
|
||||||
|
|
||||||
<string name="dialog_event_detail_title">Event detail</string>
|
<string name="dialog_event_detail_title">Event detail</string>
|
||||||
<string name="dialog_event_detail_close_button">OK</string>
|
<string name="dialog_event_detail_close_button">Close</string>
|
||||||
|
<string name="dialog_event_detail_save_button">Save</string>
|
||||||
<string name="dialog_event_detail_delete_button">Delete</string>
|
<string name="dialog_event_detail_delete_button">Delete</string>
|
||||||
<string name="dialog_event_detail_quantity">Quantity</string>
|
<string name="dialog_event_detail_quantity">Quantity</string>
|
||||||
<string name="dialog_event_detail_notes">Notes</string>
|
<string name="dialog_event_detail_notes">Notes</string>
|
||||||
<string name="dialog_event_detail_signature">by %s</string>
|
<string name="dialog_event_detail_signature">by %s</string>
|
||||||
|
|
||||||
|
<string name="dialog_duration_button_clear">Clear</string>
|
||||||
|
<string name="dialog_duration_button_minus_5">-5 min</string>
|
||||||
|
<string name="dialog_duration_button_now">Now</string>
|
||||||
|
<string name="dialog_duration_button_plus_5">+5 min</string>
|
||||||
|
|
||||||
<string name="dialog_add_logbook_title">Add logbook</string>
|
<string name="dialog_add_logbook_title">Add logbook</string>
|
||||||
<string name="dialog_add_logbook_logbookname">👶 Logbook name</string>
|
<string name="dialog_add_logbook_logbookname">👶 Logbook name</string>
|
||||||
<string name="dialog_add_logbook_message">Write a name to identify this logbook. This name will appear on top of the screen and, if you use WebDAV, will be in the save file name as well.</string>
|
<string name="dialog_add_logbook_message">Write a name to identify this logbook. This name will appear on top of the screen and, if you use WebDAV, will be in the save file name as well.</string>
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
<style name="Theme.LunaTracker" parent="Theme.AppCompat.NoActionBar">
|
<style name="Theme.LunaTracker" parent="Theme.AppCompat.NoActionBar">
|
||||||
<item name="colorAccent">@color/accent</item>
|
<item name="colorAccent">@color/accent</item>
|
||||||
<item name="android:textColor">@color/textColor</item>
|
<item name="android:textColor">@color/textColor</item>
|
||||||
|
|
||||||
|
<!-- make the screen not overlap with the system bars -->
|
||||||
|
<item name="android:fitsSystemWindows">true</item>
|
||||||
|
<item name="android:windowTranslucentStatus">true</item>
|
||||||
|
<item name="android:windowTranslucentNavigation">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="OverflowMenuText">
|
<style name="OverflowMenuText">
|
||||||
|
|||||||
@@ -21,3 +21,13 @@ kotlin.code.style=official
|
|||||||
# resources declared in the library itself and none from the library's dependencies,
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
# thereby reducing the size of the R class for that library
|
# thereby reducing the size of the R class for that library
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
|
android.defaults.buildfeatures.resvalues=true
|
||||||
|
android.sdk.defaultTargetSdkToCompileSdkIfUnset=false
|
||||||
|
android.enableAppCompileTimeRClass=false
|
||||||
|
android.usesSdkInManifest.disallowed=false
|
||||||
|
android.uniquePackageNames=false
|
||||||
|
android.dependency.useConstraints=true
|
||||||
|
android.r8.strictFullModeForKeepRules=false
|
||||||
|
android.r8.optimizedResourceShrinking=false
|
||||||
|
android.builtInKotlin=false
|
||||||
|
android.newDsl=false
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.13.0"
|
agp = "9.4.1"
|
||||||
kotlin = "2.0.0"
|
kotlin = "2.2.10"
|
||||||
coreKtx = "1.10.1"
|
coreKtx = "1.10.1"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.1.5"
|
junitVersion = "1.1.5"
|
||||||
@@ -11,6 +11,7 @@ composeBom = "2024.04.01"
|
|||||||
appcompat = "1.7.0"
|
appcompat = "1.7.0"
|
||||||
recyclerview = "1.3.2"
|
recyclerview = "1.3.2"
|
||||||
material = "1.12.0"
|
material = "1.12.0"
|
||||||
|
sardineAndroid = "v0.9"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
@@ -30,6 +31,7 @@ androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit
|
|||||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
|
sardine-android = { module = "com.github.thegrizzlylabs:sardine-android", version.ref = "sardineAndroid" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#Sat Nov 02 10:58:51 CET 2024
|
#Sat Nov 02 10:58:51 CET 2024
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ dependencyResolutionManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven(url = "https://jitpack.io")
|
maven(url = uri("https://jitpack.io"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user