6 Commits

Author SHA1 Message Date
e566624a29 remove log event title
Keep the main page simpler and have a bit more
space for log messages.
2025-09-16 09:39:58 +02:00
77f6a89fcc add setting to disable breastfeeding buttons
Some women do not breastfeed. Hide the buttons
in order to have more space for log messages.
2025-09-16 09:39:58 +02:00
9efe2a3574 replace dp with sp
As suggested by android-studio.
2025-09-16 09:39:58 +02:00
3a65d09e58 values: escape apostrophe characters 2025-09-16 09:39:58 +02:00
1508db2a56 add password toggle view icon 2025-09-16 09:39:58 +02:00
674d4fd744 layout_marginLeft is deprecated 2025-09-16 09:39:21 +02:00
21 changed files with 89 additions and 274 deletions

1
.idea/.name generated
View File

@@ -1 +0,0 @@
LunaTracker

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

6
.idea/compiler.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
</project>

View File

@@ -11,8 +11,7 @@ Dedicated to my daughter Luna.
![Screenshot](fastlane/metadata/android/en-US/images/phoneScreenshots/1.png) ![Screenshot](fastlane/metadata/android/en-US/images/phoneScreenshots/1.png)
## Thanks for the valuable contributions to: Thanks for the valuable contributions to:
- Chepycou (French translation) Chepycou (French translation)
- Daniel Neubauer (German translation) Daniel Neubauer (German translation)
- Moritz Warning (Various bugfixes and new features)

View File

