Compare commits
10 Commits
develop
...
d204b877f5
Author | SHA1 | Date | |
---|---|---|---|
d204b877f5 | |||
335c1d13af | |||
15dc8a1bef | |||
251ebd647a | |||
e09df3b0bf | |||
f36005de3b | |||
19abf20628 | |||
730ef95220 | |||
34aa092722 | |||
961e7b90e7 |
@@ -13,6 +13,7 @@ import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.NumberPicker
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.Spinner
|
||||
@@ -41,15 +42,14 @@ import okio.IOException
|
||||
import org.json.JSONException
|
||||
import utils.DateUtils
|
||||
import utils.NumericUtils
|
||||
import java.text.DateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
val TAG = "MainActivity"
|
||||
val UPDATE_EVERY_SECS: Long = 30
|
||||
val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false
|
||||
const val TAG = "MainActivity"
|
||||
const val UPDATE_EVERY_SECS: Long = 30
|
||||
const val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false
|
||||
}
|
||||
|
||||
var logbook: Logbook? = null
|
||||
@@ -58,6 +58,7 @@ class MainActivity : AppCompatActivity() {
|
||||
lateinit var buttonsContainer: ViewGroup
|
||||
lateinit var recyclerView: RecyclerView
|
||||
lateinit var handler: Handler
|
||||
var signature = ""
|
||||
var savingEvent = false
|
||||
val updateListRunnable: Runnable = Runnable {
|
||||
if (logbook != null && !pauseLogbookUpdate)
|
||||
@@ -113,24 +114,24 @@ class MainActivity : AppCompatActivity() {
|
||||
moreButton.setOnClickListener {
|
||||
showOverflowPopupWindow(moreButton)
|
||||
}
|
||||
findViewById<View>(R.id.button_no_connection_settings).setOnClickListener({
|
||||
findViewById<View>(R.id.button_no_connection_settings).setOnClickListener {
|
||||
showSettings()
|
||||
})
|
||||
findViewById<View>(R.id.button_settings).setOnClickListener({
|
||||
}
|
||||
findViewById<View>(R.id.button_settings).setOnClickListener {
|
||||
showSettings()
|
||||
})
|
||||
findViewById<View>(R.id.button_no_connection_retry).setOnClickListener({
|
||||
}
|
||||
findViewById<View>(R.id.button_no_connection_retry).setOnClickListener {
|
||||
// This may happen at start, when logbook is still null: better ask the logbook list
|
||||
loadLogbookList()
|
||||
})
|
||||
findViewById<View>(R.id.button_sync).setOnClickListener({
|
||||
}
|
||||
findViewById<View>(R.id.button_sync).setOnClickListener {
|
||||
loadLogbookList()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun setListAdapter(items: ArrayList<LunaEvent>) {
|
||||
val adapter = LunaEventRecyclerAdapter(this, items)
|
||||
adapter.onItemClickListener = object: LunaEventRecyclerAdapter.OnItemClickListener{
|
||||
adapter.onItemClickListener = object: LunaEventRecyclerAdapter.OnItemClickListener {
|
||||
override fun onItemClick(event: LunaEvent) {
|
||||
showEventDetailDialog(event, items)
|
||||
}
|
||||
@@ -169,6 +170,8 @@ class MainActivity : AppCompatActivity() {
|
||||
logbookRepo = FileLogbookRepository()
|
||||
}
|
||||
|
||||
signature = settingsRepository.loadSignature()
|
||||
|
||||
val noBreastfeeding = settingsRepository.loadNoBreastfeeding()
|
||||
findViewById<View>(R.id.layout_nipples).visibility = when (noBreastfeeding) {
|
||||
true -> View.GONE
|
||||
@@ -208,7 +211,7 @@ class MainActivity : AppCompatActivity() {
|
||||
numberPicker.wrapSelectorWheel = false
|
||||
numberPicker.value = localSettings.loadBabyBottleContent()
|
||||
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||
logEvent(LunaEvent(LunaEvent.TYPE_BABY_BOTTLE, numberPicker.value * 10))
|
||||
logEvent(LunaEvent(LunaEvent.TYPE_BABY_BOTTLE, signature, numberPicker.value * 10))
|
||||
localSettings.saveBabyBottleContent(numberPicker.value)
|
||||
}
|
||||
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
|
||||
@@ -227,7 +230,7 @@ class MainActivity : AppCompatActivity() {
|
||||
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||
val weight = weightET.text.toString().toIntOrNull()
|
||||
if (weight != null)
|
||||
logEvent(LunaEvent(LunaEvent.TYPE_WEIGHT, weight))
|
||||
logEvent(LunaEvent(LunaEvent.TYPE_WEIGHT, signature, weight))
|
||||
else
|
||||
Toast.makeText(this, R.string.toast_integer_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
@@ -253,7 +256,7 @@ class MainActivity : AppCompatActivity() {
|
||||
tempSlider.addOnChangeListener({s, v, b -> tempTextView.text = v.toString()})
|
||||
d.setPositiveButton(android.R.string.ok) { dialogInterface, i ->
|
||||
val temperature = (tempSlider.value * 10).toInt() // In tenth of a grade
|
||||
logEvent(LunaEvent(LunaEvent.TYPE_TEMPERATURE, temperature))
|
||||
logEvent(LunaEvent(LunaEvent.TYPE_TEMPERATURE, signature, temperature))
|
||||
}
|
||||
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
|
||||
val alertDialog = d.create()
|
||||
@@ -340,7 +343,6 @@ class MainActivity : AppCompatActivity() {
|
||||
fun showEventDetailDialog(event: LunaEvent, items: ArrayList<LunaEvent>) {
|
||||
// Do not update list while the detail is shown, to avoid changing the object below while it is changed by the user
|
||||
pauseLogbookUpdate = true
|
||||
val dateFormat = DateFormat.getDateTimeInstance()
|
||||
val d = AlertDialog.Builder(this)
|
||||
d.setTitle(R.string.dialog_event_detail_title)
|
||||
val dialogView = layoutInflater.inflate(R.layout.dialog_event_detail, null)
|
||||
@@ -352,8 +354,9 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
val currentDateTime = Calendar.getInstance()
|
||||
currentDateTime.time = Date(event.time * 1000)
|
||||
|
||||
val dateTextView = dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_date)
|
||||
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), dateFormat.format(currentDateTime.time))
|
||||
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
|
||||
dateTextView.setOnClickListener {
|
||||
// Show datetime picker
|
||||
val startYear = currentDateTime.get(Calendar.YEAR)
|
||||
@@ -366,11 +369,9 @@ class MainActivity : AppCompatActivity() {
|
||||
TimePickerDialog(this, { _, hour, minute ->
|
||||
val pickedDateTime = Calendar.getInstance()
|
||||
pickedDateTime.set(year, month, day, hour, minute)
|
||||
currentDateTime.time = pickedDateTime.time
|
||||
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), dateFormat.format(currentDateTime.time))
|
||||
|
||||
// Save event and move it to the right position in the logbook
|
||||
event.time = currentDateTime.time.time / 1000 // Seconds since epoch
|
||||
event.time = pickedDateTime.time.time / 1000 // Seconds since epoch
|
||||
dateTextView.text = String.format(getString(R.string.dialog_event_detail_datetime_icon), DateUtils.formatDateTime(event.time))
|
||||
logbook?.sort()
|
||||
recyclerView.adapter?.notifyDataSetChanged()
|
||||
saveLogbook()
|
||||
@@ -389,6 +390,14 @@ class MainActivity : AppCompatActivity() {
|
||||
pauseLogbookUpdate = false
|
||||
})
|
||||
|
||||
// show optional signature
|
||||
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_signature).text = event.signature
|
||||
dialogView.findViewById<LinearLayout>(R.id.dialog_event_signature_layout).visibility = if (event.signature.isNotEmpty()) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
// create next/previous links to events of the same type
|
||||
|
||||
val previousTextView = dialogView.findViewById<TextView>(R.id.dialog_event_previous)
|
||||
@@ -772,24 +781,30 @@ class MainActivity : AppCompatActivity() {
|
||||
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))
|
||||
askNotes(LunaEvent(LunaEvent.TYPE_MEDICINE, signature))
|
||||
dismiss()
|
||||
}
|
||||
contentView.findViewById<View>(R.id.button_enema).setOnClickListener({
|
||||
logEvent(LunaEvent(LunaEvent.TYPE_ENEMA))
|
||||
logEvent(LunaEvent(LunaEvent.TYPE_ENEMA, signature))
|
||||
dismiss()
|
||||
})
|
||||
contentView.findViewById<View>(R.id.button_note).setOnClickListener({
|
||||
askNotes(LunaEvent(LunaEvent.TYPE_NOTE))
|
||||
askNotes(LunaEvent(LunaEvent.TYPE_NOTE, signature))
|
||||
dismiss()
|
||||
})
|
||||
contentView.findViewById<View>(R.id.button_temperature).setOnClickListener({
|
||||
askTemperatureValue()
|
||||
dismiss()
|
||||
})
|
||||
contentView.findViewById<View>(R.id.button_puke).setOnClickListener({
|
||||
logEvent(
|
||||
LunaEvent(LunaEvent.TYPE_PUKE, signature)
|
||||
)
|
||||
dismiss()
|
||||
})
|
||||
contentView.findViewById<View>(R.id.button_colic).setOnClickListener({
|
||||
logEvent(
|
||||
LunaEvent(LunaEvent.TYPE_COLIC)
|
||||
LunaEvent(LunaEvent.TYPE_COLIC, signature)
|
||||
)
|
||||
dismiss()
|
||||
})
|
||||
@@ -797,6 +812,12 @@ class MainActivity : AppCompatActivity() {
|
||||
askWeightValue()
|
||||
dismiss()
|
||||
})
|
||||
contentView.findViewById<View>(R.id.button_bath).setOnClickListener({
|
||||
logEvent(
|
||||
LunaEvent(LunaEvent.TYPE_BATH, signature)
|
||||
)
|
||||
dismiss()
|
||||
})
|
||||
}.also { popupWindow ->
|
||||
popupWindow.setOnDismissListener({
|
||||
Handler(mainLooper).postDelayed({
|
||||
|
@@ -2,6 +2,7 @@ package it.danieleverducci.lunatracker
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.RadioButton
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
@@ -24,6 +25,7 @@ open class SettingsActivity : AppCompatActivity() {
|
||||
protected lateinit var textViewWebDAVPass: TextView
|
||||
protected lateinit var progressIndicator: LinearProgressIndicator
|
||||
protected lateinit var switchNoBreastfeeding: SwitchMaterial
|
||||
protected lateinit var textViewSignature: EditText
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -36,6 +38,7 @@ open class SettingsActivity : AppCompatActivity() {
|
||||
textViewWebDAVPass = findViewById(R.id.settings_data_webdav_pass)
|
||||
progressIndicator = findViewById(R.id.progress_indicator)
|
||||
switchNoBreastfeeding = findViewById(R.id.switch_no_breastfeeding)
|
||||
textViewSignature = findViewById(R.id.settings_signature)
|
||||
|
||||
findViewById<View>(R.id.settings_save).setOnClickListener({
|
||||
validateAndSave()
|
||||
@@ -52,18 +55,20 @@ open class SettingsActivity : AppCompatActivity() {
|
||||
val dataRepo = settingsRepository.loadDataRepository()
|
||||
val webDavCredentials = settingsRepository.loadWebdavCredentials()
|
||||
val noBreastfeeding = settingsRepository.loadNoBreastfeeding()
|
||||
val signature = settingsRepository.loadSignature()
|
||||
|
||||
when (dataRepo) {
|
||||
LocalSettingsRepository.DATA_REPO.LOCAL_FILE -> radioDataLocal.isChecked = true
|
||||
LocalSettingsRepository.DATA_REPO.WEBDAV -> radioDataWebDAV.isChecked = true
|
||||
}
|
||||
|
||||
textViewSignature.setText(signature)
|
||||
switchNoBreastfeeding.isChecked = noBreastfeeding
|
||||
|
||||
if (webDavCredentials != null) {
|
||||
textViewWebDAVUrl.setText(webDavCredentials[0])
|
||||
textViewWebDAVUser.setText(webDavCredentials[1])
|
||||
textViewWebDAVPass.setText(webDavCredentials[2])
|
||||
textViewWebDAVUrl.text = webDavCredentials[0]
|
||||
textViewWebDAVUser.text = webDavCredentials[1]
|
||||
textViewWebDAVPass.text = webDavCredentials[2]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +161,7 @@ open class SettingsActivity : AppCompatActivity() {
|
||||
else LocalSettingsRepository.DATA_REPO.LOCAL_FILE
|
||||
)
|
||||
settingsRepository.saveNoBreastfeeding(switchNoBreastfeeding.isChecked)
|
||||
settingsRepository.saveSignature(textViewSignature.text.toString())
|
||||
settingsRepository.saveWebdavCredentials(
|
||||
textViewWebDAVUrl.text.toString(),
|
||||
textViewWebDAVUser.text.toString(),
|
||||
@@ -170,7 +176,7 @@ open class SettingsActivity : AppCompatActivity() {
|
||||
*/
|
||||
private fun copyLocalLogbooksToWebdav(webDAVLogbookRepository: WebDAVLogbookRepository, listener: OnCopyLocalLogbooksToWebdavFinishedListener) {
|
||||
Thread(Runnable {
|
||||
var errors = StringBuilder()
|
||||
val errors = StringBuilder()
|
||||
val fileLogbookRepo = FileLogbookRepository()
|
||||
val logbooks = fileLogbookRepo.getAllLogbooks(this)
|
||||
for (logbook in logbooks) {
|
||||
|
@@ -53,7 +53,7 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
|
||||
holder.quantity.setTextColor(ContextCompat.getColor(context, R.color.textColor))
|
||||
// Contents
|
||||
holder.type.text = item.getTypeEmoji(context)
|
||||
holder.description.text = when(item.type) {
|
||||
holder.description.text = when (item.type) {
|
||||
LunaEvent.TYPE_MEDICINE -> item.notes
|
||||
LunaEvent.TYPE_NOTE -> item.notes
|
||||
LunaEvent.TYPE_CUSTOM -> item.notes
|
||||
|
@@ -28,6 +28,8 @@ class LunaEvent: Comparable<LunaEvent> {
|
||||
const val TYPE_COLIC = "COLIC"
|
||||
const val TYPE_TEMPERATURE = "TEMPERATURE"
|
||||
const val TYPE_FOOD = "FOOD"
|
||||
const val TYPE_PUKE = "PUKE"
|
||||
const val TYPE_BATH = "BATH"
|
||||
}
|
||||
|
||||
private val jo: JSONObject
|
||||
@@ -53,6 +55,12 @@ class LunaEvent: Comparable<LunaEvent> {
|
||||
set(value) {
|
||||
jo.put("notes", value)
|
||||
}
|
||||
var signature: String
|
||||
get(): String = jo.optString("signature")
|
||||
set(value) {
|
||||
if (value.isNotEmpty())
|
||||
jo.put("signature", value)
|
||||
}
|
||||
|
||||
constructor(jo: JSONObject) {
|
||||
this.jo = jo
|
||||
@@ -61,16 +69,18 @@ class LunaEvent: Comparable<LunaEvent> {
|
||||
throw IllegalArgumentException("JSONObject is not a LunaEvent")
|
||||
}
|
||||
|
||||
constructor(type: String) {
|
||||
constructor(type: String, signature: String) {
|
||||
this.jo = JSONObject()
|
||||
this.time = System.currentTimeMillis() / 1000
|
||||
this.signature = signature
|
||||
this.type = type
|
||||
}
|
||||
|
||||
constructor(type: String, quantity: Int) {
|
||||
constructor(type: String, signature: String, quantity: Int) {
|
||||
this.jo = JSONObject()
|
||||
this.time = System.currentTimeMillis() / 1000
|
||||
this.type = type
|
||||
this.signature = signature
|
||||
this.quantity = quantity
|
||||
}
|
||||
|
||||
@@ -90,6 +100,8 @@ class LunaEvent: Comparable<LunaEvent> {
|
||||
TYPE_TEMPERATURE -> R.string.event_temperature_type
|
||||
TYPE_COLIC -> R.string.event_colic_type
|
||||
TYPE_FOOD -> R.string.event_food_type
|
||||
TYPE_PUKE -> R.string.event_puke_type
|
||||
TYPE_BATH -> R.string.event_bath_type
|
||||
else -> R.string.event_unknown_type
|
||||
}
|
||||
)
|
||||
@@ -111,6 +123,8 @@ class LunaEvent: Comparable<LunaEvent> {
|
||||
TYPE_TEMPERATURE -> R.string.event_temperature_desc
|
||||
TYPE_COLIC -> R.string.event_colic_desc
|
||||
TYPE_FOOD -> R.string.event_food_desc
|
||||
TYPE_PUKE -> R.string.event_puke_desc
|
||||
TYPE_BATH -> R.string.event_bath_desc
|
||||
else -> R.string.event_unknown_desc
|
||||
}
|
||||
)
|
||||
@@ -128,7 +142,7 @@ class LunaEvent: Comparable<LunaEvent> {
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "${type} qty: $quantity time: ${Date(time * 1000)}"
|
||||
return "$type qty: $quantity time: ${Date(time * 1000)}"
|
||||
}
|
||||
|
||||
override fun compareTo(other: LunaEvent): Int {
|
||||
|
@@ -13,9 +13,9 @@ import java.io.FilenameFilter
|
||||
|
||||
class FileLogbookRepository: LogbookRepository {
|
||||
companion object {
|
||||
val TAG = "FileLogbookRepository"
|
||||
val FILE_NAME_START = "data"
|
||||
val FILE_NAME_END = ".json"
|
||||
const val TAG = "FileLogbookRepository"
|
||||
const val FILE_NAME_START = "data"
|
||||
const val FILE_NAME_END = ".json"
|
||||
}
|
||||
|
||||
override fun loadLogbook(context: Context, name: String, listener: LogbookLoadedListener) {
|
||||
@@ -32,7 +32,7 @@ class FileLogbookRepository: LogbookRepository {
|
||||
fun loadLogbook(context: Context, name: String): Logbook {
|
||||
val logbook = Logbook(name)
|
||||
val fileName = getFileName(name)
|
||||
val file = File(context.getFilesDir(), fileName)
|
||||
val file = File(context.filesDir, fileName)
|
||||
val json = FileInputStream(file).bufferedReader().use { it.readText() }
|
||||
val ja = JSONArray(json)
|
||||
for (i in 0 until ja.length()) {
|
||||
@@ -58,7 +58,7 @@ class FileLogbookRepository: LogbookRepository {
|
||||
|
||||
fun saveLogbook(context: Context, logbook: Logbook) {
|
||||
val fileName = getFileName(logbook.name)
|
||||
val file = File(context.getFilesDir(), fileName)
|
||||
val file = File(context.filesDir, fileName)
|
||||
val ja = JSONArray()
|
||||
for (l in logbook.logs) {
|
||||
ja.put(l.toJson())
|
||||
@@ -82,7 +82,7 @@ class FileLogbookRepository: LogbookRepository {
|
||||
}
|
||||
|
||||
private fun listLogbooks(context: Context): ArrayList<String> {
|
||||
val logbooksFileNames = context.getFilesDir().list(object: FilenameFilter {
|
||||
val logbooksFileNames = context.filesDir.list(object: FilenameFilter {
|
||||
override fun accept(dir: File?, name: String?): Boolean {
|
||||
if (name == null)
|
||||
return false
|
||||
|
@@ -7,13 +7,14 @@ import androidx.core.content.edit
|
||||
|
||||
class LocalSettingsRepository(val context: Context) {
|
||||
companion object {
|
||||
val SHARED_PREFS_FILE_NAME = "lunasettings"
|
||||
val SHARED_PREFS_BB_CONTENT = "bbcontent"
|
||||
val SHARED_PREFS_DATA_REPO = "data_repo"
|
||||
val SHARED_PREFS_DAV_URL = "webdav_url"
|
||||
val SHARED_PREFS_DAV_USER = "webdav_user"
|
||||
val SHARED_PREFS_DAV_PASS = "webdav_password"
|
||||
val SHARED_PREFS_NO_BREASTFEEDING = "no_breastfeeding"
|
||||
const val SHARED_PREFS_FILE_NAME = "lunasettings"
|
||||
const val SHARED_PREFS_BB_CONTENT = "bbcontent"
|
||||
const val SHARED_PREFS_DATA_REPO = "data_repo"
|
||||
const val SHARED_PREFS_DAV_URL = "webdav_url"
|
||||
const val SHARED_PREFS_DAV_USER = "webdav_user"
|
||||
const val SHARED_PREFS_DAV_PASS = "webdav_password"
|
||||
const val SHARED_PREFS_NO_BREASTFEEDING = "no_breastfeeding"
|
||||
const val SHARED_PREFS_SIGNATURE = "signature"
|
||||
}
|
||||
enum class DATA_REPO {LOCAL_FILE, WEBDAV}
|
||||
val sharedPreferences: SharedPreferences
|
||||
@@ -23,15 +24,23 @@ class LocalSettingsRepository(val context: Context) {
|
||||
}
|
||||
|
||||
fun saveBabyBottleContent(content: Int) {
|
||||
sharedPreferences.edit().putInt(SHARED_PREFS_BB_CONTENT, content).apply()
|
||||
sharedPreferences.edit { putInt(SHARED_PREFS_BB_CONTENT, content) }
|
||||
}
|
||||
|
||||
fun loadBabyBottleContent(): Int {
|
||||
return sharedPreferences.getInt(SHARED_PREFS_BB_CONTENT, 1)
|
||||
}
|
||||
|
||||
fun saveSignature(content: String) {
|
||||
sharedPreferences.edit { putString(SHARED_PREFS_SIGNATURE, content) }
|
||||
}
|
||||
|
||||
fun loadSignature(): String {
|
||||
return sharedPreferences.getString(SHARED_PREFS_SIGNATURE, "") ?: ""
|
||||
}
|
||||
|
||||
fun saveNoBreastfeeding(content: Boolean) {
|
||||
sharedPreferences.edit().putBoolean(SHARED_PREFS_NO_BREASTFEEDING, content).apply()
|
||||
sharedPreferences.edit { putBoolean(SHARED_PREFS_NO_BREASTFEEDING, content) }
|
||||
}
|
||||
|
||||
fun loadNoBreastfeeding(): Boolean {
|
||||
@@ -39,15 +48,15 @@ class LocalSettingsRepository(val context: Context) {
|
||||
}
|
||||
|
||||
fun saveDataRepository(repo: DATA_REPO) {
|
||||
val spe = sharedPreferences.edit()
|
||||
spe.putString(
|
||||
SHARED_PREFS_DATA_REPO,
|
||||
when (repo) {
|
||||
DATA_REPO.WEBDAV -> "webdav"
|
||||
DATA_REPO.LOCAL_FILE -> "localfile"
|
||||
}
|
||||
)
|
||||
spe.commit()
|
||||
sharedPreferences.edit(commit = true) {
|
||||
putString(
|
||||
SHARED_PREFS_DATA_REPO,
|
||||
when (repo) {
|
||||
DATA_REPO.WEBDAV -> "webdav"
|
||||
DATA_REPO.LOCAL_FILE -> "localfile"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun loadDataRepository(): DATA_REPO {
|
||||
@@ -60,11 +69,11 @@ class LocalSettingsRepository(val context: Context) {
|
||||
}
|
||||
|
||||
fun saveWebdavCredentials(url: String, username: String, password: String) {
|
||||
val spe = sharedPreferences.edit()
|
||||
spe.putString(SHARED_PREFS_DAV_URL, url)
|
||||
spe.putString(SHARED_PREFS_DAV_USER, username)
|
||||
spe.putString(SHARED_PREFS_DAV_PASS, password)
|
||||
spe.commit()
|
||||
sharedPreferences.edit(commit = true) {
|
||||
putString(SHARED_PREFS_DAV_URL, url)
|
||||
putString(SHARED_PREFS_DAV_USER, username)
|
||||
putString(SHARED_PREFS_DAV_PASS, password)
|
||||
}
|
||||
}
|
||||
|
||||
fun loadWebdavCredentials(): Array<String>? {
|
||||
|
@@ -5,8 +5,13 @@ import android.text.format.DateFormat
|
||||
import it.danieleverducci.lunatracker.R
|
||||
import java.util.Date
|
||||
|
||||
|
||||
class DateUtils {
|
||||
companion object {
|
||||
/**
|
||||
* Format time duration in seconds as e.g. "2 hours, 1 min".
|
||||
* Used for the duration to the next/previous event in the event details dialog.
|
||||
*/
|
||||
fun formatTimeDuration(context: Context, secondsDiff: Long): String {
|
||||
var seconds = secondsDiff
|
||||
|
||||
@@ -65,7 +70,8 @@ class DateUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the provided unix timestamp in a string like "3 hours, 26 minutes ago)
|
||||
* Formats the provided unix timestamp in a string like "3 hours, 26 minutes ago".
|
||||
* Used for the event list.
|
||||
*/
|
||||
fun formatTimeAgo(context: Context, unixTime: Long): String {
|
||||
val secondsDiff = (System.currentTimeMillis() / 1000) - unixTime
|
||||
@@ -100,5 +106,17 @@ class DateUtils {
|
||||
}
|
||||
return formattedTime.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time as localized string without seconds. E.g. "28 Sept 03:36:00".
|
||||
* The seconds are set to 0 since they are distracting and not relevant.
|
||||
* Used in the event detail dialog.
|
||||
*/
|
||||
fun formatDateTime(unixTime: Long): String {
|
||||
val roundedUnixTime = unixTime - (unixTime % 60)
|
||||
val date = Date(roundedUnixTime * 1000)
|
||||
val dateFormat = java.text.DateFormat.getDateTimeInstance()
|
||||
return dateFormat.format(date)
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@ package utils
|
||||
import android.content.Context
|
||||
import android.icu.util.LocaleData
|
||||
import android.icu.util.ULocale
|
||||
import android.os.Build
|
||||
import it.danieleverducci.lunatracker.R
|
||||
import it.danieleverducci.lunatracker.entities.LunaEvent
|
||||
import java.text.NumberFormat
|
||||
@@ -14,29 +15,45 @@ class NumericUtils (val context: Context) {
|
||||
val measurement_unit_weight_tiny: String
|
||||
val measurement_unit_temperature_base: String
|
||||
|
||||
private fun isMetricSystem(): Boolean {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
val measurementSystem = LocaleData.getMeasurementSystem(ULocale.getDefault())
|
||||
return (measurementSystem == LocaleData.MeasurementSystem.SI)
|
||||
} else {
|
||||
val locale = context.resources.configuration.locale
|
||||
return when (locale.country) {
|
||||
// https://en.wikipedia.org/wiki/United_States_customary_units
|
||||
// https://en.wikipedia.org/wiki/Imperial_units
|
||||
"US" -> false // US IMPERIAL
|
||||
// UK, Myanmar, Liberia,
|
||||
"GB", "MM", "LR" -> false // IMPERIAL
|
||||
else -> true // METRIC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
this.numberFormat = NumberFormat.getInstance()
|
||||
val measurementSystem = LocaleData.getMeasurementSystem(ULocale.getDefault())
|
||||
this.measurement_unit_liquid_base = context.getString(
|
||||
if (measurementSystem == LocaleData. MeasurementSystem.SI)
|
||||
if (isMetricSystem())
|
||||
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)
|
||||
if (isMetricSystem())
|
||||
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)
|
||||
if (isMetricSystem())
|
||||
R.string.measurement_unit_weight_tiny_metric
|
||||
else
|
||||
R.string.measurement_unit_weight_tiny_imperial
|
||||
)
|
||||
this.measurement_unit_temperature_base = context.getString(
|
||||
if (measurementSystem == LocaleData. MeasurementSystem.SI)
|
||||
if (isMetricSystem())
|
||||
R.string.measurement_unit_temperature_base_metric
|
||||
else
|
||||
R.string.measurement_unit_temperature_base_imperial
|
||||
@@ -45,11 +62,13 @@ class NumericUtils (val context: Context) {
|
||||
|
||||
fun formatEventQuantity(item: LunaEvent): String {
|
||||
val formatted = StringBuilder()
|
||||
if ((item.quantity ?: 0) > 0) {
|
||||
if (item.type == LunaEvent.TYPE_TEMPERATURE)
|
||||
formatted.append((item.quantity / 10.0f).toString())
|
||||
else
|
||||
formatted.append(item.quantity)
|
||||
if (item.quantity > 0) {
|
||||
formatted.append(when (item.type) {
|
||||
LunaEvent.TYPE_TEMPERATURE ->
|
||||
(item.quantity / 10.0f).toString()
|
||||
else ->
|
||||
item.quantity
|
||||
})
|
||||
|
||||
formatted.append(" ")
|
||||
formatted.append(
|
||||
@@ -70,10 +89,9 @@ class NumericUtils (val context: Context) {
|
||||
* @return min, max, normal
|
||||
*/
|
||||
fun getValidEventQuantityRange(lunaEventType: String): Triple<Int, Int, Int>? {
|
||||
val measurementSystem = LocaleData.getMeasurementSystem(ULocale.getDefault())
|
||||
return when (lunaEventType) {
|
||||
LunaEvent.TYPE_TEMPERATURE -> {
|
||||
if (measurementSystem == LocaleData. MeasurementSystem.SI)
|
||||
if (isMetricSystem())
|
||||
Triple(
|
||||
context.resources.getInteger(R.integer.human_body_temp_min_metric),
|
||||
context.resources.getInteger(R.integer.human_body_temp_max_metric),
|
||||
|
@@ -119,28 +119,57 @@
|
||||
android:visibility="invisible"/>
|
||||
</RadioGroup>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/settings_signature" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/settings_signature"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:inputType="textEmailAddress"
|
||||
android:background="@drawable/textview_background"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/settings_signature_desc"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginEnd="30dp">
|
||||
android:layout_marginTop="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/no_breastfeeding" />
|
||||
android:text="@string/settings_no_breastfeeding" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/switch_no_breastfeeding"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/settings_no_breastfeeding_desc"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@@ -89,4 +89,25 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dialog_event_signature_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:text="@string/dialog_event_detail_signature"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialog_event_detail_type_signature"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:text="" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@@ -2,7 +2,7 @@
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="20dp"
|
||||
android:padding="10dp"
|
||||
android:background="@color/transparent">
|
||||
|
||||
<LinearLayout
|
||||
@@ -14,27 +14,17 @@
|
||||
android:id="@+id/button_medicine"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="20dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/dropdown_list_item_background"
|
||||
style="@style/OverflowMenuText"
|
||||
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
|
||||
android:id="@+id/button_note"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="20dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/dropdown_list_item_background"
|
||||
style="@style/OverflowMenuText"
|
||||
android:text="@string/overflow_event_note"/>
|
||||
@@ -44,17 +34,27 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="20dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/dropdown_list_item_background"
|
||||
style="@style/OverflowMenuText"
|
||||
android:text="@string/overflow_event_temperature"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_puke"
|
||||
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_puke"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_colic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="20dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/dropdown_list_item_background"
|
||||
style="@style/OverflowMenuText"
|
||||
android:text="@string/overflow_event_colic"/>
|
||||
@@ -64,11 +64,31 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="20dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/dropdown_list_item_background"
|
||||
style="@style/OverflowMenuText"
|
||||
android:text="@string/overflow_event_scale"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_bath"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/dropdown_list_item_background"
|
||||
style="@style/OverflowMenuText"
|
||||
android:text="@string/overflow_event_bath"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_enema"
|
||||
android:layout_width="match_parent"
|
||||
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>
|
||||
|
||||
</ScrollView>
|
@@ -25,6 +25,8 @@
|
||||
<string name="event_note_type" translatable="false">📝</string>
|
||||
<string name="event_temperature_type" translatable="false">🌡️</string>
|
||||
<string name="event_colic_type" translatable="false">💨</string>
|
||||
<string name="event_puke_type" translatable="false">🤮</string>
|
||||
<string name="event_bath_type" translatable="false">🛁</string>
|
||||
<string name="event_unknown_type" translatable="false">\?</string>
|
||||
|
||||
<string name="event_bottle_desc">Baby bottle</string>
|
||||
@@ -40,6 +42,8 @@
|
||||
<string name="event_note_desc">Note</string>
|
||||
<string name="event_temperature_desc">Temperature</string>
|
||||
<string name="event_colic_desc">Gaseous colic</string>
|
||||
<string name="event_puke_desc">Puke</string>
|
||||
<string name="event_bath_desc">Bath</string>
|
||||
<string name="event_unknown_desc"></string>
|
||||
|
||||
<string name="overflow_event_scale">⚖️ Weight</string>
|
||||
@@ -48,6 +52,8 @@
|
||||
<string name="overflow_event_note">📝 Note</string>
|
||||
<string name="overflow_event_temperature">🌡️ Temperature</string>
|
||||
<string name="overflow_event_colic">💨 Gaseous colic</string>
|
||||
<string name="overflow_event_puke">🤮 Puke</string>
|
||||
<string name="overflow_event_bath">🛁 Bath</string>
|
||||
|
||||
<string name="toast_event_added">Event logged</string>
|
||||
<string name="toast_logbook_saved">Logbook saved</string>
|
||||
@@ -71,9 +77,9 @@
|
||||
<string name="no_connection_go_to_settings">Settings</string>
|
||||
<string name="no_connection_retry">Retry</string>
|
||||
|
||||
<string name="no_breastfeeding">No Breastfeeding</string>
|
||||
|
||||
<string name="settings_title">Settings</string>
|
||||
<string name="settings_signature">Signature</string>
|
||||
<string name="settings_signature_desc">Attach a signature to each event your create and for others to see. Useful if multiple people add events.</string>
|
||||
<string name="settings_storage">Choose where to save data</string>
|
||||
<string name="settings_storage_local">On device</string>
|
||||
<string name="settings_storage_local_desc">Most privacy-friendly solution: data doesn\'t leave your device</string>
|
||||
@@ -89,6 +95,8 @@
|
||||
<string name="settings_webdav_error_generic">Error while trying to access WebDAV:</string>
|
||||
<string name="settings_webdav_creation_error_generic">Unable to save a file on the WebDAV server:</string>
|
||||
<string name="settings_webdav_creation_ok">Successfully connected with the WebDAV server</string>
|
||||
<string name="settings_no_breastfeeding">No Breastfeeding</string>
|
||||
<string name="settings_no_breastfeeding_desc">Hide the Breastfeeding buttons for when they are not needed.</string>
|
||||
<string name="settings_json_error">There\'s a save file on the server, but it is corrupted or unreadable. Please delete it </string>
|
||||
<string name="settings_generic_error">Error: </string>
|
||||
<string name="settings_webdav_upload_error">Error while uploading local logbook %1$s to webdav: %2$s</string>
|
||||
@@ -123,6 +131,7 @@
|
||||
<string name="dialog_event_detail_delete_button">Delete</string>
|
||||
<string name="dialog_event_detail_quantity">Quantity</string>
|
||||
<string name="dialog_event_detail_notes">Notes</string>
|
||||
<string name="dialog_event_detail_signature">Created By</string>
|
||||
|
||||
<string name="dialog_add_logbook_title">Add logbook</string>
|
||||
<string name="dialog_add_logbook_logbookname">👶 Logbook name</string>
|
||||
|
Reference in New Issue
Block a user