3 Commits

Author SHA1 Message Date
609a9cb534 add puke event 2025-09-25 23:52:10 +02:00
eeebaeb7f3 NumericUtils: provide fallback for LocaleData.getMeasurementSystem
LocaleData.getMeasurementSystem is available at API level 28
but the app supports API level 21.
2025-09-25 23:51:13 +02:00
242bfe39ae small code cleanup 2025-09-25 23:46:46 +02:00
13 changed files with 86 additions and 202 deletions

View File

@@ -41,14 +41,15 @@ import okio.IOException
import org.json.JSONException import org.json.JSONException
import utils.DateUtils import utils.DateUtils
import utils.NumericUtils import utils.NumericUtils
import java.text.DateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
companion object { companion object {
const val TAG = "MainActivity" val TAG = "MainActivity"
const val UPDATE_EVERY_SECS: Long = 30 val UPDATE_EVERY_SECS: Long = 30
const val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false
} }
var logbook: Logbook? = null var logbook: Logbook? = null
@@ -57,7 +58,6 @@ class MainActivity : AppCompatActivity() {
lateinit var buttonsContainer: ViewGroup lateinit var buttonsContainer: ViewGroup
lateinit var recyclerView: RecyclerView lateinit var recyclerView: RecyclerView
lateinit var handler: Handler lateinit var handler: Handler
var signature = ""
var savingEvent = false var savingEvent = false
val updateListRunnable: Runnable = Runnable { val updateListRunnable: Runnable = Runnable {
if (logbook != null && !pauseLogbookUpdate) if (logbook != null && !pauseLogbookUpdate)
@@ -113,24 +113,24 @@ class MainActivity : AppCompatActivity() {
moreButton.setOnClickListener { moreButton.setOnClickListener {
showOverflowPopupWindow(moreButton) showOverflowPopupWindow(moreButton)
} }
findViewById<View>(R.id.button_no_connection_settings).setOnClickListener { findViewById<View>(R.id.button_no_connection_settings).setOnClickListener({
showSettings() showSettings()
} })
findViewById<View>(R.id.button_settings).setOnClickListener { findViewById<View>(R.id.button_settings).setOnClickListener({
showSettings() 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 // This may happen at start, when logbook is still null: better ask the logbook list
loadLogbookList() loadLogbookList()
} })
findViewById<View>(R.id.button_sync).setOnClickListener { findViewById<View>(R.id.button_sync).setOnClickListener({
loadLogbookList() loadLogbookList()
} })
} }
private fun setListAdapter(items: ArrayList<LunaEvent>) { private fun setListAdapter(items: ArrayList<LunaEvent>) {
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, items)
} }
@@ -169,8 +169,6 @@ class MainActivity : AppCompatActivity() {
logbookRepo = FileLogbookRepository() logbookRepo = FileLogbookRepository()
} }
signature = settingsRepository.loadSignature()
val noBreastfeeding = settingsRepository.loadNoBreastfeeding() val noBreastfeeding = settingsRepository.loadNoBreastfeeding()
findViewById<View>(R.id.layout_nipples).visibility = when (noBreastfeeding) { findViewById<View>(R.id.layout_nipples).visibility = when (noBreastfeeding) {
true -> View.GONE true -> View.GONE
@@ -271,7 +269,6 @@ class MainActivity : AppCompatActivity() {
val spinner = dialogView.findViewById<Spinner>(R.id.dialog_puke_value) val spinner = dialogView.findViewById<Spinner>(R.id.dialog_puke_value)
spinner.adapter = ArrayAdapter.createFromResource(this, R.array.AmountLabels, android.R.layout.simple_spinner_dropdown_item) spinner.adapter = ArrayAdapter.createFromResource(this, R.array.AmountLabels, android.R.layout.simple_spinner_dropdown_item)
spinner.setSelection(1)
d.setPositiveButton(android.R.string.ok) { dialogInterface, i -> d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
val pos = spinner.selectedItemPosition val pos = spinner.selectedItemPosition
@@ -362,6 +359,7 @@ class MainActivity : AppCompatActivity() {
fun showEventDetailDialog(event: LunaEvent, items: ArrayList<LunaEvent>) { 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 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)
@@ -373,9 +371,8 @@ class MainActivity : AppCompatActivity() {
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), DateUtils.formatDateTime(event.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)
@@ -388,9 +385,11 @@ class MainActivity : AppCompatActivity() {
TimePickerDialog(this, { _, hour, minute -> TimePickerDialog(this, { _, 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
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 // Save event and move it to the right position in the logbook
event.time = pickedDateTime.time.time / 1000 // Seconds since epoch event.time = currentDateTime.time.time / 1000 // Seconds since epoch
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
logbook?.sort() logbook?.sort()
recyclerView.adapter?.notifyDataSetChanged() recyclerView.adapter?.notifyDataSetChanged()
saveLogbook() saveLogbook()
@@ -409,13 +408,6 @@ class MainActivity : AppCompatActivity() {
pauseLogbookUpdate = false pauseLogbookUpdate = false
}) })
// show optional signature
if (event.signature.isNotEmpty()) {
val signatureTextEdit = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_signature)
signatureTextEdit.text = String.format(getString(R.string.dialog_event_detail_signature), event.signature)
signatureTextEdit.visibility = View.VISIBLE
}
// create next/previous links to events of the same type // create next/previous links to events of the same type
val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous) val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous)
@@ -665,8 +657,6 @@ class MainActivity : AppCompatActivity() {
fun logEvent(event: LunaEvent) { fun logEvent(event: LunaEvent) {
savingEvent(true) savingEvent(true)
event.signature = signature
setLoading(true) setLoading(true)
logbook?.logs?.add(0, event) logbook?.logs?.add(0, event)
recyclerView.adapter?.notifyItemInserted(0) recyclerView.adapter?.notifyItemInserted(0)
@@ -830,12 +820,6 @@ class MainActivity : AppCompatActivity() {
askWeightValue() askWeightValue()
dismiss() dismiss()
}) })
contentView.findViewById<View>(R.id.button_bath).setOnClickListener({
logEvent(
LunaEvent(LunaEvent.TYPE_BATH)
)
dismiss()
})
}.also { popupWindow -> }.also { popupWindow ->
popupWindow.setOnDismissListener({ popupWindow.setOnDismissListener({
Handler(mainLooper).postDelayed({ Handler(mainLooper).postDelayed({

View File

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

View File

@@ -29,7 +29,6 @@ class LunaEvent: Comparable<LunaEvent> {
const val TYPE_TEMPERATURE = "TEMPERATURE" const val TYPE_TEMPERATURE = "TEMPERATURE"
const val TYPE_FOOD = "FOOD" const val TYPE_FOOD = "FOOD"
const val TYPE_PUKE = "PUKE" const val TYPE_PUKE = "PUKE"
const val TYPE_BATH = "BATH"
} }
private val jo: JSONObject private val jo: JSONObject
@@ -55,12 +54,6 @@ class LunaEvent: Comparable<LunaEvent> {
set(value) { set(value) {
jo.put("notes", 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) { constructor(jo: JSONObject) {
this.jo = jo this.jo = jo
@@ -99,7 +92,6 @@ class LunaEvent: Comparable<LunaEvent> {
TYPE_COLIC -> R.string.event_colic_type TYPE_COLIC -> R.string.event_colic_type
TYPE_FOOD -> R.string.event_food_type TYPE_FOOD -> R.string.event_food_type
TYPE_PUKE -> R.string.event_puke_type TYPE_PUKE -> R.string.event_puke_type
TYPE_BATH -> R.string.event_bath_type
else -> R.string.event_unknown_type else -> R.string.event_unknown_type
} }
) )
@@ -122,7 +114,6 @@ class LunaEvent: Comparable<LunaEvent> {
TYPE_COLIC -> R.string.event_colic_desc TYPE_COLIC -> R.string.event_colic_desc
TYPE_FOOD -> R.string.event_food_desc TYPE_FOOD -> R.string.event_food_desc
TYPE_PUKE -> R.string.event_puke_desc TYPE_PUKE -> R.string.event_puke_desc
TYPE_BATH -> R.string.event_bath_desc
else -> R.string.event_unknown_desc else -> R.string.event_unknown_desc
} }
) )
@@ -140,7 +131,7 @@ class LunaEvent: Comparable<LunaEvent> {
} }
override fun toString(): String { 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 { override fun compareTo(other: LunaEvent): Int {

View File

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

View File

@@ -1,17 +1,12 @@
package utils package utils
import android.content.Context import android.content.Context
import android.os.Build
import android.text.format.DateFormat import android.text.format.DateFormat
import it.danieleverducci.lunatracker.R import it.danieleverducci.lunatracker.R
import java.util.Date import java.util.Date
class DateUtils { class DateUtils {
companion object { 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 { fun formatTimeDuration(context: Context, secondsDiff: Long): String {
var seconds = secondsDiff var seconds = secondsDiff
@@ -70,8 +65,7 @@ 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 { fun formatTimeAgo(context: Context, unixTime: Long): String {
val secondsDiff = (System.currentTimeMillis() / 1000) - unixTime val secondsDiff = (System.currentTimeMillis() / 1000) - unixTime
@@ -106,21 +100,5 @@ class DateUtils {
} }
return formattedTime.toString() return formattedTime.toString()
} }
/**
* Format time as localized string without seconds. E.g. "Sept 18, 2025, 03:36 PM".
* Used in the event detail dialog.
*/
fun formatDateTime(unixTime: Long): String {
val date = Date(unixTime * 1000)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val dateFormat = android.icu.text.DateFormat.getDateTimeInstance(android.icu.text.DateFormat.DEFAULT, android.icu.text.DateFormat.SHORT)
return dateFormat.format(date)
} else {
// fallback
val dateFormat = java.text.DateFormat.getDateTimeInstance()
return dateFormat.format(date)
}
}
} }
} }

View File

@@ -18,8 +18,8 @@ class NumericUtils (val context: Context) {
private fun isMetricSystem(): Boolean { private fun isMetricSystem(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val measurementSystem = LocaleData.getMeasurementSystem(ULocale.getDefault()) val measurementSystem = LocaleData.getMeasurementSystem(ULocale.getDefault())
return (measurementSystem == LocaleData.MeasurementSystem.SI) return (measurementSystem == LocaleData. MeasurementSystem.SI)
} else { } else {
val locale = context.resources.configuration.locale val locale = context.resources.configuration.locale
return when (locale.country) { return when (locale.country) {
// https://en.wikipedia.org/wiki/United_States_customary_units // https://en.wikipedia.org/wiki/United_States_customary_units
@@ -27,9 +27,9 @@ class NumericUtils (val context: Context) {
"US" -> false // US IMPERIAL "US" -> false // US IMPERIAL
// UK, Myanmar, Liberia, // UK, Myanmar, Liberia,
"GB", "MM", "LR" -> false // IMPERIAL "GB", "MM", "LR" -> false // IMPERIAL
else -> true // METRIC else -> true // UnitSystem.METRIC
} }
} }
} }
init { init {

View File

@@ -119,57 +119,28 @@
android:visibility="invisible"/> android:visibility="invisible"/>
</RadioGroup> </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="5dp"
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 <LinearLayout
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="20dp"> android:layout_marginTop="5dp"
android:layout_marginEnd="30dp">
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textStyle="bold" android:textStyle="bold"
android:text="@string/settings_no_breastfeeding" /> android:text="@string/no_breastfeeding" />
<com.google.android.material.switchmaterial.SwitchMaterial <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_no_breastfeeding" android:id="@+id/switch_no_breastfeeding"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_weight="1" /> android:layout_weight="1" />
</LinearLayout> </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 <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@@ -4,9 +4,7 @@
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"
android:paddingTop="20dp" android:padding="20dp">
android:paddingBottom="10dp"
android:paddingHorizontal="20dp">
<TextView <TextView
android:id="@+id/dialog_event_detail_type_emoji" android:id="@+id/dialog_event_detail_type_emoji"
@@ -63,14 +61,6 @@
</ScrollView> </ScrollView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:id="@+id/dialog_event_detail_type_signature"
android:layout_marginBottom="5dp"
android:visibility="gone"/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@@ -2,7 +2,7 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="10dp" android:padding="20dp"
android:background="@color/transparent"> android:background="@color/transparent">
<LinearLayout <LinearLayout
@@ -14,17 +14,27 @@
android:id="@+id/button_medicine" android:id="@+id/button_medicine"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="10dp" android:padding="20dp"
android:background="@drawable/dropdown_list_item_background" android:background="@drawable/dropdown_list_item_background"
style="@style/OverflowMenuText" style="@style/OverflowMenuText"
android:text="@string/overflow_event_medicine"/> 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/dropdown_list_item_background"
style="@style/OverflowMenuText"
android:text="@string/overflow_event_enema"/>
<TextView <TextView
android:id="@+id/button_note" android:id="@+id/button_note"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:padding="10dp" android:padding="20dp"
android:background="@drawable/dropdown_list_item_background" android:background="@drawable/dropdown_list_item_background"
style="@style/OverflowMenuText" style="@style/OverflowMenuText"
android:text="@string/overflow_event_note"/> android:text="@string/overflow_event_note"/>
@@ -34,7 +44,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:padding="10dp" android:padding="20dp"
android:background="@drawable/dropdown_list_item_background" android:background="@drawable/dropdown_list_item_background"
style="@style/OverflowMenuText" style="@style/OverflowMenuText"
android:text="@string/overflow_event_temperature"/> android:text="@string/overflow_event_temperature"/>
@@ -44,7 +54,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:padding="10dp" android:padding="20dp"
android:background="@drawable/dropdown_list_item_background" android:background="@drawable/dropdown_list_item_background"
style="@style/OverflowMenuText" style="@style/OverflowMenuText"
android:text="@string/overflow_event_puke"/> android:text="@string/overflow_event_puke"/>
@@ -54,7 +64,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:padding="10dp" android:padding="20dp"
android:background="@drawable/dropdown_list_item_background" android:background="@drawable/dropdown_list_item_background"
style="@style/OverflowMenuText" style="@style/OverflowMenuText"
android:text="@string/overflow_event_colic"/> android:text="@string/overflow_event_colic"/>
@@ -64,31 +74,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:padding="10dp" android:padding="20dp"
android:background="@drawable/dropdown_list_item_background" android:background="@drawable/dropdown_list_item_background"
style="@style/OverflowMenuText" style="@style/OverflowMenuText"
android:text="@string/overflow_event_scale"/> 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"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:padding="10dp"
android:background="@drawable/dropdown_list_item_background"
style="@style/OverflowMenuText"
android:text="@string/overflow_event_enema"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@@ -50,8 +50,9 @@
<string name="no_connection_go_to_settings">Einstellungen</string> <string name="no_connection_go_to_settings">Einstellungen</string>
<string name="no_connection_retry">Erneut versuchen</string> <string name="no_connection_retry">Erneut versuchen</string>
<string name="no_breastfeeding">Kein Stillen</string>
<string name="settings_title">Einstellungen</string> <string name="settings_title">Einstellungen</string>
<string name="settings_no_breastfeeding">Kein Stillen</string>
<string name="settings_storage">Speicherort für Daten auswählen</string> <string name="settings_storage">Speicherort für Daten auswählen</string>
<string name="settings_storage_local">Auf dem Gerät</string> <string name="settings_storage_local">Auf dem Gerät</string>
<string name="settings_storage_local_desc">Datenschutzfreundlichste Lösung: Deine Daten verlassen dein Gerät nicht</string> <string name="settings_storage_local_desc">Datenschutzfreundlichste Lösung: Deine Daten verlassen dein Gerät nicht</string>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string-array name="AmountLabels"> <string-array name="AmountLabels">
<item>@string/amount_little</item> <item>@string/amount_low</item>
<item>@string/amount_normal</item> <item>@string/amount_medium</item>
<item>@string/amount_plenty</item> <item>@string/amount_high</item>
</string-array> </string-array>
</resources> </resources>

View File

@@ -29,7 +29,6 @@
<string name="event_temperature_type" translatable="false">🌡️</string> <string name="event_temperature_type" translatable="false">🌡️</string>
<string name="event_colic_type" translatable="false">💨</string> <string name="event_colic_type" translatable="false">💨</string>
<string name="event_puke_type" translatable="false">🤮</string> <string name="event_puke_type" translatable="false">🤮</string>
<string name="event_bath_type" translatable="false">🛁</string>
<string name="event_unknown_type" translatable="false">\?</string> <string name="event_unknown_type" translatable="false">\?</string>
<string name="event_bottle_desc">Baby bottle</string> <string name="event_bottle_desc">Baby bottle</string>
@@ -46,7 +45,6 @@
<string name="event_temperature_desc">Temperature</string> <string name="event_temperature_desc">Temperature</string>
<string name="event_colic_desc">Gaseous colic</string> <string name="event_colic_desc">Gaseous colic</string>
<string name="event_puke_desc">Puke</string> <string name="event_puke_desc">Puke</string>
<string name="event_bath_desc">Bath</string>
<string name="event_unknown_desc"></string> <string name="event_unknown_desc"></string>
<string name="overflow_event_scale">⚖️ Weight</string> <string name="overflow_event_scale">⚖️ Weight</string>
@@ -56,7 +54,6 @@
<string name="overflow_event_temperature">🌡️ Temperature</string> <string name="overflow_event_temperature">🌡️ Temperature</string>
<string name="overflow_event_colic">💨 Gaseous colic</string> <string name="overflow_event_colic">💨 Gaseous colic</string>
<string name="overflow_event_puke">🤮 Puke</string> <string name="overflow_event_puke">🤮 Puke</string>
<string name="overflow_event_bath">🛁 Bath</string>
<string name="toast_event_added">Event logged</string> <string name="toast_event_added">Event logged</string>
<string name="toast_logbook_saved">Logbook saved</string> <string name="toast_logbook_saved">Logbook saved</string>
@@ -75,18 +72,18 @@
<string name="year_ago">year</string> <string name="year_ago">year</string>
<string name="years_ago">years</string> <string name="years_ago">years</string>
<string name="amount_little">Little</string> <string name="amount_low">Low</string>
<string name="amount_normal">Normal</string> <string name="amount_medium">Medium</string>
<string name="amount_plenty">Plenty</string> <string name="amount_high">High</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>
<string name="no_connection_go_to_settings">Settings</string> <string name="no_connection_go_to_settings">Settings</string>
<string name="no_connection_retry">Retry</string> <string name="no_connection_retry">Retry</string>
<string name="no_breastfeeding">No Breastfeeding</string>
<string name="settings_title">Settings</string> <string name="settings_title">Settings</string>
<string name="settings_signature">Signature</string>
<string name="settings_signature_desc">Attach a signature to each event you create and for others to see. Useful if multiple people add events.</string>
<string name="settings_storage">Choose where to save data</string> <string name="settings_storage">Choose where to save data</string>
<string name="settings_storage_local">On device</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> <string name="settings_storage_local_desc">Most privacy-friendly solution: data doesn\'t leave your device</string>
@@ -102,8 +99,6 @@
<string name="settings_webdav_error_generic">Error while trying to access WebDAV:</string> <string name="settings_webdav_error_generic">Error while trying to access WebDAV:</string>
<string name="settings_webdav_creation_error_generic">Unable to save a file on the WebDAV server:</string> <string name="settings_webdav_creation_error_generic">Unable to save a file on the WebDAV server:</string>
<string name="settings_webdav_creation_ok">Successfully connected with the WebDAV server</string> <string name="settings_webdav_creation_ok">Successfully connected with the WebDAV server</string>
<string name="settings_no_breastfeeding">No Breastfeeding</string>
<string name="settings_no_breastfeeding_desc">Hide the Breastfeeding buttons for when they are not needed.</string>
<string name="settings_json_error">There\'s a save file on the server, but it is corrupted or unreadable. Please delete it </string> <string name="settings_json_error">There\'s a save file on the server, but it is corrupted or unreadable. Please delete it </string>
<string name="settings_generic_error">Error: </string> <string name="settings_generic_error">Error: </string>
<string name="settings_webdav_upload_error">Error while uploading local logbook %1$s to webdav: %2$s</string> <string name="settings_webdav_upload_error">Error while uploading local logbook %1$s to webdav: %2$s</string>
@@ -138,7 +133,6 @@
<string name="dialog_event_detail_delete_button">Delete</string> <string name="dialog_event_detail_delete_button">Delete</string>
<string name="dialog_event_detail_quantity">Quantity</string> <string name="dialog_event_detail_quantity">Quantity</string>
<string name="dialog_event_detail_notes">Notes</string> <string name="dialog_event_detail_notes">Notes</string>
<string name="dialog_event_detail_signature">by %s</string>
<string name="dialog_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>