9 Commits

Author SHA1 Message Date
7ec5e48b12 activity_setting: fine tune layout style 2025-09-29 03:34:49 +02:00
f2e0e26c11 add signature setting
For multiple users it helps to
keep track about who did what.
2025-09-29 03:34:08 +02:00
9e4b767450 DateUtils: move event details formatting to DateUtils
Also display second as 0 since it is easier
to read and does not have meaning for the user.
2025-09-29 03:34:08 +02:00
19c93e8aa9 add bath event type 2025-09-29 03:34:08 +02:00
16ffe671b9 add no-breastfeeding help text 2025-09-29 03:34:08 +02:00
471aac0ce2 more_events_popup: move enema to bottom and adjust padding
Enemas are usually are rare thing. Let's
move it to the bottom. Also adjust padding
to have more space to display all items.
2025-09-29 03:34:08 +02:00
14a3322ebc add puke event 2025-09-29 03:34:08 +02:00
34aa092722 NumericUtils: provide fallback for LocaleData.getMeasurementSystem
LocaleData.getMeasurementSystem is available at API level 28
but the app supports API level 21.
2025-09-29 03:34:08 +02:00
961e7b90e7 small code cleanup
No code behavior has been changed.
2025-09-29 03:33:30 +02:00
10 changed files with 184 additions and 60 deletions

View File

