forked from penguin86/luna-tracker
Compare commits
44
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75d02a8548 | ||
|
|
a38f701f87 | ||
|
|
3a46f737bf | ||
|
|
691df16c23 | ||
|
|
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 |
@@ -1,6 +1,8 @@
|
|||||||
*.iml
|
*.iml
|
||||||
.gradle
|
.gradle
|
||||||
/local.properties
|
/local.properties
|
||||||
|
/.idea/deviceManager.xml
|
||||||
|
/.idea/codeStyles
|
||||||
/.idea/caches
|
/.idea/caches
|
||||||
/.idea/libraries
|
/.idea/libraries
|
||||||
/.idea/modules.xml
|
/.idea/modules.xml
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="21" />
|
<bytecodeTargetLevel target="25" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
var currentPopupItems = listOf<LunaEvent.Type>()
|
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
|
||||||
@@ -77,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)
|
||||||
@@ -86,8 +88,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
recyclerView = findViewById(R.id.list_events)
|
recyclerView = findViewById(R.id.list_events)
|
||||||
recyclerView.setLayoutManager(LinearLayoutManager(applicationContext))
|
recyclerView.setLayoutManager(LinearLayoutManager(applicationContext))
|
||||||
|
|
||||||
populateHeaderMenu()
|
|
||||||
|
|
||||||
// Set listeners
|
// Set listeners
|
||||||
findViewById<View>(R.id.logbooks_add_button).setOnClickListener {
|
findViewById<View>(R.id.logbooks_add_button).setOnClickListener {
|
||||||
showAddLogbookDialog(true)
|
showAddLogbookDialog(true)
|
||||||
@@ -138,20 +138,19 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
allEvents = logbook?.logs ?: arrayListOf()
|
allEvents = logbook?.logs ?: arrayListOf()
|
||||||
setListAdapter(allEvents)
|
setListAdapter(allEvents)
|
||||||
|
|
||||||
populateHeaderMenu()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun populateHeaderMenu() {
|
private fun populateHeaderMenu() {
|
||||||
val settingsRepository = LocalSettingsRepository(this)
|
|
||||||
val dynamicMenu = settingsRepository.loadDynamicMenu()
|
val dynamicMenu = settingsRepository.loadDynamicMenu()
|
||||||
val eventTypeStats = mutableMapOf<LunaEvent.Type, Int>()
|
val eventTypeStats = mutableMapOf<LunaEvent.Type, Int>()
|
||||||
|
|
||||||
if (dynamicMenu) {
|
if (dynamicMenu) {
|
||||||
val sampleSize = 100
|
// populate frequency map from all events of the last two weeks
|
||||||
// populate frequency map from first 100 events
|
val lastWeekTime = (System.currentTimeMillis() / 1000) - (14 * 24 * 60 * 60)
|
||||||
allEvents.take(sampleSize.coerceAtMost(allEvents.size)).forEach {
|
allEvents.forEach {
|
||||||
eventTypeStats[it.type] = 1 + (eventTypeStats[it.type] ?: 0)
|
if (it.time > lastWeekTime) {
|
||||||
|
eventTypeStats[it.type] = 1 + (eventTypeStats[it.type] ?: 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,66 +159,60 @@ class MainActivity : AppCompatActivity() {
|
|||||||
compareBy({ -1 * (eventTypeStats[it] ?: 0) }, { it.ordinal })
|
compareBy({ -1 * (eventTypeStats[it] ?: 0) }, { it.ordinal })
|
||||||
).filter { it != LunaEvent.Type.UNKNOWN }
|
).filter { it != LunaEvent.Type.UNKNOWN }
|
||||||
|
|
||||||
fun setupMenu(maxButtonCount: Int, sortedEventTypes: List<LunaEvent.Type>): Int {
|
|
||||||
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 = sortedEventTypes[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)
|
|
||||||
}
|
|
||||||
|
|
||||||
return showCounter
|
|
||||||
}
|
|
||||||
|
|
||||||
val usedEventCount = eventTypeStats.count { it.value > 0 }
|
val usedEventCount = eventTypeStats.count { it.value > 0 }
|
||||||
val maxButtonCount = if (dynamicMenu) { usedEventCount } else { 7 }
|
val maxButtonCount = if (dynamicMenu) { usedEventCount } else { 7 }
|
||||||
val eventsShown = setupMenu(maxButtonCount, eventTypesSorted)
|
|
||||||
|
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
|
// store left over events for popup menu
|
||||||
currentPopupItems = eventTypesSorted.subList(eventsShown, eventTypesSorted.size)
|
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) {
|
||||||
@@ -275,6 +268,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
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 = dateTimePicker(event.time, dateTV)
|
val pickedTime = dateTimePicker(event.time, dateTV)
|
||||||
|
|
||||||
@@ -313,6 +309,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
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 = dateTimePicker(event.time, dateTV)
|
val pickedTime = dateTimePicker(event.time, dateTV)
|
||||||
|
|
||||||
@@ -341,6 +340,53 @@ 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)
|
setToPreviousQuantity(event)
|
||||||
askTemperatureValue(event, true) { saveEvent(event) }
|
askTemperatureValue(event, true) { saveEvent(event) }
|
||||||
@@ -421,83 +467,110 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return dateTime
|
return dateTime
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addSleepEvent(event: LunaEvent) {
|
fun addDurationEvent(event: LunaEvent) {
|
||||||
askSleepValue(event, true) { saveEvent(event) }
|
askDurationEvent(event, true) { saveEvent(event) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun askSleepValue(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
fun askDurationEvent(event: LunaEvent, showTime: Boolean, onPositive: () -> Unit) {
|
||||||
val d = AlertDialog.Builder(this)
|
val d = AlertDialog.Builder(this)
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_duration, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_duration, null)
|
||||||
d.setTitle(event.getDialogTitle(this))
|
d.setTitle(event.getDialogTitle(this))
|
||||||
d.setView(dialogView)
|
d.setView(dialogView)
|
||||||
|
|
||||||
val durationTextView = dialogView.findViewById<TextView>(R.id.dialog_date_duration)
|
val durationTV = dialogView.findViewById<TextView>(R.id.dialog_date_duration)
|
||||||
val datePickerBegin = dialogView.findViewById<TextView>(R.id.dialog_date_picker_begin)
|
val datePickerBeginTV = dialogView.findViewById<TextView>(R.id.dialog_date_picker_begin)
|
||||||
val datePickerEnd = dialogView.findViewById<TextView>(R.id.dialog_date_picker_end)
|
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 = durationTextView.currentTextColor
|
val currentDurationTextColor = durationTV.currentTextColor
|
||||||
val invalidDurationTextColor = ContextCompat.getColor(this, R.color.danger)
|
val invalidDurationTextColor = ContextCompat.getColor(this, R.color.danger)
|
||||||
|
|
||||||
// in seconds
|
// in seconds
|
||||||
var sleepStart = event.time
|
var durationStart = event.getStartTime()
|
||||||
var sleepEnd = event.time + event.quantity
|
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 {
|
fun isValidTimeSpan(timeBeginUnix: Long, timeEndUnix: Long): Boolean {
|
||||||
val now = System.currentTimeMillis() / 1000
|
return (timeBeginUnix <= timeEndUnix) && (timeEndUnix - timeBeginUnix) < (24 * 60 * 60)
|
||||||
return (timeBeginUnix > 0)
|
|
||||||
&& (timeEndUnix > 0)
|
|
||||||
&& (timeBeginUnix <= timeEndUnix)
|
|
||||||
&& (timeBeginUnix <= now)
|
|
||||||
&& (timeEndUnix <= now)
|
|
||||||
&& (timeEndUnix - timeBeginUnix) < (24 * 60 * 60)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent printing of seconds
|
fun updateFields() {
|
||||||
fun adjustToMinute(unixTime: Long): Long {
|
datePickerBeginTV.text = DateUtils.formatDateTime(durationStart)
|
||||||
return unixTime - (unixTime % 60)
|
datePickerEndTV.text = DateUtils.formatDateTime(durationEnd)
|
||||||
}
|
|
||||||
|
|
||||||
fun updateDuration() {
|
dateTimePicker(durationStart, datePickerBeginTV) { pickedTime: Long ->
|
||||||
durationTextView.setTextColor(currentDurationTextColor)
|
durationStart = pickedTime
|
||||||
val duration = sleepEnd - sleepStart
|
if (datePickerEndTV.visibility == View.GONE) {
|
||||||
if (duration == 0L) {
|
durationEnd = pickedTime
|
||||||
// baby is sleeping
|
|
||||||
durationTextView.text = "💤"
|
|
||||||
} else {
|
|
||||||
durationTextView.text = DateUtils.formatTimeDuration(applicationContext, duration)
|
|
||||||
if (!isValidTimeSpan(sleepStart, sleepEnd)) {
|
|
||||||
durationTextView.setTextColor(invalidDurationTextColor)
|
|
||||||
}
|
}
|
||||||
|
updateFields()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val pickedDateTimeBegin = dateTimePicker(event.time, datePickerBegin) { time: Long ->
|
dateTimePicker(durationEnd, datePickerEndTV) { pickedTime: Long ->
|
||||||
sleepStart = adjustToMinute(time)
|
durationEnd = pickedTime
|
||||||
updateDuration()
|
updateFields()
|
||||||
}
|
}
|
||||||
|
|
||||||
val pickedDateTimeEnd = dateTimePicker(event.time + event.quantity, datePickerEnd) { time: Long ->
|
durationTV.setTextColor(currentDurationTextColor)
|
||||||
sleepEnd = adjustToMinute(time)
|
val duration = durationEnd - durationStart
|
||||||
updateDuration()
|
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
|
||||||
|
}
|
||||||
|
|
||||||
sleepStart = adjustToMinute(pickedDateTimeBegin.time.time / 1000)
|
val colorBegin = if (isValidTime(durationStart)) { currentDurationTextColor } else { invalidDurationTextColor }
|
||||||
sleepEnd = adjustToMinute(pickedDateTimeEnd.time.time / 1000)
|
datePickerBeginTV.setTextColor(colorBegin)
|
||||||
updateDuration()
|
|
||||||
|
val colorEnd = if (isValidTime(durationEnd)) { currentDurationTextColor } else { invalidDurationTextColor }
|
||||||
|
datePickerEndTV.setTextColor(colorEnd)
|
||||||
|
}
|
||||||
|
|
||||||
if (showTime) {
|
if (showTime) {
|
||||||
datePickerEnd.visibility = View.GONE
|
dateDelimiterTV.visibility = View.GONE
|
||||||
durationTextView.visibility = View.GONE
|
datePickerEndTV.visibility = View.GONE
|
||||||
|
durationTV.visibility = View.GONE
|
||||||
|
durationButtons.visibility = View.GONE
|
||||||
//d.setMessage("")
|
//d.setMessage("")
|
||||||
} else {
|
} else {
|
||||||
durationTextView.visibility = View.VISIBLE
|
dateDelimiterTV.visibility = View.VISIBLE
|
||||||
|
datePickerEndTV.visibility = View.VISIBLE
|
||||||
|
durationTV.visibility = View.VISIBLE
|
||||||
|
durationButtons.visibility = View.VISIBLE
|
||||||
d.setMessage(event.getDialogMessage(this))
|
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 ->
|
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||||
if (isValidTimeSpan(sleepStart, sleepEnd)) {
|
if (isValidTime(durationStart) && isValidTime(durationEnd) && isValidTimeSpan(durationStart, durationEnd)) {
|
||||||
event.time = sleepStart
|
event.time = durationStart
|
||||||
event.quantity = (sleepEnd - sleepStart).toInt()
|
event.quantity = (durationEnd - durationStart).toInt()
|
||||||
onPositive()
|
onPositive()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.toast_date_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.toast_date_error, Toast.LENGTH_SHORT).show()
|
||||||
@@ -618,9 +691,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
var nextEvent = getNextSameEvent(current, templates)
|
var nextEvent = getNextSameEvent(current, templates)
|
||||||
|
|
||||||
notesET.setText(current.notes)
|
notesET.setText(current.notes)
|
||||||
if (useQuantity) {
|
|
||||||
qtyET.setText(current.quantity.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextEvent == null && current != event) {
|
if (nextEvent == null && current != event) {
|
||||||
nextEvent = event
|
nextEvent = event
|
||||||
@@ -629,9 +699,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (nextEvent != null) {
|
if (nextEvent != null) {
|
||||||
nextTextView.setOnClickListener {
|
nextTextView.setOnClickListener {
|
||||||
notesET.setText(nextEvent.notes)
|
notesET.setText(nextEvent.notes)
|
||||||
if (useQuantity) {
|
|
||||||
qtyET.setText(nextEvent.quantity.toString())
|
|
||||||
}
|
|
||||||
updateContent(nextEvent)
|
updateContent(nextEvent)
|
||||||
}
|
}
|
||||||
nextTextView.alpha = 1.0f
|
nextTextView.alpha = 1.0f
|
||||||
@@ -643,9 +710,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (prevEvent != null) {
|
if (prevEvent != null) {
|
||||||
prevTextView.setOnClickListener {
|
prevTextView.setOnClickListener {
|
||||||
notesET.setText(prevEvent.notes)
|
notesET.setText(prevEvent.notes)
|
||||||
if (useQuantity) {
|
|
||||||
qtyET.setText(prevEvent.quantity.toString())
|
|
||||||
}
|
|
||||||
updateContent(prevEvent)
|
updateContent(prevEvent)
|
||||||
}
|
}
|
||||||
prevTextView.alpha = 1.0f
|
prevTextView.alpha = 1.0f
|
||||||
@@ -700,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
|
||||||
}
|
}
|
||||||
@@ -838,12 +902,15 @@ class MainActivity : AppCompatActivity() {
|
|||||||
when (event.type) {
|
when (event.type) {
|
||||||
LunaEvent.Type.BABY_BOTTLE -> askBabyBottleContent(event, false, updateValues)
|
LunaEvent.Type.BABY_BOTTLE -> askBabyBottleContent(event, false, updateValues)
|
||||||
LunaEvent.Type.WEIGHT -> askWeightValue(event, false, updateValues)
|
LunaEvent.Type.WEIGHT -> askWeightValue(event, false, updateValues)
|
||||||
|
LunaEvent.Type.HEIGHT -> askHeightValue(event, false, updateValues)
|
||||||
LunaEvent.Type.DIAPERCHANGE_POO,
|
LunaEvent.Type.DIAPERCHANGE_POO,
|
||||||
LunaEvent.Type.DIAPERCHANGE_PEE,
|
LunaEvent.Type.DIAPERCHANGE_PEE,
|
||||||
LunaEvent.Type.PUKE -> askAmountValue(event, false, updateValues)
|
LunaEvent.Type.PUKE -> askAmountValue(event, false, updateValues)
|
||||||
LunaEvent.Type.TEMPERATURE -> askTemperatureValue(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.NOTE -> askNotes(event, false, updateValues)
|
||||||
LunaEvent.Type.SLEEP -> askSleepValue(event, false, updateValues)
|
LunaEvent.Type.SLEEP -> askDurationEvent(event, false, updateValues)
|
||||||
else -> {
|
else -> {
|
||||||
Log.w(TAG, "Unexpected type: ${event.type}")
|
Log.w(TAG, "Unexpected type: ${event.type}")
|
||||||
}
|
}
|
||||||
@@ -933,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) }
|
||||||
)
|
)
|
||||||
@@ -946,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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1056,6 +1131,8 @@ 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.getHeaderEmoji(this@MainActivity)
|
val em = e.getHeaderEmoji(this@MainActivity)
|
||||||
@@ -1174,6 +1251,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
savingEvent(false)
|
savingEvent(false)
|
||||||
|
|
||||||
|
populateHeaderMenu()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1257,6 +1336,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
when (type) {
|
when (type) {
|
||||||
LunaEvent.Type.BABY_BOTTLE -> addBabyBottleEvent(event)
|
LunaEvent.Type.BABY_BOTTLE -> addBabyBottleEvent(event)
|
||||||
LunaEvent.Type.WEIGHT -> addWeightEvent(event)
|
LunaEvent.Type.WEIGHT -> addWeightEvent(event)
|
||||||
|
LunaEvent.Type.HEIGHT -> addHeightEvent(event)
|
||||||
LunaEvent.Type.BREASTFEEDING_LEFT_NIPPLE -> addPlainEvent(event)
|
LunaEvent.Type.BREASTFEEDING_LEFT_NIPPLE -> addPlainEvent(event)
|
||||||
LunaEvent.Type.BREASTFEEDING_BOTH_NIPPLE -> addPlainEvent(event)
|
LunaEvent.Type.BREASTFEEDING_BOTH_NIPPLE -> addPlainEvent(event)
|
||||||
LunaEvent.Type.BREASTFEEDING_RIGHT_NIPPLE -> addPlainEvent(event)
|
LunaEvent.Type.BREASTFEEDING_RIGHT_NIPPLE -> addPlainEvent(event)
|
||||||
@@ -1270,7 +1350,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
LunaEvent.Type.FOOD -> addNoteEvent(event)
|
LunaEvent.Type.FOOD -> addNoteEvent(event)
|
||||||
LunaEvent.Type.PUKE -> addAmountEvent(event)
|
LunaEvent.Type.PUKE -> addAmountEvent(event)
|
||||||
LunaEvent.Type.BATH -> addPlainEvent(event)
|
LunaEvent.Type.BATH -> addPlainEvent(event)
|
||||||
LunaEvent.Type.SLEEP -> addSleepEvent(event)
|
LunaEvent.Type.SLEEP -> addDurationEvent(event)
|
||||||
LunaEvent.Type.UNKNOWN -> {} // ignore
|
LunaEvent.Type.UNKNOWN -> {} // ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-3
@@ -63,7 +63,7 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
|
|||||||
|
|
||||||
// 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 ""
|
||||||
@@ -74,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
|
||||||
@@ -88,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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class LunaEvent: Comparable<LunaEvent> {
|
|||||||
DIAPERCHANGE_PEE,
|
DIAPERCHANGE_PEE,
|
||||||
SLEEP,
|
SLEEP,
|
||||||
WEIGHT,
|
WEIGHT,
|
||||||
|
HEIGHT,
|
||||||
MEDICINE,
|
MEDICINE,
|
||||||
ENEMA,
|
ENEMA,
|
||||||
NOTE,
|
NOTE,
|
||||||
@@ -145,6 +146,7 @@ class LunaEvent: Comparable<LunaEvent> {
|
|||||||
when (type) {
|
when (type) {
|
||||||
Type.BABY_BOTTLE -> R.string.event_bottle_type
|
Type.BABY_BOTTLE -> R.string.event_bottle_type
|
||||||
Type.WEIGHT -> R.string.event_weight_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_LEFT_NIPPLE -> R.string.event_breastfeeding_left_type
|
||||||
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type
|
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type
|
||||||
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type
|
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type
|
||||||
@@ -174,7 +176,8 @@ class LunaEvent: Comparable<LunaEvent> {
|
|||||||
Type.DIAPERCHANGE_PEE,
|
Type.DIAPERCHANGE_PEE,
|
||||||
Type.PUKE -> R.string.log_amount_dialog_description
|
Type.PUKE -> R.string.log_amount_dialog_description
|
||||||
Type.WEIGHT -> R.string.log_weight_dialog_description
|
Type.WEIGHT -> R.string.log_weight_dialog_description
|
||||||
Type.SLEEP -> R.string.log_sleep_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
|
else -> R.string.log_unknown_dialog_description
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -185,6 +188,7 @@ class LunaEvent: Comparable<LunaEvent> {
|
|||||||
when (type) {
|
when (type) {
|
||||||
Type.BABY_BOTTLE -> R.string.event_bottle_desc
|
Type.BABY_BOTTLE -> R.string.event_bottle_desc
|
||||||
Type.WEIGHT -> R.string.event_weight_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_LEFT_NIPPLE -> R.string.event_breastfeeding_left_desc
|
||||||
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc
|
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc
|
||||||
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc
|
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc
|
||||||
@@ -210,6 +214,7 @@ class LunaEvent: Comparable<LunaEvent> {
|
|||||||
when (type) {
|
when (type) {
|
||||||
Type.BABY_BOTTLE -> R.string.event_type_item_bottle
|
Type.BABY_BOTTLE -> R.string.event_type_item_bottle
|
||||||
Type.WEIGHT -> R.string.event_type_item_weight
|
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_LEFT_NIPPLE -> R.string.event_type_item_breastfeeding_left
|
||||||
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_type_item_breastfeeding_both
|
Type.BREASTFEEDING_BOTH_NIPPLE -> R.string.event_type_item_breastfeeding_both
|
||||||
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_type_item_breastfeeding_right
|
Type.BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_type_item_breastfeeding_right
|
||||||
|
|||||||
+11
@@ -15,6 +15,7 @@ class LocalSettingsRepository(val context: Context) {
|
|||||||
const val SHARED_PREFS_DAV_PASS = "webdav_password"
|
const val SHARED_PREFS_DAV_PASS = "webdav_password"
|
||||||
const val SHARED_PREFS_DYNAMIC_MENU = "dynamic_menu"
|
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
|
||||||
@@ -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()
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ 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 {
|
||||||
@@ -35,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
|
||||||
@@ -54,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
|
||||||
@@ -90,6 +95,7 @@ class NumericUtils (val context: Context) {
|
|||||||
when (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.HEIGHT -> measurement_unit_height_base
|
||||||
LunaEvent.Type.MEDICINE -> measurement_unit_weight_tiny
|
LunaEvent.Type.MEDICINE -> measurement_unit_weight_tiny
|
||||||
LunaEvent.Type.TEMPERATURE -> measurement_unit_temperature_base
|
LunaEvent.Type.TEMPERATURE -> measurement_unit_temperature_base
|
||||||
else -> ""
|
else -> ""
|
||||||
|
|||||||
@@ -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="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path
|
|
||||||
android:fillColor="#3DDC84"
|
|
||||||
android:pathData="M0,0h108v108h-108z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M9,0L9,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,0L19,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,0L29,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,0L39,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,0L49,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,0L59,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,0L69,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,0L79,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M89,0L89,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M99,0L99,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,9L108,9"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,19L108,19"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,29L108,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,39L108,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,49L108,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,59L108,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,69L108,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,79L108,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,89L108,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,99L108,99"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,29L89,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,39L89,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,49L89,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,59L89,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,69L89,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,79L89,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,19L29,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,19L39,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,19L49,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,19L59,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,19L69,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,19L79,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
</vector>
|
|
||||||
@@ -259,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"/>
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -7,26 +7,69 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dialog_date_picker_begin"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="10dp"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/dialog_date_duration"
|
android:id="@+id/dialog_date_duration"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="10dp"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:text="💤"/>
|
android:text="💤"/>
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/dialog_date_picker_end"
|
android:id="@+id/duration_buttons"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginTop="20dp"/>
|
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>
|
</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>
|
||||||
@@ -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,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<TextView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="5dip" />
|
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
<string name="event_note_desc">Notiz</string>
|
<string name="event_note_desc">Notiz</string>
|
||||||
<string name="event_temperature_desc">Temperatur</string>
|
<string name="event_temperature_desc">Temperatur</string>
|
||||||
<string name="event_colic_desc">Blähungskolik</string>
|
<string name="event_colic_desc">Blähungskolik</string>
|
||||||
|
<string name="event_puke_desc">Erbrechen</string>
|
||||||
|
<string name="event_bath_desc">Bad</string>
|
||||||
<string name="event_unknown_desc"></string>
|
<string name="event_unknown_desc"></string>
|
||||||
|
|
||||||
<string name="toast_event_added">Ereignis gespeichert</string>
|
<string name="toast_event_added">Ereignis gespeichert</string>
|
||||||
@@ -35,6 +37,8 @@
|
|||||||
<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_signature">Signatur</string>
|
||||||
|
<string name="settings_signature_desc">Fügen Sie jedem von Ihnen erstellten Ereignis eine Signatur hinzu, die für andere sichtbar ist. Dies ist nützlich, wenn mehrere Personen Ereignisse hinzufügen.</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>
|
||||||
@@ -48,7 +52,6 @@
|
|||||||
<string name="settings_webdav_error_denied">Falscher WebDAV-Benutzer oder falsches Passwort</string>
|
<string name="settings_webdav_error_denied">Falscher WebDAV-Benutzer oder falsches Passwort</string>
|
||||||
<string name="settings_webdav_error_server_offline">WebDAV-Server ist derzeit nicht verfügbar</string>
|
<string name="settings_webdav_error_server_offline">WebDAV-Server ist derzeit nicht verfügbar</string>
|
||||||
<string name="settings_webdav_error_generic">Fehler beim Zugriff auf WebDAV:</string>
|
<string name="settings_webdav_error_generic">Fehler beim Zugriff auf WebDAV:</string>
|
||||||
<string name="settings_webdav_creation_error_generic">Eine Datei konnte auf dem WebDAV-Server nicht gespeichert werden:</string>
|
|
||||||
<string name="settings_webdav_creation_ok">Erfolgreich mit dem WebDAV-Server verbunden</string>
|
<string name="settings_webdav_creation_ok">Erfolgreich mit dem WebDAV-Server verbunden</string>
|
||||||
<string name="settings_json_error">Es befindet sich eine Speicherdatei auf dem Server, aber sie ist beschädigt oder unlesbar. Bitte lösche die Datei.</string>
|
<string name="settings_json_error">Es befindet sich eine Speicherdatei auf dem Server, aber sie ist beschädigt oder unlesbar. Bitte lösche die Datei.</string>
|
||||||
<string name="settings_generic_error">Fehler: </string>
|
<string name="settings_generic_error">Fehler: </string>
|
||||||
@@ -62,7 +65,6 @@
|
|||||||
|
|
||||||
<string name="log_bottle_dialog_description">Trinkmenge eingeben</string>
|
<string name="log_bottle_dialog_description">Trinkmenge eingeben</string>
|
||||||
<string name="log_medicine_dialog_description">Medikamentenname, Menge, Art, Notizen, …:</string>
|
<string name="log_medicine_dialog_description">Medikamentenname, Menge, Art, Notizen, …:</string>
|
||||||
<string name="log_notes_dialog_description">Notizen:</string>
|
|
||||||
<string name="log_notes_dialog_note_hint">Notiz eingeben</string>
|
<string name="log_notes_dialog_note_hint">Notiz eingeben</string>
|
||||||
<string name="log_notes_dialog_qty_hint">Menge (optional)</string>
|
<string name="log_notes_dialog_qty_hint">Menge (optional)</string>
|
||||||
<string name="log_temperature_dialog_description">Temperatur eingeben</string>
|
<string name="log_temperature_dialog_description">Temperatur eingeben</string>
|
||||||
@@ -71,6 +73,9 @@
|
|||||||
<string name="dialog_event_detail_title">Ereignisdetails</string>
|
<string name="dialog_event_detail_title">Ereignisdetails</string>
|
||||||
<string name="dialog_event_detail_close_button">OK</string>
|
<string name="dialog_event_detail_close_button">OK</string>
|
||||||
<string name="dialog_event_detail_delete_button">Löschen</string>
|
<string name="dialog_event_detail_delete_button">Löschen</string>
|
||||||
|
<string name="dialog_event_detail_quantity">Menge</string>
|
||||||
|
<string name="dialog_event_detail_notes">Notiz</string>
|
||||||
|
<string name="dialog_event_detail_signature">von %s</string>
|
||||||
|
|
||||||
<string name="dialog_add_logbook_title">Logbuch hinzufügen</string>
|
<string name="dialog_add_logbook_title">Logbuch hinzufügen</string>
|
||||||
<string name="dialog_add_logbook_logbookname">👶 Logbuchname</string>
|
<string name="dialog_add_logbook_logbookname">👶 Logbuchname</string>
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
<string name="settings_webdav_error_denied">Nom d\'utilisateur ou mot de passe incorrect pour le service WebDAV</string>
|
<string name="settings_webdav_error_denied">Nom d\'utilisateur ou mot de passe incorrect pour le service WebDAV</string>
|
||||||
<string name="settings_webdav_error_server_offline">Impossible d\'accéder au serveur WebDAV</string>
|
<string name="settings_webdav_error_server_offline">Impossible d\'accéder au serveur WebDAV</string>
|
||||||
<string name="settings_webdav_error_generic">Une erreur est survenue en essayant d\'accéder au serveur WebDAV:</string>
|
<string name="settings_webdav_error_generic">Une erreur est survenue en essayant d\'accéder au serveur WebDAV:</string>
|
||||||
<string name="settings_webdav_creation_error_generic">Impossible de sauvegarder un fichier sur le serveur WebDAV:</string>
|
|
||||||
<string name="settings_webdav_creation_ok">Connexion réussie avec le serveur WebDAV</string>
|
<string name="settings_webdav_creation_ok">Connexion réussie avec le serveur WebDAV</string>
|
||||||
<string name="settings_json_error">Il y a un fichier sur le serveur WebDAV, toutefois il est corronpu ou illisible. Merci de le supprimer et réessayer</string>
|
<string name="settings_json_error">Il y a un fichier sur le serveur WebDAV, toutefois il est corronpu ou illisible. Merci de le supprimer et réessayer</string>
|
||||||
<string name="settings_generic_error">Erreur: </string>
|
<string name="settings_generic_error">Erreur: </string>
|
||||||
@@ -62,7 +61,6 @@
|
|||||||
|
|
||||||
<string name="log_bottle_dialog_description">Renseignez la quantité contenue dans le biberon</string>
|
<string name="log_bottle_dialog_description">Renseignez la quantité contenue dans le biberon</string>
|
||||||
<string name="log_medicine_dialog_description">nom du médicament, quantité, type, notes …:</string>
|
<string name="log_medicine_dialog_description">nom du médicament, quantité, type, notes …:</string>
|
||||||
<string name="log_notes_dialog_description">Notes:</string>
|
|
||||||
<string name="log_notes_dialog_note_hint">Notes ...</string>
|
<string name="log_notes_dialog_note_hint">Notes ...</string>
|
||||||
<string name="log_notes_dialog_qty_hint">Quantité (ou vide)</string>
|
<string name="log_notes_dialog_qty_hint">Quantité (ou vide)</string>
|
||||||
<string name="log_temperature_dialog_description">Renseignez la Température</string>
|
<string name="log_temperature_dialog_description">Renseignez la Température</string>
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
<string name="settings_webdav_error_denied">Nome utente o password WebDAV sbagliati</string>
|
<string name="settings_webdav_error_denied">Nome utente o password WebDAV sbagliati</string>
|
||||||
<string name="settings_webdav_error_server_offline">Il server WebDAV non è al momento disponibile</string>
|
<string name="settings_webdav_error_server_offline">Il server WebDAV non è al momento disponibile</string>
|
||||||
<string name="settings_webdav_error_generic">Si è verificato un errore tentando di accedere al server WebDAV:</string>
|
<string name="settings_webdav_error_generic">Si è verificato un errore tentando di accedere al server WebDAV:</string>
|
||||||
<string name="settings_webdav_creation_error_generic">Impossibile creare un file di salvataggio sul server WebDAV:</string>
|
|
||||||
<string name="settings_webdav_creation_ok">Connessione al server WebDAV avvenuta con successo</string>
|
<string name="settings_webdav_creation_ok">Connessione al server WebDAV avvenuta con successo</string>
|
||||||
<string name="settings_json_error">Sul server esiste un salvataggio, ma è corrotto o illeggibile. Cancellare il file </string>
|
<string name="settings_json_error">Sul server esiste un salvataggio, ma è corrotto o illeggibile. Cancellare il file </string>
|
||||||
<string name="settings_generic_error">Si è verificato un errore: </string>
|
<string name="settings_generic_error">Si è verificato un errore: </string>
|
||||||
@@ -62,7 +61,6 @@
|
|||||||
|
|
||||||
<string name="log_bottle_dialog_description">Inserisci la quantità contenuta nel biberon</string>
|
<string name="log_bottle_dialog_description">Inserisci la quantità contenuta nel biberon</string>
|
||||||
<string name="log_medicine_dialog_description">Nome della medicina, quantità, formato, note…:</string>
|
<string name="log_medicine_dialog_description">Nome della medicina, quantità, formato, note…:</string>
|
||||||
<string name="log_notes_dialog_description">Note:</string>
|
|
||||||
<string name="log_notes_dialog_note_hint">Inserisci le note</string>
|
<string name="log_notes_dialog_note_hint">Inserisci le note</string>
|
||||||
<string name="log_notes_dialog_qty_hint">Quantità, o vuoto</string>
|
<string name="log_notes_dialog_qty_hint">Quantità, o vuoto</string>
|
||||||
<string name="log_temperature_dialog_description">Inserisci la temperatura</string>
|
<string name="log_temperature_dialog_description">Inserisci la temperatura</string>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="accent">#FFE68F</color>
|
<color name="accent">#FFE68F</color>
|
||||||
<color name="black">#FF000000</color>
|
|
||||||
<color name="white">#FFFFFFFF</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
<color name="translucent">#c000</color>
|
<color name="translucent">#c000</color>
|
||||||
<color name="transparent">#0000</color>
|
<color name="transparent">#0000</color>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<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_height_type" translatable="false">📏</string>
|
||||||
<string name="event_breastfeeding_left_type" translatable="false">🤱⬅️</string>
|
<string name="event_breastfeeding_left_type" translatable="false">🤱⬅️</string>
|
||||||
<string name="event_breastfeeding_both_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_breastfeeding_right_type" translatable="false">🤱➡️️</string>
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
<string name="event_type_item_bottle">🍼 Bottle</string>
|
<string name="event_type_item_bottle">🍼 Bottle</string>
|
||||||
<string name="event_type_item_food">🥣 Food</string>
|
<string name="event_type_item_food">🥣 Food</string>
|
||||||
<string name="event_type_item_weight">⚖️ Weight</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_left">🤱⬅️ Nursing</string>
|
||||||
<string name="event_type_item_breastfeeding_both">🤱↔️ 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_breastfeeding_right">🤱➡️️ Nursing</string>
|
||||||
@@ -45,6 +47,7 @@
|
|||||||
<string name="event_bottle_desc">Milk Bottle</string>
|
<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_height_desc">Height</string>
|
||||||
<string name="event_breastfeeding_left_desc">Nursing (left)</string>
|
<string name="event_breastfeeding_left_desc">Nursing (left)</string>
|
||||||
<string name="event_breastfeeding_both_desc">Nursing (both)</string>
|
<string name="event_breastfeeding_both_desc">Nursing (both)</string>
|
||||||
<string name="event_breastfeeding_right_desc">Nursing (right)</string>
|
<string name="event_breastfeeding_right_desc">Nursing (right)</string>
|
||||||
@@ -106,7 +109,6 @@
|
|||||||
<string name="settings_webdav_error_denied">Wrong WebDAV user or password</string>
|
<string name="settings_webdav_error_denied">Wrong WebDAV user or password</string>
|
||||||
<string name="settings_webdav_error_server_offline">WebDAV server is currently unavailable</string>
|
<string name="settings_webdav_error_server_offline">WebDAV server is currently unavailable</string>
|
||||||
<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_ok">Successfully connected with the WebDAV server</string>
|
<string name="settings_webdav_creation_ok">Successfully connected with the WebDAV server</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>
|
||||||
@@ -121,20 +123,22 @@
|
|||||||
<string name="log_amount_dialog_description">Select the amount:</string>
|
<string name="log_amount_dialog_description">Select the amount:</string>
|
||||||
<string name="log_bottle_dialog_description">Insert the quantity contained in the baby bottle:</string>
|
<string name="log_bottle_dialog_description">Insert the quantity contained in the baby bottle:</string>
|
||||||
<string name="log_medicine_dialog_description">Medicine name, quantity, type, notes…:</string>
|
<string name="log_medicine_dialog_description">Medicine name, quantity, type, notes…:</string>
|
||||||
<string name="log_notes_dialog_description">Notes:</string>
|
|
||||||
<string name="log_notes_dialog_note_hint">Write some notes</string>
|
<string name="log_notes_dialog_note_hint">Write some notes</string>
|
||||||
<string name="log_notes_dialog_qty_hint">Quantity (or empty)</string>
|
<string name="log_notes_dialog_qty_hint">Quantity (or empty)</string>
|
||||||
<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_sleep_dialog_description">Set sleep duration:</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>
|
||||||
|
|
||||||
@@ -150,6 +154,9 @@
|
|||||||
<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_now">Now</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>
|
||||||
|
|||||||
+11
-1
@@ -20,4 +20,14 @@ kotlin.code.style=official
|
|||||||
# Enables namespacing of each library's R class so that its R class includes only the
|
# Enables namespacing of each library's R class so that its R class includes only the
|
||||||
# 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"
|
||||||
|
|||||||
+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
|
||||||
|
|||||||
Reference in New Issue
Block a user