6 Commits

Author SHA1 Message Date
37b68450da List spacing 2024-11-24 09:37:17 +01:00
841da9e28e Added type Note 2024-11-24 09:32:05 +01:00
876c68ce81 Measurement units 2024-11-24 09:04:19 +01:00
35a3b42a32 Avoid frequent reloads 2024-11-24 08:31:30 +01:00
d5cb30cdd7 Added Medicine and Enema types, overflow menu 2024-11-24 08:26:39 +01:00
57f997e6f1 Screenshot in readme 2024-11-23 08:30:49 +01:00
13 changed files with 322 additions and 51 deletions

View File

@ -8,3 +8,5 @@ You have to react fast, event if it's 4 AM and you have no idea why is crying.
This app is meant to log all the relevant events (diaper change, breastfeeding, baby bottle feeding...), so you can always remember when has been done last time. It supports syncing the data between different devices (using your WebDAV server for the best privacy) so that when the baby needs attentions, the dad can step in leaving the mom sleeping peacefully.
Dedicated to my daughter Luna.
![Screenshot](fastlane/metadata/android/en-US/images/phoneScreenshots/1.png)

View File

@ -4,9 +4,12 @@ import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.NumberPicker
import android.widget.PopupWindow
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
@ -31,6 +34,7 @@ import org.json.JSONException
class MainActivity : AppCompatActivity() {
companion object {
val TAG = "MainActivity"
val UPDATE_EVERY_SECS: Long = 30
}
lateinit var logbook: Logbook
@ -89,6 +93,10 @@ class MainActivity : AppCompatActivity() {
LunaEvent.TYPE_DIAPERCHANGE_PEE
)
) }
val moreButton = findViewById<View>(R.id.button_more)
moreButton.setOnClickListener {
showOverflowPopupWindow(moreButton)
}
findViewById<View>(R.id.button_no_connection_settings).setOnClickListener({
showSettings()
})
@ -138,7 +146,6 @@ class MainActivity : AppCompatActivity() {
// Reload data
loadLogbook()
handler.postDelayed(updateListRunnable, 1000*30)
}
override fun onStop() {
@ -177,7 +184,7 @@ class MainActivity : AppCompatActivity() {
d.setTitle(R.string.log_weight_dialog_title)
d.setMessage(R.string.log_weight_dialog_description)
d.setView(dialogView)
val weightET = dialogView.findViewById<TextView>(R.id.dialog_number_edittext)
val weightET = dialogView.findViewById<EditText>(R.id.dialog_number_edittext)
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
val weight = weightET.text.toString().toIntOrNull()
if (weight != null)
@ -190,6 +197,40 @@ class MainActivity : AppCompatActivity() {
alertDialog.show()
}
fun askNotes(lunaEvent: LunaEvent) {
val d = AlertDialog.Builder(this)
val dialogView = layoutInflater.inflate(R.layout.dialog_notes, null)
d.setTitle(lunaEvent.getTypeDescription(this))
d.setMessage(
when (lunaEvent.type){
LunaEvent.TYPE_MEDICINE -> R.string.log_medicine_dialog_description
else -> R.string.log_notes_dialog_description
}
)
d.setView(dialogView)
val notesET = dialogView.findViewById<EditText>(R.id.notes_edittext)
val qtyET = dialogView.findViewById<EditText>(R.id.notes_qty_edittext)
if (lunaEvent.type == LunaEvent.TYPE_NOTE || lunaEvent.type == LunaEvent.TYPE_CUSTOM)
qtyET.visibility = View.GONE
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
val qtyStr = qtyET.text.toString()
if (qtyStr.isNotEmpty()) {
val qty = qtyStr.toIntOrNull()
if (qty == null) {
Toast.makeText(this, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
return@setPositiveButton
}
lunaEvent.quantity = qty
}
val notes = notesET.text.toString()
lunaEvent.notes = notes
logEvent(lunaEvent)
}
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
val alertDialog = d.create()
alertDialog.show()
}
fun askToTrimLogbook() {
val d = AlertDialog.Builder(this)
d.setTitle(R.string.trim_logbook_dialog_title)
@ -214,6 +255,10 @@ class MainActivity : AppCompatActivity() {
if (savingEvent)
return
// Reset time counter
handler.removeCallbacks(updateListRunnable)
handler.postDelayed(updateListRunnable, UPDATE_EVERY_SECS*1000)
// Load data
setLoading(true)
logbookRepo?.loadLogbook(this, object: LogbookLoadedListener{
@ -384,4 +429,29 @@ class MainActivity : AppCompatActivity() {
}
}
private fun showOverflowPopupWindow(anchor: View) {
PopupWindow(anchor.context).apply {
isOutsideTouchable = true
val inflater = LayoutInflater.from(anchor.context)
contentView = inflater.inflate(R.layout.more_events_popup, null)
contentView.findViewById<View>(R.id.button_medicine).setOnClickListener({
askNotes(LunaEvent(LunaEvent.TYPE_MEDICINE))
dismiss()
})
contentView.findViewById<View>(R.id.button_enema).setOnClickListener({
logEvent(LunaEvent(LunaEvent.TYPE_ENEMA))
dismiss()
})
contentView.findViewById<View>(R.id.button_note).setOnClickListener({
askNotes(LunaEvent(LunaEvent.TYPE_NOTE))
dismiss()
})
contentView.findViewById<View>(R.id.button_custom).setOnClickListener({
Toast.makeText(anchor.context, "TODO: Implement custom events", Toast.LENGTH_SHORT).show()
dismiss()
})
}.also { popupWindow ->
popupWindow.showAsDropDown(anchor)
}
}
}

View File

@ -1,6 +1,8 @@
package it.danieleverducci.lunatracker.adapters
import android.content.Context
import android.icu.util.LocaleData
import android.icu.util.ULocale
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
@ -10,13 +12,36 @@ import androidx.recyclerview.widget.RecyclerView
import it.danieleverducci.lunatracker.entities.LunaEvent
import it.danieleverducci.lunatracker.R
import java.util.Date
import java.util.Locale
class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.LunaEventVH> {
private val context: Context
val items = ArrayList<LunaEvent>()
val measurement_unit_liquid_base: String
val measurement_unit_weight_base: String
val measurement_unit_weight_tiny: String
constructor(context: Context) {
this.context = context
val measurementSystem = LocaleData.getMeasurementSystem(ULocale.getDefault())
this.measurement_unit_liquid_base = context.getString(
if (measurementSystem == LocaleData. MeasurementSystem.SI)
R.string.measurement_unit_liquid_base_metric
else
R.string.measurement_unit_liquid_base_imperial
)
this.measurement_unit_weight_base = context.getString(
if (measurementSystem == LocaleData. MeasurementSystem.SI)
R.string.measurement_unit_weight_base_metric
else
R.string.measurement_unit_weight_base_imperial
)
this.measurement_unit_weight_tiny = context.getString(
if (measurementSystem == LocaleData. MeasurementSystem.SI)
R.string.measurement_unit_weight_tiny_metric
else
R.string.measurement_unit_weight_tiny_imperial
)
}
override fun onCreateViewHolder(
@ -33,32 +58,25 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
position: Int
) {
val item = items.get(position)
holder.type.text = context.getString(
when (item.type) {
LunaEvent.TYPE_BABY_BOTTLE -> R.string.event_bottle_type
LunaEvent.TYPE_WEIGHT -> R.string.event_scale_type
LunaEvent.TYPE_BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_type
LunaEvent.TYPE_BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type
LunaEvent.TYPE_BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type
LunaEvent.TYPE_DIAPERCHANGE_POO -> R.string.event_diaperchange_poo_type
LunaEvent.TYPE_DIAPERCHANGE_PEE -> R.string.event_diaperchange_pee_type
else -> R.string.event_unknown_type
}
)
holder.description.text = context.getString(
when (item.type) {
LunaEvent.TYPE_BABY_BOTTLE -> R.string.event_bottle_desc
LunaEvent.TYPE_WEIGHT -> R.string.event_scale_desc
LunaEvent.TYPE_BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_desc
LunaEvent.TYPE_BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc
LunaEvent.TYPE_BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc
LunaEvent.TYPE_DIAPERCHANGE_POO -> R.string.event_diaperchange_poo_desc
LunaEvent.TYPE_DIAPERCHANGE_PEE -> R.string.event_diaperchange_pee_desc
else -> R.string.event_unknown_desc
}
)
holder.quantity.text = if ((item.quantity ?: 0) > 0) item.quantity.toString() else ""
holder.type.text = item.getTypeEmoji(context)
holder.description.text = when(item.type) {
LunaEvent.TYPE_MEDICINE -> item.notes
LunaEvent.TYPE_NOTE -> item.notes
LunaEvent.TYPE_CUSTOM -> item.notes
else -> item.getTypeDescription(context)
}
holder.time.text = formatTimeAgo(context, item.time)
val qtyText = if ((item.quantity ?: 0) > 0) {
item.quantity.toString() + " " + when (item.type) {
LunaEvent.TYPE_BABY_BOTTLE -> measurement_unit_liquid_base
LunaEvent.TYPE_WEIGHT -> measurement_unit_weight_base
LunaEvent.TYPE_MEDICINE -> measurement_unit_weight_tiny
else -> ""
}
} else {
""
}
holder.quantity.text = qtyText
}
override fun getItemCount(): Int {
@ -90,9 +108,9 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
else
formattedTime.append(context.getString(R.string.hours_ago))
}
if (formattedTime.isNotEmpty())
formattedTime.append(", ")
if (minutesAgo > 0) {
if (formattedTime.isNotEmpty())
formattedTime.append(", ")
formattedTime.append(minutesAgo).append(" ")
if (minutesAgo.toInt() == 1)
formattedTime.append(context.getString(R.string.minute_ago))

View File

@ -1,5 +1,7 @@
package it.danieleverducci.lunatracker.entities
import android.content.Context
import it.danieleverducci.lunatracker.R
import org.json.JSONObject
import java.util.Date
@ -19,6 +21,10 @@ class LunaEvent {
val TYPE_BREASTFEEDING_RIGHT_NIPPLE = "BREASTFEEDING_RIGHT_NIPPLE"
val TYPE_DIAPERCHANGE_POO = "DIAPERCHANGE_POO"
val TYPE_DIAPERCHANGE_PEE = "DIAPERCHANGE_PEE"
val TYPE_MEDICINE = "MEDICINE"
val TYPE_ENEMA = "ENEMA"
val TYPE_NOTE = "NOTE"
val TYPE_CUSTOM = "CUSTOM"
}
private val jo: JSONObject
@ -39,6 +45,11 @@ class LunaEvent {
if (value > 0)
jo.put("quantity", value)
}
var notes: String
get(): String = jo.getString("notes")
set(value) {
jo.put("notes", value)
}
constructor(jo: JSONObject) {
this.jo = jo
@ -60,6 +71,42 @@ class LunaEvent {
this.quantity = quantity
}
fun getTypeEmoji(context: Context): String {
return context.getString(
when (type) {
TYPE_BABY_BOTTLE -> R.string.event_bottle_type
TYPE_WEIGHT -> R.string.event_scale_type
TYPE_BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_type
TYPE_BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_type
TYPE_BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_type
TYPE_DIAPERCHANGE_POO -> R.string.event_diaperchange_poo_type
TYPE_DIAPERCHANGE_PEE -> R.string.event_diaperchange_pee_type
TYPE_MEDICINE -> R.string.event_medicine_type
TYPE_ENEMA -> R.string.event_enema_type
TYPE_NOTE -> R.string.event_note_type
else -> R.string.event_unknown_type
}
)
}
fun getTypeDescription(context: Context): String {
return context.getString(
when (type) {
TYPE_BABY_BOTTLE -> R.string.event_bottle_desc
TYPE_WEIGHT -> R.string.event_scale_desc
TYPE_BREASTFEEDING_LEFT_NIPPLE -> R.string.event_breastfeeding_left_desc
TYPE_BREASTFEEDING_BOTH_NIPPLE -> R.string.event_breastfeeding_both_desc
TYPE_BREASTFEEDING_RIGHT_NIPPLE -> R.string.event_breastfeeding_right_desc
TYPE_DIAPERCHANGE_POO -> R.string.event_diaperchange_poo_desc
TYPE_DIAPERCHANGE_PEE -> R.string.event_diaperchange_pee_desc
TYPE_MEDICINE -> R.string.event_medicine_desc
TYPE_ENEMA -> R.string.event_enema_desc
TYPE_NOTE -> R.string.event_note_desc
else -> R.string.event_unknown_desc
}
)
}
fun toJson(): JSONObject {
return jo
}

View File

@ -3,6 +3,8 @@
<stroke
android:width="2dp"
android:color="@color/accent" />
<solid
android:color="@color/cardview_dark_background"/>
<corners android:radius="15dp" />
<padding
android:bottom="5dp"

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>

View File

@ -108,7 +108,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:layout_weight="2"
android:background="@drawable/button_background"
android:gravity="center_horizontal"
android:textSize="30dp"
@ -119,12 +119,23 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:layout_weight="2"
android:background="@drawable/button_background"
android:gravity="center_horizontal"
android:textSize="30dp"
android:text="🚼 💧"/>
<ImageView
android:id="@+id/button_more"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@drawable/button_background"
android:gravity="center_horizontal"
android:src="@drawable/ic_more"
app:tint="@android:color/darker_gray"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp">
<EditText
android:id="@+id/notes_qty_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="1"
android:inputType="number"
android:hint="@string/log_notes_dialog_qty_hint"/>
<EditText
android:id="@+id/notes_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:lines="10"/>
</LinearLayout>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:background="@color/transparent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/button_medicine"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:background="@drawable/button_background"
android:text="@string/overflow_event_medicine"/>
<TextView
android:id="@+id/button_enema"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:padding="20dp"
android:background="@drawable/button_background"
android:text="@string/overflow_event_enema"/>
<TextView
android:id="@+id/button_note"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:padding="20dp"
android:background="@drawable/button_background"
android:text="@string/overflow_event_note"/>
<LinearLayout
android:id="@+id/overflow_event_custom_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
<TextView
android:id="@+id/button_custom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:padding="20dp"
android:background="@drawable/button_background"
android:text="@string/overflow_event_custom"/>
</LinearLayout>
</ScrollView>

View File

@ -7,17 +7,20 @@
<TextView
android:id="@+id/type"
android:layout_width="0dp"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textSize="28sp"
android:text="Type"/>
android:lines="1"
android:maxLines="1"
android:text="@string/event_diaperchange_pee_type"/>
<TextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:ellipsize="end"
android:maxLines="2"
android:text="Description"/>
<TextView
@ -25,7 +28,11 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center_horizontal"
android:lines="1"
android:maxLines="1"
android:text="Qty"/>
<TextView
@ -35,6 +42,8 @@
android:layout_weight="2"
android:gravity="center_horizontal"
android:textStyle="bold"
android:ellipsize="end"
android:maxLines="2"
android:text="Time"/>
</LinearLayout>

View File

@ -10,14 +10,10 @@
<string name="log_weight_dialog_title">Pesata</string>
<string name="log_weight_dialog_description">Inserisci il peso rilevato</string>
<string name="event_bottle_type">🍼</string>
<string name="event_scale_type">⚖️</string>
<string name="event_breastfeeding_left_type">🤱 ←</string>
<string name="event_breastfeeding_both_type">🤱 ↔</string>
<string name="event_breastfeeding_right_type">🤱 →</string>
<string name="event_diaperchange_poo_type">🚼 💩</string>
<string name="event_diaperchange_pee_type">🚼 💧</string>
<string name="event_unknown_type">-</string>
<string name="overflow_event_medicine">💊 Medicina</string>
<string name="overflow_event_enema">🪠 Clistere</string>
<string name="overflow_event_note">📝 Nota</string>
<string name="overflow_event_custom"> Aggiungi evento personalizzato</string>
<string name="event_bottle_desc">Biberon</string>
<string name="event_scale_desc">Pesata</string>
@ -26,6 +22,9 @@
<string name="event_breastfeeding_right_desc">Allatt. al seno (dx)</string>
<string name="event_diaperchange_poo_desc">Cambio (con cacca)</string>
<string name="event_diaperchange_pee_desc">Cambio (con pipì)</string>
<string name="event_medicine_desc">Medicina</string>
<string name="event_enema_desc">Clistere</string>
<string name="event_note_desc">Nota</string>
<string name="event_unknown_desc"></string>
<string name="toast_event_added">Evento aggiunto</string>
@ -68,4 +67,8 @@
<string name="trim_logbook_dialog_button_ok">Cancella i più vecchi</string>
<string name="trim_logbook_dialog_button_cancel">Ricordamelo dopo</string>
<string name="log_notes_dialog_description">Note:</string>
<string name="log_medicine_dialog_description">Nome della medicina, quantità, formato, note…:</string>
<string name="log_notes_dialog_qty_hint">Quantità (numero intero), o lascia vuoto</string>
</resources>

View File

@ -4,5 +4,6 @@
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="translucent">#c000</color>
<color name="transparent">#0000</color>
<color name="grey">#ccc</color>
</resources>

View File

@ -10,14 +10,17 @@
<string name="log_weight_dialog_title">Weight</string>
<string name="log_weight_dialog_description">Insert the weight</string>
<string name="event_bottle_type">🍼</string>
<string name="event_scale_type">⚖️</string>
<string name="event_breastfeeding_left_type">🤱 ←</string>
<string name="event_breastfeeding_both_type">🤱 ↔</string>
<string name="event_breastfeeding_right_type">🤱 →</string>
<string name="event_diaperchange_poo_type">🚼 💩</string>
<string name="event_diaperchange_pee_type">🚼 💧</string>
<string name="event_unknown_type">-</string>
<string name="event_bottle_type" translatable="false">🍼</string>
<string name="event_scale_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_right_type" translatable="false">🤱 →</string>
<string name="event_diaperchange_poo_type" translatable="false">🚼 💩</string>
<string name="event_diaperchange_pee_type" translatable="false">🚼 💧</string>
<string name="event_medicine_type" translatable="false">💊</string>
<string name="event_enema_type" translatable="false">🪠</string>
<string name="event_note_type" translatable="false">📝</string>
<string name="event_unknown_type" translatable="false">\?</string>
<string name="event_bottle_desc">Baby bottle</string>
<string name="event_scale_desc">Weight</string>
@ -26,8 +29,16 @@
<string name="event_breastfeeding_right_desc">Breastfeeding (right)</string>
<string name="event_diaperchange_poo_desc">Diaper chg (poo)</string>
<string name="event_diaperchange_pee_desc">Diaper chg (pee)</string>
<string name="event_medicine_desc">Medicine</string>
<string name="event_enema_desc">Enema</string>
<string name="event_note_desc">Note</string>
<string name="event_unknown_desc"></string>
<string name="overflow_event_medicine">💊 Medicine</string>
<string name="overflow_event_enema">🪠 Enema</string>
<string name="overflow_event_note">📝 Note</string>
<string name="overflow_event_custom"> Add custom event</string>
<string name="toast_event_added">Event logged</string>
<string name="toast_logbook_saved">Logbook saved</string>
<string name="toast_event_add_error">Unable to log the event</string>
@ -49,7 +60,7 @@
<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>
<string name="settings_storage_dav">On a WebDAV server</string>
<string name="settings_storage_dav_desc">You can use any WebDAV service (i.e. Nextcloud, Owncloud, Dropbox, Box...) to save the data. In this way you can syncronize it between more devices, i.e. the dad\'s, the mom\'s, the grandma\'s... You will need the WebDAV url, you can find it in your provider\'s documentation (i.e. in Nextcloud web is in the Files app settings)</string>
<string name="settings_storage_dav_desc">You can use any WebDAV service (i.e. Nextcloud, Owncloud, Dropbox, Box) to save the data. In this way you can syncronize it between more devices, i.e. the dad\'s, the mom\'s, the grandma\'s You will need the WebDAV url, you can find it in your provider\'s documentation (i.e. in Nextcloud web is in the Files app settings)</string>
<string name="settings_storage_dav_url">WebDAV url</string>
<string name="settings_storage_dav_url_hint">https://</string>
<string name="settings_storage_dav_user">Username</string>
@ -68,4 +79,15 @@
<string name="trim_logbook_dialog_button_ok">Trim it now</string>
<string name="trim_logbook_dialog_button_cancel">Remind me later</string>
<string name="log_notes_dialog_description">Notes:</string>
<string name="log_medicine_dialog_description">Medicine name, quantity, type, notes…:</string>
<string name="log_notes_dialog_qty_hint">Integer quantity, or leave blank</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_tiny_metric" translatable="false">mg</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_tiny_imperial" translatable="false">gr</string>
</resources>