@@ -13,6 +13,7 @@ import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.NumberPicker
import android.widget.PopupWindow
import android.widget.Spinner
@@ -41,15 +42,14 @@ import okio.IOException
import org.json.JSONException
import utils.DateUtils
import utils.NumericUtils
import java.text.DateFormat
import java.util.Calendar
import java.util.Date
class MainActivity : AppCompatActivity() {
companion object {
val TAG = "MainActivity"
val UPDATE_EVERY_SECS: Long = 30
val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false
const val TAG = "MainActivity"
const val UPDATE_EVERY_SECS: Long = 30
const val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false
}
var logbook: Logbook? = null
@@ -58,6 +58,7 @@ class MainActivity : AppCompatActivity() {
lateinit var buttonsContainer: ViewGroup
lateinit var recyclerView: RecyclerView
lateinit var handler: Handler
var signature = ""
var savingEvent = false
val updateListRunnable: Runnable = Runnable {
if (logbook != null && !pauseLogbookUpdate)
@@ -113,24 +114,24 @@ class MainActivity : AppCompatActivity() {
moreButton.setOnClickListener {
showOverflowPopupWindow(moreButton)
}
findViewById<View>(R.id.button_no_connection_settings).setOnClickListener({
findViewById<View>(R.id.button_no_connection_settings).setOnClickListener {
showSettings()
})
findViewById<View>(R.id.button_settings).setOnClickListener({
}
findViewById<View>(R.id.button_settings).setOnClickListener {
showSettings()
})
findViewById<View>(R.id.button_no_connection_retry).setOnClickListener({
}
findViewById<View>(R.id.button_no_connection_retry).setOnClickListener {
// This may happen at start, when logbook is still null: better ask the logbook list
loadLogbookList()
})
findViewById<View>(R.id.button_sync).setOnClickListener({
}
findViewById<View>(R.id.button_sync).setOnClickListener {
loadLogbookList()
})
}
}
private fun setListAdapter(items: ArrayList<LunaEvent>) {
val adapter = LunaEventRecyclerAdapter(this, items)
adapter.onItemClickListener = object: LunaEventRecyclerAdapter.OnItemClickListener{
adapter.onItemClickListener = object: LunaEventRecyclerAdapter.OnItemClickListener {
override fun onItemClick(event: LunaEvent) {
showEventDetailDialog(event, items)
}
@@ -169,6 +170,8 @@ class MainActivity : AppCompatActivity() {
logbookRepo = FileLogbookRepository()
}
signature = settingsRepository.loadSignature()
val noBreastfeeding = settingsRepository.loadNoBreastfeeding()
findViewById<View>(R.id.layout_nipples).visibility = when (noBreastfeeding) {
true -> View.GONE
@@ -208,7 +211,7 @@ class MainActivity : AppCompatActivity() {
numberPicker.wrapSelectorWheel = false
numberPicker.value = localSettings.loadBabyBottleContent()
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
logEvent(LunaEvent(LunaEvent.TYPE_BABY_BOTTLE, numberPicker.value * 10))
logEvent(LunaEvent(LunaEvent.TYPE_BABY_BOTTLE, signature, numberPicker.value * 10))
localSettings.saveBabyBottleContent(numberPicker.value)
}
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
@@ -227,7 +230,7 @@ class MainActivity : AppCompatActivity() {
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
val weight = weightET.text.toString().toIntOrNull()
if (weight != null)
logEvent(LunaEvent(LunaEvent.TYPE_WEIGHT, weight))
logEvent(LunaEvent(LunaEvent.TYPE_WEIGHT, signature, weight))
else
Toast.makeText(this, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
}
@@ -253,7 +256,7 @@ class MainActivity : AppCompatActivity() {
tempSlider.addOnChangeListener({s, v, b -> tempTextView.text = v.toString()})
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
val temperature = (tempSlider.value * 10).toInt() // In tenth of a grade
logEvent(LunaEvent(LunaEvent.TYPE_TEMPERATURE, temperature))
logEvent(LunaEvent(LunaEvent.TYPE_TEMPERATURE, signature, temperature))
}
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
val alertDialog = d.create()
@@ -273,7 +276,7 @@ class MainActivity : AppCompatActivity() {
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
val pos = spinner.selectedItemPosition
logEvent(LunaEvent(LunaEvent.TYPE_PUKE, pos))
logEvent(LunaEvent(LunaEvent.TYPE_PUKE, signature, pos))
}
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
val alertDialog = d.create()
@@ -360,7 +363,6 @@ class MainActivity : AppCompatActivity() {
fun showEventDetailDialog(event: LunaEvent, items: ArrayList<LunaEvent>) {
// Do not update list while the detail is shown, to avoid changing the object below while it is changed by the user
pauseLogbookUpdate = true
val dateFormat = DateFormat.getDateTimeInstance()
val d = AlertDialog.Builder(this)
d.setTitle(R.string.dialog_event_detail_title)
val dialogView = layoutInflater.inflate(R.layout.dialog_event_detail, null)
@@ -372,8 +374,9 @@ class MainActivity : AppCompatActivity() {
val currentDateTime = Calendar.getInstance()
currentDateTime.time = Date(event.time * 1000)
val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date)
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), dateFormat.format(currentDateTime.time))
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
dateTextView.setOnClickListener {
// Show datetime picker
val startYear = currentDateTime.get(Calendar.YEAR)
@@ -386,11 +389,9 @@ class MainActivity : AppCompatActivity() {
TimePickerDialog(this, { _, hour, minute ->
val pickedDateTime = Calendar.getInstance()
pickedDateTime.set(year, month, day, hour, minute)
currentDateTime.time = pickedDateTime.time
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), dateFormat.format(currentDateTime.time))
// Save event and move it to the right position in the logbook
event.time = currentDateTime.time.time / 1000 // Seconds since epoch
event.time = pickedDateTime.time.time / 1000 // Seconds since epoch
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
logbook?.sort()
recyclerView.adapter?.notifyDataSetChanged()
saveLogbook()
@@ -409,6 +410,14 @@ class MainActivity : AppCompatActivity() {
pauseLogbookUpdate = false
})
// show optional signature
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_signature).text = event.signature
dialogView.findViewById<LinearLayout>(R.id.dialog_event_signature_layout).visibility = if (event.signature.isNotEmpty()) {
View.VISIBLE
} else {
View.GONE
}
// create next/previous links to events of the same type
val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous)
@@ -821,6 +830,12 @@ class MainActivity : AppCompatActivity() {
askWeightValue()
dismiss()
})
contentView.findViewById<View>(R.id.button_bath).setOnClickListener({
logEvent(
LunaEvent(LunaEvent.TYPE_BATH)
)
dismiss()
})
}.also { popupWindow ->
popupWindow.setOnDismissListener({
Handler(mainLooper).postDelayed({

View File

@@ -2,6 +2,7 @@ package it.danieleverducci.lunatracker
import android.os.Bundle
import android.view.View
import android.widget.EditText
import android.widget.RadioButton
import android.widget.TextView
import android.widget.Toast
@@ -24,6 +25,7 @@ open class SettingsActivity : AppCompatActivity() {
protected lateinit var textViewWebDAVPass: TextView
protected lateinit var progressIndicator: LinearProgressIndicator
protected lateinit var switchNoBreastfeeding: SwitchMaterial
protected lateinit var textViewSignature: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -36,6 +38,7 @@ open class SettingsActivity : AppCompatActivity() {
textViewWebDAVPass = findViewById(R.id.settings_data_webdav_pass)
progressIndicator = findViewById(R.id.progress_indicator)
switchNoBreastfeeding = findViewById(R.id.switch_no_breastfeeding)
textViewSignature = findViewById(R.id.settings_signature)
findViewById<View>(R.id.settings_save).setOnClickListener({
validateAndSave()
@@ -52,18 +55,20 @@ open class SettingsActivity : AppCompatActivity() {
val dataRepo = settingsRepository.loadDataRepository()
val webDavCredentials = settingsRepository.loadWebdavCredentials()
val noBreastfeeding = settingsRepository.loadNoBreastfeeding()
val signature = settingsRepository.loadSignature()
when (dataRepo) {
LocalSettingsRepository.DATA_REPO.LOCAL_FILE -> radioDataLocal.isChecked = true
LocalSettingsRepository.DATA_REPO.WEBDAV -> radioDataWebDAV.isChecked = true
}
textViewSignature.setText(signature)
switchNoBreastfeeding.isChecked = noBreastfeeding
if (webDavCredentials != null) {
textViewWebDAVUrl.setText(webDavCredentials[0])
textViewWebDAVUser.setText(webDavCredentials[1])
textViewWebDAVPass.setText(webDavCredentials[2])
textViewWebDAVUrl.text = webDavCredentials[0]
textViewWebDAVUser.text = webDavCredentials[1]
textViewWebDAVPass.text = webDavCredentials[2]
}
}
@@ -156,6 +161,7 @@ open class SettingsActivity : AppCompatActivity() {
else LocalSettingsRepository.DATA_REPO.LOCAL_FILE
)
settingsRepository.saveNoBreastfeeding(switchNoBreastfeeding.isChecked)
settingsRepository.saveSignature(textViewSignature.text.toString())
settingsRepository.saveWebdavCredentials(
textViewWebDAVUrl.text.toString(),
textViewWebDAVUser.text.toString(),
@@ -170,7 +176,7 @@ open class SettingsActivity : AppCompatActivity() {
*/
private fun copyLocalLogbooksToWebdav(webDAVLogbookRepository: WebDAVLogbookRepository, listener: OnCopyLocalLogbooksToWebdavFinishedListener) {
Thread(Runnable {
var errors = StringBuilder()
val errors = StringBuilder()
val fileLogbookRepo = FileLogbookRepository()
val logbooks = fileLogbookRepo.getAllLogbooks(this)
for (logbook in logbooks) {

View File

@@ -53,7 +53,7 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
holder.quantity.setTextColor(ContextCompat.getColor(context, R.color.textColor))
// Contents
holder.type.text = item.getTypeEmoji(context)
holder.description.text = when(item.type) {
holder.description.text = when (item.type) {
LunaEvent.TYPE_MEDICINE -> item.notes
LunaEvent.TYPE_NOTE -> item.notes
LunaEvent.TYPE_CUSTOM -> item.notes

View File

@@ -29,6 +29,7 @@ class LunaEvent: Comparable<LunaEvent> {
const val TYPE_TEMPERATURE = "TEMPERATURE"
const val TYPE_FOOD = "FOOD"
const val TYPE_PUKE = "PUKE"
const val TYPE_BATH = "BATH"
}
private val jo: JSONObject
@@ -54,6 +55,12 @@ class LunaEvent: Comparable<LunaEvent> {
set(value) {
jo.put("notes", value)
}
var signature: String
get(): String = jo.optString("signature")
set(value) {
if (value.isNotEmpty())
jo.put("signature", value)
}
constructor(jo: JSONObject) {
this.jo = jo
@@ -68,10 +75,11 @@ class LunaEvent: Comparable<LunaEvent> {
this.type = type
}
constructor(type: String, quantity: Int) {
constructor(type: String, signature: String, quantity: Int) {
this.jo = JSONObject()
this.time = System.currentTimeMillis() / 1000
this.type = type
this.signature = signature
this.quantity = quantity
}
@@ -92,6 +100,7 @@ class LunaEvent: Comparable<LunaEvent> {
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
}
)
@@ -114,6 +123,7 @@ class LunaEvent: Comparable<LunaEvent> {
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
}
)
@@ -131,7 +141,7 @@ class LunaEvent: Comparable<LunaEvent> {
}
override fun toString(): String {
return "${type} qty: $quantity time: ${Date(time * 1000)}"
return "$type qty: $quantity time: ${Date(time * 1000)}"
}
override fun compareTo(other: LunaEvent): Int {

View File

@@ -7,13 +7,14 @@ import androidx.core.content.edit
class LocalSettingsRepository(val context: Context) {
companion object {
val SHARED_PREFS_FILE_NAME = "lunasettings"
val SHARED_PREFS_BB_CONTENT = "bbcontent"
val SHARED_PREFS_DATA_REPO = "data_repo"
val SHARED_PREFS_DAV_URL = "webdav_url"
val SHARED_PREFS_DAV_USER = "webdav_user"
val SHARED_PREFS_DAV_PASS = "webdav_password"
val SHARED_PREFS_NO_BREASTFEEDING = "no_breastfeeding"
const val SHARED_PREFS_FILE_NAME = "lunasettings"
const val SHARED_PREFS_BB_CONTENT = "bbcontent"
const val SHARED_PREFS_DATA_REPO = "data_repo"
const val SHARED_PREFS_DAV_URL = "webdav_url"
const val SHARED_PREFS_DAV_USER = "webdav_user"
const val SHARED_PREFS_DAV_PASS = "webdav_password"
const val SHARED_PREFS_NO_BREASTFEEDING = "no_breastfeeding"
const val SHARED_PREFS_SIGNATURE = "signature"
}
enum class DATA_REPO {LOCAL_FILE, WEBDAV}
val sharedPreferences: SharedPreferences
@@ -23,15 +24,23 @@ class LocalSettingsRepository(val context: Context) {
}
fun saveBabyBottleContent(content: Int) {
sharedPreferences.edit().putInt(SHARED_PREFS_BB_CONTENT, content).apply()
sharedPreferences.edit { putInt(SHARED_PREFS_BB_CONTENT, content) }
}
fun loadBabyBottleContent(): Int {
return sharedPreferences.getInt(SHARED_PREFS_BB_CONTENT, 1)
}
fun saveSignature(content: String) {
sharedPreferences.edit { putString(SHARED_PREFS_SIGNATURE, content) }
}
fun loadSignature(): String {
return sharedPreferences.getString(SHARED_PREFS_SIGNATURE, "") ?: ""
}
fun saveNoBreastfeeding(content: Boolean) {
sharedPreferences.edit().putBoolean(SHARED_PREFS_NO_BREASTFEEDING, content).apply()
sharedPreferences.edit { putBoolean(SHARED_PREFS_NO_BREASTFEEDING, content) }
}
fun loadNoBreastfeeding(): Boolean {
@@ -39,15 +48,15 @@ class LocalSettingsRepository(val context: Context) {
}
fun saveDataRepository(repo: DATA_REPO) {
val spe = sharedPreferences.edit()
spe.putString(
SHARED_PREFS_DATA_REPO,
when (repo) {
DATA_REPO.WEBDAV -> "webdav"
DATA_REPO.LOCAL_FILE -> "localfile"
}
)
spe.commit()
sharedPreferences.edit(commit = true) {
putString(
SHARED_PREFS_DATA_REPO,
when (repo) {
DATA_REPO.WEBDAV -> "webdav"
DATA_REPO.LOCAL_FILE -> "localfile"
}
)
}
}
fun loadDataRepository(): DATA_REPO {
@@ -60,11 +69,11 @@ class LocalSettingsRepository(val context: Context) {
}
fun saveWebdavCredentials(url: String, username: String, password: String) {
val spe = sharedPreferences.edit()
spe.putString(SHARED_PREFS_DAV_URL, url)
spe.putString(SHARED_PREFS_DAV_USER, username)
spe.putString(SHARED_PREFS_DAV_PASS, password)
spe.commit()
sharedPreferences.edit(commit = true) {
putString(SHARED_PREFS_DAV_URL, url)
putString(SHARED_PREFS_DAV_USER, username)
putString(SHARED_PREFS_DAV_PASS, password)
}
}
fun loadWebdavCredentials(): Array<String>? {

View File

@@ -5,8 +5,13 @@ import android.text.format.DateFormat
import it.danieleverducci.lunatracker.R
import java.util.Date
class DateUtils {
companion object {
/**
* Format time duration in seconds as e.g. "2 hours, 1 min".
* Used for the duration to the next/previous event in the event details dialog.
*/
fun formatTimeDuration(context: Context, secondsDiff: Long): String {
var seconds = secondsDiff
@@ -65,7 +70,8 @@ class DateUtils {
}
/**
* Formats the provided unix timestamp in a string like "3 hours, 26 minutes ago)
* Formats the provided unix timestamp in a string like "3 hours, 26 minutes ago".
* Used for the event list.
*/
fun formatTimeAgo(context: Context, unixTime: Long): String {
val secondsDiff = (System.currentTimeMillis() / 1000) - unixTime
@@ -100,5 +106,17 @@ class DateUtils {
}
return formattedTime.toString()
}
/**
* Format time as localized string without seconds. E.g. "28 Sept 03:36:00".
* The seconds are set to 0 since they are distracting and not relevant.
* Used in the event detail dialog.
*/
fun formatDateTime(unixTime: Long): String {
val roundedUnixTime = unixTime - (unixTime % 60)
val date = Date(roundedUnixTime * 1000)
val dateFormat = java.text.DateFormat.getDateTimeInstance()
return dateFormat.format(date)
}
}
}

View File

@@ -119,28 +119,57 @@
android:visibility="invisible"/>
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/settings_signature" />
<EditText
android:id="@+id/settings_signature"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:inputType="textEmailAddress"
android:background="@drawable/textview_background"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="5dp"
android:text="@string/settings_signature_desc"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="5dp"
android:layout_marginEnd="30dp">
android:layout_marginTop="20dp">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/no_breastfeeding" />
android:text="@string/settings_no_breastfeeding" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_no_breastfeeding"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_weight="1" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="5dp"
android:text="@string/settings_no_breastfeeding_desc"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -89,4 +89,25 @@
</LinearLayout>
<LinearLayout
android:id="@+id/dialog_event_signature_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:text="@string/dialog_event_detail_signature"/>
<TextView
android:id="@+id/dialog_event_detail_type_signature"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="" />
</LinearLayout>
</LinearLayout>

View File

@@ -69,6 +69,16 @@
style="@style/OverflowMenuText"
android:text="@string/overflow_event_scale"/>
<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"

View File

@@ -29,6 +29,7 @@
<string name="event_temperature_type" translatable="false">🌡️</string>
<string name="event_colic_type" translatable="false">💨</string>
<string name="event_puke_type" translatable="false">🤮</string>
<string name="event_bath_type" translatable="false">🛁</string>
<string name="event_unknown_type" translatable="false">\?</string>
<string name="event_bottle_desc">Baby bottle</string>
@@ -45,6 +46,7 @@
<string name="event_temperature_desc">Temperature</string>
<string name="event_colic_desc">Gaseous colic</string>
<string name="event_puke_desc">Puke</string>
<string name="event_bath_desc">Bath</string>
<string name="event_unknown_desc"></string>
<string name="overflow_event_scale">⚖️ Weight</string>
@@ -54,6 +56,7 @@
<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_logbook_saved">Logbook saved</string>
@@ -81,9 +84,9 @@
<string name="no_connection_go_to_settings">Settings</string>
<string name="no_connection_retry">Retry</string>
<string name="no_breastfeeding">No Breastfeeding</string>
<string name="settings_title">Settings</string>
<string name="settings_signature">Signature</string>
<string name="settings_signature_desc">Attach a signature to each event your create and for others to see. Useful if multiple people add events.</string>
<string name="settings_storage">Choose where to save data</string>
<string name="settings_storage_local">On device</string>
<string name="settings_storage_local_desc">Most privacy-friendly solution: data doesn\'t leave your device</string>
@@ -99,6 +102,8 @@
<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_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_generic_error">Error: </string>
<string name="settings_webdav_upload_error">Error while uploading local logbook %1$s to webdav: %2$s</string>
@@ -133,6 +138,7 @@
<string name="dialog_event_detail_delete_button">Delete</string>
<string name="dialog_event_detail_quantity">Quantity</string>
<string name="dialog_event_detail_notes">Notes</string>
<string name="dialog_event_detail_signature">Created By</string>
<string name="dialog_add_logbook_title">Add logbook</string>
<string name="dialog_add_logbook_logbookname">👶 Logbook name</string>