@@ -12,8 +12,8 @@ android {
applicationId = "it.danieleverducci.lunatracker" applicationId = "it.danieleverducci.lunatracker"
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = 5 versionCode = 4
versionName = "0.7" versionName = "0.6"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -39,7 +39,6 @@ import it.danieleverducci.lunatracker.repository.WebDAVLogbookRepository
import kotlinx.coroutines.Runnable import kotlinx.coroutines.Runnable
import okio.IOException import okio.IOException
import org.json.JSONException import org.json.JSONException
import utils.DateUtils
import utils.NumericUtils import utils.NumericUtils
import java.text.DateFormat import java.text.DateFormat
import java.util.Calendar import java.util.Calendar
@@ -75,9 +74,9 @@ class MainActivity : AppCompatActivity() {
// Show view // Show view
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
progressIndicator = findViewById(R.id.progress_indicator) progressIndicator = findViewById<LinearProgressIndicator>(R.id.progress_indicator)
buttonsContainer = findViewById(R.id.buttons_container) buttonsContainer = findViewById<ViewGroup>(R.id.buttons_container)
recyclerView = findViewById(R.id.list_events) recyclerView = findViewById<RecyclerView>(R.id.list_events)
recyclerView.setLayoutManager(LinearLayoutManager(applicationContext)) recyclerView.setLayoutManager(LinearLayoutManager(applicationContext))
// Set listeners // Set listeners
@@ -132,7 +131,7 @@ class MainActivity : AppCompatActivity() {
val adapter = LunaEventRecyclerAdapter(this, items) val adapter = LunaEventRecyclerAdapter(this, items)
adapter.onItemClickListener = object: LunaEventRecyclerAdapter.OnItemClickListener{ adapter.onItemClickListener = object: LunaEventRecyclerAdapter.OnItemClickListener{
override fun onItemClick(event: LunaEvent) { override fun onItemClick(event: LunaEvent) {
showEventDetailDialog(event, items) showEventDetailDialog(event)
} }
} }
recyclerView.adapter = adapter recyclerView.adapter = adapter
@@ -309,52 +308,25 @@ class MainActivity : AppCompatActivity() {
alertDialog.show() alertDialog.show()
} }
fun getPreviousSameEvent(event: LunaEvent, items: ArrayList<LunaEvent>): LunaEvent? { fun showEventDetailDialog(event: LunaEvent) {
var previousEvent: LunaEvent? = null
for (item in items) {
if (item.type == event.type && item.time < event.time) {
if (previousEvent == null) {
previousEvent = item
} else if (previousEvent.time < item.time) {
previousEvent = item
}
}
}
return previousEvent
}
fun getNextSameEvent(event: LunaEvent, items: ArrayList<LunaEvent>): LunaEvent? {
var nextEvent: LunaEvent? = null
for (item in items) {
if (item.type == event.type && item.time > event.time) {
if (nextEvent == null) {
nextEvent = item
} else if (nextEvent.time > item.time) {
nextEvent = item
}
}
}
return nextEvent
}
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 // Do not update list while the detail is shown, to avoid changing the object below while it is changed by the user
pauseLogbookUpdate = true pauseLogbookUpdate = true
val dateFormat = DateFormat.getDateTimeInstance() val dateFormat = DateFormat.getDateTimeInstance();
val d = AlertDialog.Builder(this) val d = AlertDialog.Builder(this)
d.setTitle(R.string.dialog_event_detail_title) d.setTitle(R.string.dialog_event_detail_title)
val dialogView = layoutInflater.inflate(R.layout.dialog_event_detail, null) val dialogView = layoutInflater.inflate(R.layout.dialog_event_detail, null)
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_emoji).text = event.getTypeEmoji(this) dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_emoji).setText(event.getTypeEmoji(this))
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_description).text = event.getTypeDescription(this) dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_description).setText(event.getTypeDescription(this))
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_quantity).text = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_quantity).setText(
NumericUtils(this).formatEventQuantity(event) NumericUtils(this).formatEventQuantity(event)
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_notes).text = event.notes )
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_notes).setText(event.notes)
val currentDateTime = Calendar.getInstance() val currentDateTime = Calendar.getInstance()
currentDateTime.time = Date(event.time * 1000) currentDateTime.time = Date(event.time * 1000)
val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date) val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date)
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), dateFormat.format(currentDateTime.time)) dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), dateFormat.format(currentDateTime.time))
dateTextView.setOnClickListener { dateTextView.setOnClickListener({
// Show datetime picker // Show datetime picker
val startYear = currentDateTime.get(Calendar.YEAR) val startYear = currentDateTime.get(Calendar.YEAR)
val startMonth = currentDateTime.get(Calendar.MONTH) val startMonth = currentDateTime.get(Calendar.MONTH)
@@ -362,8 +334,8 @@ class MainActivity : AppCompatActivity() {
val startHour = currentDateTime.get(Calendar.HOUR_OF_DAY) val startHour = currentDateTime.get(Calendar.HOUR_OF_DAY)
val startMinute = currentDateTime.get(Calendar.MINUTE) val startMinute = currentDateTime.get(Calendar.MINUTE)
DatePickerDialog(this, { _, year, month, day -> DatePickerDialog(this, DatePickerDialog.OnDateSetListener { _, year, month, day ->
TimePickerDialog(this, { _, hour, minute -> TimePickerDialog(this, TimePickerDialog.OnTimeSetListener { _, hour, minute ->
val pickedDateTime = Calendar.getInstance() val pickedDateTime = Calendar.getInstance()
pickedDateTime.set(year, month, day, hour, minute) pickedDateTime.set(year, month, day, hour, minute)
currentDateTime.time = pickedDateTime.time currentDateTime.time = pickedDateTime.time
@@ -374,9 +346,9 @@ class MainActivity : AppCompatActivity() {
logbook?.sort() logbook?.sort()
recyclerView.adapter?.notifyDataSetChanged() recyclerView.adapter?.notifyDataSetChanged()
saveLogbook() saveLogbook()
}, startHour, startMinute, android.text.format.DateFormat.is24HourFormat(this@MainActivity)).show() }, startHour, startMinute, false).show()
}, startYear, startMonth, startDay).show() }, startYear, startMonth, startDay).show()
} })
d.setView(dialogView) d.setView(dialogView)
d.setPositiveButton(R.string.dialog_event_detail_close_button) { dialogInterface, i -> dialogInterface.dismiss() } d.setPositiveButton(R.string.dialog_event_detail_close_button) { dialogInterface, i -> dialogInterface.dismiss() }
@@ -388,37 +360,6 @@ class MainActivity : AppCompatActivity() {
// Resume logbook update // Resume logbook update
pauseLogbookUpdate = false pauseLogbookUpdate = false
}) })
// create next/previous links to events of the same type
val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous)
val nextTextView = dialogView.findViewById<TextView>(R.id.dialog_event_next)
val nextEvent = getNextSameEvent(event, items)
val previousEvent = getPreviousSameEvent(event, items)
if (previousEvent != null) {
val emoji = previousEvent.getTypeEmoji(applicationContext)
val time = DateUtils.formatTimeDuration(applicationContext, event.time - previousEvent.time)
previousTextView.text = String.format("⬅️ %s %s", emoji, time)
previousTextView.setOnClickListener {
alertDialog.cancel()
showEventDetailDialog(previousEvent, items)
}
} else {
previousTextView.visibility = View.GONE
}
if (nextEvent != null) {
val emoji = nextEvent.getTypeEmoji(applicationContext)
val time = DateUtils.formatTimeDuration(applicationContext, nextEvent.time - event.time)
nextTextView.text = String.format("%s %s ➡️", time, emoji)
nextTextView.setOnClickListener {
alertDialog.cancel()
showEventDetailDialog(nextEvent, items)
}
} else {
nextTextView.visibility = View.GONE
}
} }
fun showAddLogbookDialog(requestedByUser: Boolean) { fun showAddLogbookDialog(requestedByUser: Boolean) {
@@ -457,7 +398,7 @@ class MainActivity : AppCompatActivity() {
sAdapter.setDropDownViewResource(R.layout.row_logbook_spinner) sAdapter.setDropDownViewResource(R.layout.row_logbook_spinner)
for (ln in logbooksNames) { for (ln in logbooksNames) {
sAdapter.add( sAdapter.add(
ln.ifEmpty { getString(R.string.default_logbook_name) } if (ln.isEmpty()) getString(R.string.default_logbook_name) else ln
) )
} }
spinner.adapter = sAdapter spinner.adapter = sAdapter
@@ -475,6 +416,7 @@ class MainActivity : AppCompatActivity() {
} }
override fun onNothingSelected(parent: AdapterView<*>?) {} override fun onNothingSelected(parent: AdapterView<*>?) {}
} }
}) })
} }
@@ -624,6 +566,7 @@ class MainActivity : AppCompatActivity() {
onRepoError(getString(R.string.settings_generic_error) + error.toString()) onRepoError(getString(R.string.settings_generic_error) + error.toString())
}) })
} }
}) })
} }
@@ -771,10 +714,10 @@ class MainActivity : AppCompatActivity() {
isOutsideTouchable = true isOutsideTouchable = true
val inflater = LayoutInflater.from(anchor.context) val inflater = LayoutInflater.from(anchor.context)
contentView = inflater.inflate(R.layout.more_events_popup, null) contentView = inflater.inflate(R.layout.more_events_popup, null)
contentView.findViewById<View>(R.id.button_medicine).setOnClickListener { contentView.findViewById<View>(R.id.button_medicine).setOnClickListener({
askNotes(LunaEvent(LunaEvent.TYPE_MEDICINE)) askNotes(LunaEvent(LunaEvent.TYPE_MEDICINE))
dismiss() dismiss()
} })
contentView.findViewById<View>(R.id.button_enema).setOnClickListener({ contentView.findViewById<View>(R.id.button_enema).setOnClickListener({
logEvent(LunaEvent(LunaEvent.TYPE_ENEMA)) logEvent(LunaEvent(LunaEvent.TYPE_ENEMA))
dismiss() dismiss()

View File

@@ -12,8 +12,10 @@ import com.thegrizzlylabs.sardineandroid.impl.SardineException
import it.danieleverducci.lunatracker.repository.FileLogbookRepository import it.danieleverducci.lunatracker.repository.FileLogbookRepository
import it.danieleverducci.lunatracker.repository.LocalSettingsRepository import it.danieleverducci.lunatracker.repository.LocalSettingsRepository
import it.danieleverducci.lunatracker.repository.LogbookListObtainedListener import it.danieleverducci.lunatracker.repository.LogbookListObtainedListener
import it.danieleverducci.lunatracker.repository.LogbookRepository
import it.danieleverducci.lunatracker.repository.WebDAVLogbookRepository import it.danieleverducci.lunatracker.repository.WebDAVLogbookRepository
import okio.IOException import okio.IOException
import org.json.JSONException
open class SettingsActivity : AppCompatActivity() { open class SettingsActivity : AppCompatActivity() {
protected lateinit var settingsRepository: LocalSettingsRepository protected lateinit var settingsRepository: LocalSettingsRepository

View File

@@ -2,7 +2,7 @@ package it.danieleverducci.lunatracker.entities
class Logbook(val name: String) { class Logbook(val name: String) {
companion object { companion object {
const val MAX_SAFE_LOGBOOK_SIZE = 30000 val MAX_SAFE_LOGBOOK_SIZE = 30000
} }
val logs = ArrayList<LunaEvent>() val logs = ArrayList<LunaEvent>()

View File

@@ -14,20 +14,20 @@ import java.util.Date
class LunaEvent: Comparable<LunaEvent> { class LunaEvent: Comparable<LunaEvent> {
companion object { companion object {
const val TYPE_BABY_BOTTLE = "BABY_BOTTLE" val TYPE_BABY_BOTTLE = "BABY_BOTTLE"
const val TYPE_WEIGHT = "WEIGHT" val TYPE_WEIGHT = "WEIGHT"
const val TYPE_BREASTFEEDING_LEFT_NIPPLE = "BREASTFEEDING_LEFT_NIPPLE" val TYPE_BREASTFEEDING_LEFT_NIPPLE = "BREASTFEEDING_LEFT_NIPPLE"
const val TYPE_BREASTFEEDING_BOTH_NIPPLE = "BREASTFEEDING_BOTH_NIPPLE" val TYPE_BREASTFEEDING_BOTH_NIPPLE = "BREASTFEEDING_BOTH_NIPPLE"
const val TYPE_BREASTFEEDING_RIGHT_NIPPLE = "BREASTFEEDING_RIGHT_NIPPLE" val TYPE_BREASTFEEDING_RIGHT_NIPPLE = "BREASTFEEDING_RIGHT_NIPPLE"
const val TYPE_DIAPERCHANGE_POO = "DIAPERCHANGE_POO" val TYPE_DIAPERCHANGE_POO = "DIAPERCHANGE_POO"
const val TYPE_DIAPERCHANGE_PEE = "DIAPERCHANGE_PEE" val TYPE_DIAPERCHANGE_PEE = "DIAPERCHANGE_PEE"
const val TYPE_MEDICINE = "MEDICINE" val TYPE_MEDICINE = "MEDICINE"
const val TYPE_ENEMA = "ENEMA" val TYPE_ENEMA = "ENEMA"
const val TYPE_NOTE = "NOTE" val TYPE_NOTE = "NOTE"
const val TYPE_CUSTOM = "CUSTOM" val TYPE_CUSTOM = "CUSTOM"
const val TYPE_COLIC = "COLIC" val TYPE_COLIC = "COLIC"
const val TYPE_TEMPERATURE = "TEMPERATURE" val TYPE_TEMPERATURE = "TEMPERATURE"
const val TYPE_FOOD = "FOOD" val TYPE_FOOD = "FOOD"
} }
private val jo: JSONObject private val jo: JSONObject

View File

@@ -7,62 +7,6 @@ import java.util.Date
class DateUtils { class DateUtils {
companion object { companion object {
fun formatTimeDuration(context: Context, secondsDiff: Long): String {
var seconds = secondsDiff
val years = (seconds / (365 * 24 * 60 * 60F)).toLong()
seconds -= years * (365 * 24 * 60 * 60)
val days = (seconds / (24 * 60 * 60F)).toLong()
seconds -= days * (24 * 60 * 60)
val hours = (seconds / (60 * 60F)).toLong()
seconds -= hours * (60 * 60)
val minutes = (seconds / 60F).toLong()
seconds -= minutes * 60
fun format(value1: Long, value2: Long, resIdSingular1: Int, resIdPlural1: Int, resIdSingular2: Int, resIdPlural2: Int): String {
val builder = StringBuilder()
if (value1 == 0L) {
// omit
} else if (value1 == 1L) {
builder.append(value1)
builder.append(" ")
builder.append(context.getString(resIdSingular1))
} else {
builder.append(value1)
builder.append(" ")
builder.append(context.getString(resIdPlural1))
}
if (value1 > 0L && value2 > 0L) {
builder.append(", ")
}
if (value2 == 0L) {
// omit
} else if (value2 == 1L) {
builder.append(value2)
builder.append(" ")
builder.append(context.getString(resIdSingular2))
} else {
builder.append(value2)
builder.append(" ")
builder.append(context.getString(resIdPlural2))
}
return builder.toString()
}
if (years > 0) {
return format(years, days, R.string.year_ago, R.string.years_ago, R.string.day_ago, R.string.days_ago)
} else if (days > 0) {
return format(days, hours, R.string.day_ago, R.string.days_ago, R.string.hour_ago, R.string.hours_ago)
} else if (hours > 0) {
return format(hours, minutes, R.string.hour_ago, R.string.hours_ago, R.string.minute_ago, R.string.minutes_ago)
} else if (minutes > 0) {
return format(minutes, seconds, R.string.minute_ago, R.string.minute_ago, R.string.second_ago, R.string.seconds_ago)
} else {
return context.getString(R.string.now)
}
}
/** /**
* 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)
@@ -81,10 +25,10 @@ class DateUtils {
return DateFormat.getDateFormat(context).format(Date(unixTime*1000)) + "\n" + return DateFormat.getDateFormat(context).format(Date(unixTime*1000)) + "\n" +
DateFormat.getTimeFormat(context).format(Date(unixTime*1000)) DateFormat.getTimeFormat(context).format(Date(unixTime*1000))
val formattedTime = StringBuilder() var formattedTime = StringBuilder()
if (hoursAgo > 0) { if (hoursAgo > 0) {
formattedTime.append(hoursAgo).append(" ") formattedTime.append(hoursAgo).append(" ")
if (hoursAgo == 1) if (hoursAgo.toInt() == 1)
formattedTime.append(context.getString(R.string.hour_ago)) formattedTime.append(context.getString(R.string.hour_ago))
else else
formattedTime.append(context.getString(R.string.hours_ago)) formattedTime.append(context.getString(R.string.hours_ago))
@@ -93,7 +37,7 @@ class DateUtils {
if (formattedTime.isNotEmpty()) if (formattedTime.isNotEmpty())
formattedTime.append(", ") formattedTime.append(", ")
formattedTime.append(minutesAgo).append(" ") formattedTime.append(minutesAgo).append(" ")
if (minutesAgo == 1) if (minutesAgo.toInt() == 1)
formattedTime.append(context.getString(R.string.minute_ago)) formattedTime.append(context.getString(R.string.minute_ago))
else else
formattedTime.append(context.getString(R.string.minutes_ago)) formattedTime.append(context.getString(R.string.minutes_ago))

View File

@@ -47,7 +47,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="38dp" android:layout_height="38dp"
android:layout_margin="5dp" android:layout_margin="10dp"
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="center_vertical"> android:gravity="center_vertical">
@@ -95,7 +95,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:layout_margin="5dp" android:layout_margin="10dp"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textSize="50sp" android:textSize="50sp"
@@ -106,7 +106,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:layout_margin="5dp" android:layout_margin="10dp"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textSize="50sp" android:textSize="50sp"
@@ -123,7 +123,7 @@
android:id="@+id/button_nipple_left" android:id="@+id/button_nipple_left"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="10dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
@@ -134,7 +134,7 @@
android:id="@+id/button_nipple_both" android:id="@+id/button_nipple_both"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="10dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
@@ -145,7 +145,7 @@
android:id="@+id/button_nipple_right" android:id="@+id/button_nipple_right"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="10dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
@@ -162,7 +162,7 @@
android:id="@+id/button_change_poo" android:id="@+id/button_change_poo"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="10dp"
android:layout_weight="2" android:layout_weight="2"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
@@ -173,7 +173,7 @@
android:id="@+id/button_change_pee" android:id="@+id/button_change_pee"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="10dp"
android:layout_weight="2" android:layout_weight="2"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
@@ -184,7 +184,7 @@
android:id="@+id/button_more" android:id="@+id/button_more"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="5dp" android:layout_margin="10dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@drawable/button_background" android:background="@drawable/button_background"
android:gravity="center_horizontal" android:gravity="center_horizontal"
@@ -195,31 +195,21 @@
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/logbook"
android:textColor="@color/accent"
android:textStyle="bold"/>
<com.google.android.material.progressindicator.LinearProgressIndicator <com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_indicator" android:id="@+id/progress_indicator"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_marginHorizontal="10dp"
android:indeterminate="true" android:indeterminate="true"
app:indicatorColor="@color/accent" app:indicatorColor="@color/accent"
android:visibility="invisible"/> android:visibility="invisible"/>
</LinearLayout> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/logbook"
android:textColor="@color/accent"
android:textStyle="bold"/>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/list_events" android:id="@+id/list_events"

View File

@@ -45,7 +45,7 @@
<RadioButton android:id="@+id/settings_data_webdav" <RadioButton android:id="@+id/settings_data_webdav"
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="30dp"
android:text="@string/settings_storage_dav"/> android:text="@string/settings_storage_dav"/>
<TextView <TextView
@@ -123,7 +123,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_marginTop="5dp"
android:layout_marginEnd="30dp"> android:layout_marginEnd="30dp">
<TextView <TextView

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@@ -11,17 +10,17 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textSize="60sp" android:textSize="60dp"
android:text="@string/event_diaperchange_pee_type"/> android:text="@string/event_diaperchange_pee_type"/>
<TextView <TextView
android:id="@+id/dialog_event_detail_type_description" android:id="@+id/dialog_event_detail_type_description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="10dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textColor="@color/accent" android:textColor="@color/accent"
android:textSize="32sp" android:textSize="24dp"
android:text="@string/event_diaperchange_pee_desc"/> android:text="@string/event_diaperchange_pee_desc"/>
<TextView <TextView
@@ -31,20 +30,18 @@
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:gravity="center_vertical" android:gravity="center_vertical"
android:drawableEnd="@drawable/ic_edit"
android:drawablePadding="10dp" android:drawablePadding="10dp"
android:drawableTint="@color/accent" android:drawableTint="@color/accent"
android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:text="@string/dialog_event_detail_datetime_icon" android:text="@string/dialog_event_detail_datetime_icon"/>
app:drawableEndCompat="@drawable/ic_edit" />
<TextView <TextView
android:id="@+id/dialog_event_detail_type_quantity" android:id="@+id/dialog_event_detail_type_quantity"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textSize="28sp" android:text="Quantity"/>
android:text="@string/dialog_event_detail_quantity"/>
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -56,37 +53,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textStyle="italic" android:textStyle="italic"
android:textSize="20sp" android:text="Notes"/>
android:text="@string/dialog_event_detail_notes"/>
</ScrollView> </ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/dialog_event_previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textSize="12sp"
android:text="" />
<Space
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/dialog_event_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:textSize="12sp"
android:text="" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -11,7 +11,7 @@
android:id="@+id/type" android:id="@+id/type"
android:layout_width="90dp" android:layout_width="90dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="10dp" android:paddingLeft="10dp"
android:textSize="28sp" android:textSize="28sp"
android:lines="1" android:lines="1"
android:maxLines="1" android:maxLines="1"
@@ -25,7 +25,7 @@
android:ellipsize="end" android:ellipsize="end"
android:maxLines="2" android:maxLines="2"
android:textColor="@color/accent" android:textColor="@color/accent"
android:text="@string/row_luna_event_description"/> android:text="Description"/>
<TextView <TextView
android:id="@+id/quantity" android:id="@+id/quantity"
@@ -35,7 +35,7 @@
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:text="@string/row_luna_event_quantity"/> android:text="Qty"/>
<TextView <TextView
android:id="@+id/time" android:id="@+id/time"
@@ -46,6 +46,6 @@
android:textStyle="bold" android:textStyle="bold"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="2" android:maxLines="2"
android:text="@string/row_luna_event_time"/> android:text="Time"/>
</LinearLayout> </LinearLayout>

View File

@@ -31,7 +31,7 @@
android:maxLines="2" android:maxLines="2"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textColor="@color/accent" android:textColor="@color/accent"
android:text="@string/row_luna_event_description"/> android:text="Description"/>
<TextView <TextView
android:id="@+id/quantity" android:id="@+id/quantity"
@@ -41,7 +41,7 @@
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:text="@string/dialog_event_detail_quantity"/> android:text="Qty"/>
<TextView <TextView
android:id="@+id/time" android:id="@+id/time"
@@ -52,7 +52,7 @@
android:textStyle="bold" android:textStyle="bold"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="2" android:maxLines="2"
android:text="@string/row_luna_event_time"/> android:text="Time"/>
</LinearLayout> </LinearLayout>

View File

@@ -55,16 +55,10 @@
<string name="toast_integer_error">Invalid value. Insert an integer.</string> <string name="toast_integer_error">Invalid value. Insert an integer.</string>
<string name="now">now</string> <string name="now">now</string>
<string name="second_ago">sec</string>
<string name="seconds_ago">secs</string>
<string name="minute_ago">min</string>
<string name="minutes_ago">mins</string>
<string name="hour_ago">hour</string> <string name="hour_ago">hour</string>
<string name="hours_ago">hours</string> <string name="hours_ago">hours</string>
<string name="day_ago">day</string> <string name="minute_ago">min</string>
<string name="days_ago">days</string> <string name="minutes_ago">mins</string>
<string name="year_ago">year</string>
<string name="years_ago">years</string>
<string name="no_connection">No connection</string> <string name="no_connection">No connection</string>
<string name="no_connection_explain">Unable to reach WebDAV service</string> <string name="no_connection_explain">Unable to reach WebDAV service</string>
@@ -113,16 +107,10 @@
<string name="measurement_unit_temperature_base_imperial" translatable="false">°F</string> <string name="measurement_unit_temperature_base_imperial" translatable="false">°F</string>
<string name="measurement_unit_temperature_base_metric" translatable="false">°C</string> <string name="measurement_unit_temperature_base_metric" translatable="false">°C</string>
<string name="row_luna_event_description">Description</string>
<string name="row_luna_event_quantity">Qty</string>
<string name="row_luna_event_time">Time</string>
<string name="dialog_event_detail_title">Event detail</string> <string name="dialog_event_detail_title">Event detail</string>
<string name="dialog_event_detail_datetime_icon" translatable="false">🕒 %s</string> <string name="dialog_event_detail_datetime_icon" translatable="false">🕒 %s1</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">Delete</string> <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_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>

View File

@@ -6,7 +6,6 @@ This app is meant to log all the relevant events (diaper change, breastfeeding,
Dedicated to my daughter Luna. Dedicated to my daughter Luna.
A HUGE thanks to all our contributors. See https://git.ichibi.eu/penguin86/luna-tracker/src/branch/master/README.md
NOTE: The content on this app is for informational or educational purposes only and does not substitute professional medical advice or consultations with healthcare professionals. NOTE: The content on this app is for informational or educational purposes only and does not substitute professional medical advice or consultations with healthcare professionals.
Feature graphic ("Baby and baby milk bottle. Baby feeding."): © Vyacheslav Argenberg / http://www.vascoplanet.com/, CC BY 4.0 <https://creativecommons.org/licenses/by/4.0>, via Wikimedia Commons Feature graphic ("Baby and baby milk bottle. Baby feeding."): © Vyacheslav Argenberg / http://www.vascoplanet.com/, CC BY 4.0 <https://creativecommons.org/licenses/by/4.0>, via Wikimedia Commons

View File

@@ -8,8 +8,6 @@ Elle permet de synchroniser les données entre différents appareils (en utilisa
Dédié à ma fille Luna. Dédié à ma fille Luna.
Un grand merci à tous nos contributeurs. Voir https://git.ichibi.eu/penguin86/luna-tracker/src/branch/master/README.md
REMARQUE : le contenu de cette application est fourni à titre informatif ou éducatif uniquement et ne remplace pas les conseils médicaux professionnels ou les consultations avec des professionnels de la santé. REMARQUE : le contenu de cette application est fourni à titre informatif ou éducatif uniquement et ne remplace pas les conseils médicaux professionnels ou les consultations avec des professionnels de la santé.
Crédit image ("Baby and baby milk bottle. Baby feeding."): © Vyacheslav Argenberg / http://www.vascoplanet.com/, CC BY 4.0 <https://creativecommons.org/licenses/by/4.0>, via Wikimedia Commons Crédit image ("Baby and baby milk bottle. Baby feeding."): © Vyacheslav Argenberg / http://www.vascoplanet.com/, CC BY 4.0 <https://creativecommons.org/licenses/by/4.0>, via Wikimedia Commons

View File

@@ -6,7 +6,6 @@ Quest'app è pensata per memorizzare tutti gli eventi del bambino (cambio di pan
Dedicato a mia figlia Luna. Dedicato a mia figlia Luna.
Un grandissimo ringraziamento a tutti i contributors! Vedi https://git.ichibi.eu/penguin86/luna-tracker/src/branch/master/README.md
NOTA: il contenuto di quest'app ha solo scopo informativo o didattico e non sostituisce il consulto medico professionale o le consulenze con operatori sanitari. NOTA: il contenuto di quest'app ha solo scopo informativo o didattico e non sostituisce il consulto medico professionale o le consulenze con operatori sanitari.
Feature graphic ("Baby and baby milk bottle. Baby feeding."): © Vyacheslav Argenberg / http://www.vascoplanet.com/, CC BY 4.0 <https://creativecommons.org/licenses/by/4.0>, via Wikimedia Commons Feature graphic ("Baby and baby milk bottle. Baby feeding."): © Vyacheslav Argenberg / http://www.vascoplanet.com/, CC BY 4.0 <https://creativecommons.org/licenses/by/4.0>, via Wikimedia Commons

View File

@@ -1,5 +1,5 @@
[versions] [versions]
agp = "8.13.0" agp = "8.7.2"
kotlin = "2.0.0" kotlin = "2.0.0"
coreKtx = "1.10.1" coreKtx = "1.10.1"
junit = "4.13.2" junit = "4.13.2"

View File

@@ -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-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists