10 Commits

9 changed files with 296 additions and 102 deletions

View File

@ -12,8 +12,8 @@ android {
applicationId = "it.danieleverducci.lunatracker" applicationId = "it.danieleverducci.lunatracker"
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = 2 versionCode = 3
versionName = "0.3" versionName = "0.5"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@ -1,5 +1,6 @@
package it.danieleverducci.lunatracker package it.danieleverducci.lunatracker
import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
@ -48,7 +49,7 @@ class MainActivity : AppCompatActivity() {
val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false val DEBUG_CHECK_LOGBOOK_CONSISTENCY = false
} }
lateinit var logbook: Logbook var logbook: Logbook? = null
lateinit var adapter: LunaEventRecyclerAdapter lateinit var adapter: LunaEventRecyclerAdapter
lateinit var progressIndicator: LinearProgressIndicator lateinit var progressIndicator: LinearProgressIndicator
lateinit var buttonsContainer: ViewGroup lateinit var buttonsContainer: ViewGroup
@ -56,7 +57,8 @@ class MainActivity : AppCompatActivity() {
lateinit var handler: Handler lateinit var handler: Handler
var savingEvent = false var savingEvent = false
val updateListRunnable: Runnable = Runnable { val updateListRunnable: Runnable = Runnable {
loadLogbook() if (logbook != null)
loadLogbook(logbook!!.name)
handler.postDelayed(updateListRunnable, 1000*60) handler.postDelayed(updateListRunnable, 1000*60)
} }
var logbookRepo: LogbookRepository? = null var logbookRepo: LogbookRepository? = null
@ -83,7 +85,7 @@ class MainActivity : AppCompatActivity() {
recyclerView.adapter = adapter recyclerView.adapter = adapter
// Set listeners // Set listeners
findViewById<View>(R.id.logbooks_add_button).setOnClickListener { showAddLogbookDialog() } findViewById<View>(R.id.logbooks_add_button).setOnClickListener { showAddLogbookDialog(true) }
findViewById<View>(R.id.button_bottle).setOnClickListener { askBabyBottleContent() } findViewById<View>(R.id.button_bottle).setOnClickListener { askBabyBottleContent() }
findViewById<View>(R.id.button_scale).setOnClickListener { askWeightValue() } findViewById<View>(R.id.button_scale).setOnClickListener { askWeightValue() }
findViewById<View>(R.id.button_nipple_left).setOnClickListener { logEvent( findViewById<View>(R.id.button_nipple_left).setOnClickListener { logEvent(
@ -122,10 +124,11 @@ class MainActivity : AppCompatActivity() {
showSettings() showSettings()
}) })
findViewById<View>(R.id.button_no_connection_retry).setOnClickListener({ findViewById<View>(R.id.button_no_connection_retry).setOnClickListener({
loadLogbook() // 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({
loadLogbook() loadLogbookList()
}) })
} }
@ -136,8 +139,11 @@ class MainActivity : AppCompatActivity() {
fun showLogbook() { fun showLogbook() {
// Show logbook // Show logbook
if (logbook == null)
Log.w(TAG, "showLogbook(): logbook is null!")
adapter.items.clear() adapter.items.clear()
adapter.items.addAll(logbook.logs) adapter.items.addAll(logbook?.logs ?: listOf())
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
} }
@ -162,8 +168,13 @@ class MainActivity : AppCompatActivity() {
// Update list dates // Update list dates
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
// Reload data if (logbook != null) {
loadLogbookList() // Already running: reload data for currently selected logbook
loadLogbook(logbook!!.name)
} else {
// First start: load logbook list
loadLogbookList()
}
} }
override fun onStop() { override fun onStop() {
@ -283,7 +294,7 @@ class MainActivity : AppCompatActivity() {
} }
) )
d.setPositiveButton(R.string.trim_logbook_dialog_button_ok) { dialogInterface, i -> d.setPositiveButton(R.string.trim_logbook_dialog_button_ok) { dialogInterface, i ->
logbook.trim() logbook?.trim()
saveLogbook() saveLogbook()
} }
d.setNegativeButton(R.string.trim_logbook_dialog_button_cancel) { dialogInterface, i -> d.setNegativeButton(R.string.trim_logbook_dialog_button_cancel) { dialogInterface, i ->
@ -307,18 +318,28 @@ class MainActivity : AppCompatActivity() {
dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_notes).setText(event.notes) dialogView.findViewById<TextView>(R.id.dialog_event_detail_type_notes).setText(event.notes)
d.setView(dialogView) d.setView(dialogView)
d.setPositiveButton(android.R.string.ok) { dialogInterface, i -> dialogInterface.dismiss() } d.setPositiveButton(android.R.string.ok) { dialogInterface, i -> dialogInterface.dismiss() }
d.setNeutralButton(R.string.dialog_event_detail_delete_button) { dialogInterface, i -> deleteEvent(event) }
val alertDialog = d.create() val alertDialog = d.create()
alertDialog.show() alertDialog.show()
alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(ContextCompat.getColor(this, R.color.danger))
} }
fun showAddLogbookDialog() { fun showAddLogbookDialog(requestedByUser: Boolean) {
val d = AlertDialog.Builder(this) val d = AlertDialog.Builder(this)
d.setTitle(R.string.dialog_add_logbook_title) d.setTitle(R.string.dialog_add_logbook_title)
val dialogView = layoutInflater.inflate(R.layout.dialog_add_logbook, null) val dialogView = layoutInflater.inflate(R.layout.dialog_add_logbook, null)
dialogView.findViewById<TextView>(R.id.dialog_add_logbook_message).text = getString(
if (requestedByUser) R.string.dialog_add_logbook_message else R.string.dialog_add_logbook_message_intro
)
val logbookNameEditText = dialogView.findViewById<EditText>(R.id.dialog_add_logbook_logbookname) val logbookNameEditText = dialogView.findViewById<EditText>(R.id.dialog_add_logbook_logbookname)
d.setView(dialogView) d.setView(dialogView)
d.setPositiveButton(android.R.string.ok) { dialogInterface, i -> addLogbook(logbookNameEditText.text.toString()) } d.setPositiveButton(android.R.string.ok) { dialogInterface, i -> addLogbook(logbookNameEditText.text.toString()) }
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() } if (requestedByUser) {
d.setCancelable(true)
d.setNegativeButton(android.R.string.cancel) { dialogInterface, i -> dialogInterface.dismiss() }
} else {
d.setCancelable(false)
}
val alertDialog = d.create() val alertDialog = d.create()
alertDialog.show() alertDialog.show()
} }
@ -328,6 +349,11 @@ class MainActivity : AppCompatActivity() {
logbookRepo?.listLogbooks(this, object: LogbookListObtainedListener { logbookRepo?.listLogbooks(this, object: LogbookListObtainedListener {
override fun onLogbookListObtained(logbooksNames: ArrayList<String>) { override fun onLogbookListObtained(logbooksNames: ArrayList<String>) {
runOnUiThread({ runOnUiThread({
if (logbooksNames.isEmpty()) {
// First run, no logbook: create one
showAddLogbookDialog(false)
return@runOnUiThread
}
// Show logbooks dropdown // Show logbooks dropdown
val spinner = findViewById<Spinner>(R.id.logbooks_spinner) val spinner = findViewById<Spinner>(R.id.logbooks_spinner)
val sAdapter = ArrayAdapter<String>(this@MainActivity, android.R.layout.simple_spinner_item) val sAdapter = ArrayAdapter<String>(this@MainActivity, android.R.layout.simple_spinner_item)
@ -359,26 +385,87 @@ class MainActivity : AppCompatActivity() {
} }
override fun onIOError(error: IOException) { override fun onIOError(error: IOException) {
TODO("Not yet implemented") Log.e(TAG, "Unable to load logbooks list (IOError): $error")
runOnUiThread({
setLoading(false)
onRepoError(getString(R.string.settings_network_error) + error.toString())
})
} }
override fun onWebDAVError(error: SardineException) { override fun onWebDAVError(error: SardineException) {
TODO("Not yet implemented") Log.e(TAG, "Unable to load logbooks list (SardineException): $error")
runOnUiThread({
setLoading(false)
onRepoError(
if(error.toString().contains("401")) {
getString(R.string.settings_webdav_error_denied)
} else if(error.toString().contains("503")) {
getString(R.string.settings_webdav_error_server_offline)
} else {
getString(R.string.settings_webdav_error_generic) + error.toString()
}
)
})
} }
override fun onError(error: Exception) { override fun onError(error: Exception) {
TODO("Not yet implemented") Log.e(TAG, "Unable to load logbooks list: $error")
runOnUiThread({
setLoading(false)
onRepoError(getString(R.string.settings_generic_error) + error.toString())
})
} }
}) })
} }
fun addLogbook(logbookName: String) { fun addLogbook(logbookName: String) {
this.logbook = Logbook(logbookName) val newLogbook = Logbook(logbookName)
saveLogbook() setLoading(true)
loadLogbookList() // TODO: Does not reload logbooks buttons on top, why? logbookRepo?.saveLogbook(this, newLogbook, object: LogbookSavedListener{
override fun onLogbookSaved() {
Log.d(TAG, "Logbook $logbookName created")
runOnUiThread({
setLoading(false)
loadLogbookList()
Toast.makeText(this@MainActivity, getString(R.string.logbook_created) + logbookName, Toast.LENGTH_SHORT).show()
})
}
override fun onIOError(error: IOException) {
runOnUiThread({
onRepoError(getString(R.string.settings_network_error) + error.toString())
})
}
override fun onWebDAVError(error: SardineException) {
runOnUiThread({
onRepoError(
if(error.toString().contains("401")) {
getString(R.string.settings_webdav_error_denied)
} else if(error.toString().contains("503")) {
getString(R.string.settings_webdav_error_server_offline)
} else {
getString(R.string.settings_webdav_error_generic) + error.toString()
}
)
})
}
override fun onJSONError(error: JSONException) {
runOnUiThread({
onRepoError(getString(R.string.settings_json_error) + error.toString())
})
}
override fun onError(error: Exception) {
runOnUiThread({
onRepoError(getString(R.string.settings_generic_error) + error.toString())
})
}
})
} }
fun loadLogbook(name: String = LogbookRepository.DEFAULT_LOGBOOK_NAME) { fun loadLogbook(name: String) {
if (savingEvent) if (savingEvent)
return return
@ -397,7 +484,7 @@ class MainActivity : AppCompatActivity() {
showLogbook() showLogbook()
if (DEBUG_CHECK_LOGBOOK_CONSISTENCY) { if (DEBUG_CHECK_LOGBOOK_CONSISTENCY) {
for (e in logbook.logs) { for (e in logbook?.logs ?: listOf()) {
val em = e.getTypeEmoji(this@MainActivity) val em = e.getTypeEmoji(this@MainActivity)
if (em == getString(R.string.event_unknown_type)) { if (em == getString(R.string.event_unknown_type)) {
Log.e(TAG, "UNKNOWN: ${e.type}") Log.e(TAG, "UNKNOWN: ${e.type}")
@ -420,6 +507,8 @@ class MainActivity : AppCompatActivity() {
onRepoError( onRepoError(
if(error.toString().contains("401")) { if(error.toString().contains("401")) {
getString(R.string.settings_webdav_error_denied) getString(R.string.settings_webdav_error_denied)
} else if(error.toString().contains("503")) {
getString(R.string.settings_webdav_error_server_offline)
} else { } else {
getString(R.string.settings_webdav_error_generic) + error.toString() getString(R.string.settings_webdav_error_generic) + error.toString()
} }
@ -459,21 +548,37 @@ class MainActivity : AppCompatActivity() {
recyclerView.smoothScrollToPosition(0) recyclerView.smoothScrollToPosition(0)
setLoading(true) setLoading(true)
logbook.logs.add(0, event) logbook?.logs?.add(0, event)
saveLogbook(event) saveLogbook(event)
// Check logbook size to avoid OOM errors // Check logbook size to avoid OOM errors
if (logbook.isTooBig()) { if (logbook?.isTooBig() == true) {
askToTrimLogbook() askToTrimLogbook()
} }
} }
fun deleteEvent(event: LunaEvent) {
// Update view
savingEvent(true)
adapter.items.remove(event)
adapter.notifyDataSetChanged()
// Update data
setLoading(true)
logbook?.logs?.remove(event)
saveLogbook()
}
/** /**
* Saves the logbook. If saving while adding an event, please specify the event so in case * Saves the logbook. If saving while adding an event, please specify the event so in case
* of error can be removed from the list. * of error can be removed from the list.
*/ */
fun saveLogbook(lastEventAdded: LunaEvent? = null) { fun saveLogbook(lastEventAdded: LunaEvent? = null) {
logbookRepo?.saveLogbook(this, logbook, object: LogbookSavedListener{ if (logbook == null) {
Log.e(TAG, "Trying to save logbook, but logbook is null!")
return
}
logbookRepo?.saveLogbook(this, logbook!!, object: LogbookSavedListener{
override fun onLogbookSaved() { override fun onLogbookSaved() {
Log.d(TAG, "Logbook saved") Log.d(TAG, "Logbook saved")
runOnUiThread({ runOnUiThread({
@ -506,6 +611,8 @@ class MainActivity : AppCompatActivity() {
onRepoError( onRepoError(
if(error.toString().contains("401")) { if(error.toString().contains("401")) {
getString(R.string.settings_webdav_error_denied) getString(R.string.settings_webdav_error_denied)
} else if(error.toString().contains("503")) {
getString(R.string.settings_webdav_error_server_offline)
} else { } else {
getString(R.string.settings_webdav_error_generic) + error.toString() getString(R.string.settings_webdav_error_generic) + error.toString()
} }

View File

@ -8,7 +8,9 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.progressindicator.LinearProgressIndicator
import com.thegrizzlylabs.sardineandroid.impl.SardineException import com.thegrizzlylabs.sardineandroid.impl.SardineException
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.LogbookRepository import it.danieleverducci.lunatracker.repository.LogbookRepository
import it.danieleverducci.lunatracker.repository.WebDAVLogbookRepository import it.danieleverducci.lunatracker.repository.WebDAVLogbookRepository
import okio.IOException import okio.IOException
@ -73,13 +75,34 @@ open class SettingsActivity : AppCompatActivity() {
textViewWebDAVPass.text.toString() textViewWebDAVPass.text.toString()
) )
progressIndicator.visibility = View.VISIBLE progressIndicator.visibility = View.VISIBLE
webDAVLogbookRepo.createLogbook(this, LogbookRepository.DEFAULT_LOGBOOK_NAME, object: WebDAVLogbookRepository.LogbookCreatedListener{
override fun onLogbookCreated() { webDAVLogbookRepo.listLogbooks(this, object: LogbookListObtainedListener{
runOnUiThread({
progressIndicator.visibility = View.INVISIBLE override fun onLogbookListObtained(logbooksNames: ArrayList<String>) {
saveSettings() if (logbooksNames.isEmpty()) {
Toast.makeText(this@SettingsActivity, R.string.settings_webdav_creation_ok, Toast.LENGTH_SHORT).show() // TODO: Ask the user if he wants to upload the local ones or to create a new one
}) copyLocalLogbooksToWebdav(webDAVLogbookRepo, object: OnCopyLocalLogbooksToWebdavFinishedListener {
override fun onCopyLocalLogbooksToWebdavFinished(errors: String?) {
runOnUiThread({
progressIndicator.visibility = View.INVISIBLE
if (errors == null) {
saveSettings()
Toast.makeText(this@SettingsActivity, R.string.settings_webdav_creation_ok, Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this@SettingsActivity, errors, Toast.LENGTH_SHORT).show()
}
})
}
})
} else {
runOnUiThread({
progressIndicator.visibility = View.INVISIBLE
saveSettings()
Toast.makeText(this@SettingsActivity, R.string.settings_webdav_creation_ok, Toast.LENGTH_SHORT).show()
})
}
} }
override fun onIOError(error: IOException) { override fun onIOError(error: IOException) {
@ -100,6 +123,16 @@ open class SettingsActivity : AppCompatActivity() {
}) })
} }
override fun onError(error: Exception) {
runOnUiThread({
progressIndicator.visibility = View.INVISIBLE
Toast.makeText(this@SettingsActivity, getString(R.string.settings_generic_error) + error.toString(), Toast.LENGTH_SHORT).show()
})
}
})
/*webDAVLogbookRepo.createLogbook(this, LogbookRepository.DEFAULT_LOGBOOK_NAME, object: WebDAVLogbookRepository.LogbookCreatedListener{
override fun onJSONError(error: JSONException) { override fun onJSONError(error: JSONException) {
runOnUiThread({ runOnUiThread({
progressIndicator.visibility = View.INVISIBLE progressIndicator.visibility = View.INVISIBLE
@ -107,14 +140,8 @@ open class SettingsActivity : AppCompatActivity() {
}) })
} }
override fun onError(error: Exception) {
runOnUiThread({
progressIndicator.visibility = View.INVISIBLE
Toast.makeText(this@SettingsActivity, getString(R.string.settings_generic_error) + error.toString(), Toast.LENGTH_SHORT).show()
})
}
}) })*/
} }
fun saveSettings() { fun saveSettings() {
@ -130,4 +157,32 @@ open class SettingsActivity : AppCompatActivity() {
finish() finish()
} }
/**
* Copies the local logbooks to webdav.
* @return success
*/
private fun copyLocalLogbooksToWebdav(webDAVLogbookRepository: WebDAVLogbookRepository, listener: OnCopyLocalLogbooksToWebdavFinishedListener) {
Thread(Runnable {
var errors = StringBuilder()
val fileLogbookRepo = FileLogbookRepository()
val logbooks = fileLogbookRepo.getAllLogbooks(this)
for (logbook in logbooks) {
// Copy only if does not already exist
val error = webDAVLogbookRepository.uploadLogbookIfNotExists(this, logbook.name)
if (error != null) {
if (errors.isNotEmpty())
errors.append("\n")
errors.append(String.format(getString(R.string.settings_webdav_upload_error), logbook.name, error))
}
}
listener.onCopyLocalLogbooksToWebdavFinished(
if (errors.isEmpty()) null else errors.toString()
)
}).start()
}
private interface OnCopyLocalLogbooksToWebdavFinishedListener {
fun onCopyLocalLogbooksToWebdavFinished(errors: String?)
}
} }

View File

@ -70,6 +70,18 @@ class FileLogbookRepository: LogbookRepository {
context: Context, context: Context,
listener: LogbookListObtainedListener listener: LogbookListObtainedListener
) { ) {
listener.onLogbookListObtained(listLogbooks(context))
}
fun getAllLogbooks(context: Context): List<Logbook> {
val logbooks = arrayListOf<Logbook>()
for (logbookName in listLogbooks(context)) {
logbooks.add(loadLogbook(context, logbookName))
}
return logbooks
}
private fun listLogbooks(context: Context): ArrayList<String> {
val logbooksFileNames = context.getFilesDir().list(object: FilenameFilter { val logbooksFileNames = context.getFilesDir().list(object: FilenameFilter {
override fun accept(dir: File?, name: String?): Boolean { override fun accept(dir: File?, name: String?): Boolean {
if (name == null) if (name == null)
@ -80,8 +92,9 @@ class FileLogbookRepository: LogbookRepository {
} }
}) })
if (logbooksFileNames == null || logbooksFileNames.isEmpty()) if (logbooksFileNames == null || logbooksFileNames.isEmpty()) {
listener.onLogbookListObtained(arrayListOf()) return arrayListOf()
}
val logbooksNames = arrayListOf<String>() val logbooksNames = arrayListOf<String>()
logbooksFileNames.forEach { it -> logbooksFileNames.forEach { it ->
@ -89,7 +102,7 @@ class FileLogbookRepository: LogbookRepository {
it.replace("${FILE_NAME_START}_", "").replace(FILE_NAME_START, "").replace(FILE_NAME_END, "") it.replace("${FILE_NAME_START}_", "").replace(FILE_NAME_START, "").replace(FILE_NAME_END, "")
) )
} }
listener.onLogbookListObtained(logbooksNames) return logbooksNames
} }
private fun getFileName(name: String): String { private fun getFileName(name: String): String {

View File

@ -103,19 +103,32 @@ class WebDAVLogbookRepository(val webDavURL: String, val username: String, val p
listener: LogbookListObtainedListener listener: LogbookListObtainedListener
) { ) {
Thread(Runnable { Thread(Runnable {
val logbooksNames = arrayListOf<String>() try {
for (dr: DavResource in sardine.list(webDavURL)){ val logbooksNames = arrayListOf<String>()
if(!dr.name.startsWith(FILE_NAME_START)) for (dr: DavResource in sardine.list(webDavURL)){
continue if(!dr.name.startsWith(FILE_NAME_START))
if(!dr.name.endsWith(FILE_NAME_END)) continue
continue if(!dr.name.endsWith(FILE_NAME_END))
logbooksNames.add( continue
dr.name.replace("${FILE_NAME_START}_", "") logbooksNames.add(
.replace(FILE_NAME_START, "") dr.name.replace("${FILE_NAME_START}_", "")
.replace(FILE_NAME_END, "") .replace(FILE_NAME_START, "")
) .replace(FILE_NAME_END, "")
)
}
listener.onLogbookListObtained(logbooksNames)
} catch (e: SardineException) {
Log.e(TAG, e.toString())
listener.onWebDAVError(e)
} catch (e: IOException) {
Log.e(TAG, e.toString())
listener.onIOError(e)
} catch (e: SocketTimeoutException) {
Log.e(TAG, e.toString())
listener.onIOError(e)
} catch (e: Exception) {
listener.onError(e)
} }
listener.onLogbookListObtained(logbooksNames)
}).start() }).start()
} }
@ -137,47 +150,46 @@ class WebDAVLogbookRepository(val webDavURL: String, val username: String, val p
/** /**
* Connect to server and check if a logbook already exists. * Connect to server and check if a logbook already exists.
* If it does not exist, try to upload the local one (or create a new one). * If it does not exist, try to upload the local one.
* @return error, or null if no error
*/ */
fun createLogbook(context: Context, name: String, listener: LogbookCreatedListener) { fun uploadLogbookIfNotExists(context: Context, name: String): String? {
Thread(Runnable { val flr = FileLogbookRepository()
try { try {
loadLogbook(name) loadLogbook(name)
listener.onLogbookCreated() Log.d(TAG, "Logbook file $name already exist on the webDav share: will not overwrite it")
} catch (e: SardineException) { return null
if (e.toString().contains("404")) { } catch (e: SardineException) {
// Connection successful, but no existing save. Upload the local one. if (e.toString().contains("404")) {
try { // Connection successful, but logbook does not exist. Upload the local one.
val flr = FileLogbookRepository() try {
val logbook = flr.loadLogbook(context, name) val logbook = flr.loadLogbook(context, name)
saveLogbook(context, logbook) saveLogbook(context, logbook)
Log.d(TAG, "Local logbook file found, uploaded") Log.d(TAG, "Local logbook file $name found, uploaded")
listener.onLogbookCreated() return null
} catch (e: FileNotFoundException) { } catch (e: FileNotFoundException) {
Log.d(TAG, "No local logbook file found, uploading empty file") Log.e(TAG, "No local logbook file found, this should not happen!")
saveLogbook(context, Logbook(name)) return "No local logbook file found, app is in inconsistent state, please delete and reinstall it"
listener.onLogbookCreated() } catch (e: SardineException) {
} catch (e: SardineException) { Log.e(TAG, "Unable to upload logbook: $e")
Log.e(TAG, "Unable to upload logbook: $e") return e.toString()
listener.onWebDAVError(e)
}
} else {
Log.e(TAG, e.toString())
listener.onWebDAVError(e)
} }
} catch (e: IOException) { } else {
Log.e(TAG, e.toString()) Log.e(TAG, e.toString())
listener.onIOError(e) return e.toString()
} catch (e: SocketTimeoutException) {
Log.e(TAG, e.toString())
listener.onIOError(e)
} catch (e: JSONException) {
Log.e(TAG, e.toString())
listener.onJSONError(e)
} catch (e: Exception) {
listener.onError(e)
} }
}).start() } catch (e: IOException) {
Log.e(TAG, e.toString())
return e.toString()
} catch (e: SocketTimeoutException) {
Log.e(TAG, e.toString())
return e.toString()
} catch (e: JSONException) {
Log.e(TAG, e.toString())
return e.toString()
} catch (e: Exception) {
return e.toString()
}
} }
private fun getUrl(name: String): String { private fun getUrl(name: String): String {
@ -185,13 +197,4 @@ class WebDAVLogbookRepository(val webDavURL: String, val username: String, val p
Log.d(TAG, fileName) Log.d(TAG, fileName)
return "$webDavURL/$fileName" return "$webDavURL/$fileName"
} }
interface LogbookCreatedListener {
fun onLogbookCreated()
fun onIOError(error: okio.IOException)
fun onWebDAVError(error: SardineException)
fun onJSONError(error: JSONException)
fun onError(error: Exception)
}
} }

View File

@ -6,6 +6,7 @@
android:padding="20dp"> android:padding="20dp">
<TextView <TextView
android:id="@+id/dialog_add_logbook_message"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/dialog_add_logbook_message"/> android:text="@string/dialog_add_logbook_message"/>

View File

@ -61,11 +61,13 @@
<string name="settings_storage_dav_pass">Password</string> <string name="settings_storage_dav_pass">Password</string>
<string name="settings_network_error">Impossibile raggiungere il server: </string> <string name="settings_network_error">Impossibile raggiungere il server: </string>
<string name="settings_webdav_error_denied">Nome utente o password WebDAV sbagliati</string> <string name="settings_webdav_error_denied">Nome utente o password WebDAV sbagliati</string>
<string name="settings_webdav_error_server_offline">Il server WebDAV non è al momento disponibile</string>
<string name="settings_webdav_error_generic">Si è verificato un errore tentando di accedere al server WebDAV:</string> <string name="settings_webdav_error_generic">Si è verificato un errore tentando di accedere al server WebDAV:</string>
<string name="settings_webdav_creation_error_generic">Impossibile creare un file di salvataggio sul server WebDAV:</string> <string name="settings_webdav_creation_error_generic">Impossibile creare un file di salvataggio sul server WebDAV:</string>
<string name="settings_webdav_creation_ok">Connessione al server WebDAV avvenuta con successo</string> <string name="settings_webdav_creation_ok">Connessione al server WebDAV avvenuta con successo</string>
<string name="settings_json_error">Sul server esiste un salvataggio, ma è corrotto o illeggibile. Cancellare il file </string> <string name="settings_json_error">Sul server esiste un salvataggio, ma è corrotto o illeggibile. Cancellare il file </string>
<string name="settings_generic_error">Si è verificato un errore: </string> <string name="settings_generic_error">Si è verificato un errore: </string>
<string name="settings_webdav_upload_error">Errore durante l\'upload del logbook locale %1$s su webdav: %2$s</string>
<string name="trim_logbook_dialog_title">Il tuo diario è bello grande!</string> <string name="trim_logbook_dialog_title">Il tuo diario è bello grande!</string>
<string name="trim_logbook_dialog_message_local">Il file del tuo diario sta crescendo molto. Ti suggeriamo di cancellare gli eventi più vecchi per evitare problemi di memoria.</string> <string name="trim_logbook_dialog_message_local">Il file del tuo diario sta crescendo molto. Ti suggeriamo di cancellare gli eventi più vecchi per evitare problemi di memoria.</string>
@ -79,11 +81,15 @@
<string name="log_notes_dialog_note_hint">Inserisci le note</string> <string name="log_notes_dialog_note_hint">Inserisci le note</string>
<string name="dialog_event_detail_title">Dettaglio evento</string> <string name="dialog_event_detail_title">Dettaglio evento</string>
<string name="dialog_event_detail_save_button">Salva</string>
<string name="dialog_event_detail_delete_button">Elimina</string>
<string name="dialog_add_logbook_title">Aggiungi diario</string> <string name="dialog_add_logbook_title">Aggiungi diario</string>
<string name="dialog_add_logbook_logbookname">Nome del diario</string> <string name="dialog_add_logbook_logbookname">👶 Nome del diario</string>
<string name="dialog_add_logbook_message">Scrivi un nome per identificare questo diario. Comparirà in cima allo schermo, e se usi WebDAV sarà incluso anche nel nome del file di salvataggio.</string> <string name="dialog_add_logbook_message">Scrivi un nome per identificare questo diario. Comparirà in cima allo schermo, e se usi WebDAV sarà incluso anche nel nome del file di salvataggio.\nSe vuoi un\'icona, inserisci una emoji!</string>
<string name="dialog_add_logbook_message_intro">Benvenuto! Per usare quest\'app devi creare almeno un diario. Probabilmente vuoi chiamarlo col nome di tuo figlio.</string>
<string name="default_logbook_name">👶 Il mio primo diario</string> <string name="default_logbook_name">👶 Il mio primo diario</string>
<string name="logbook_created">Creato nuovo diario: </string>
</resources> </resources>

View File

@ -75,11 +75,13 @@
<string name="settings_storage_dav_pass">Password</string> <string name="settings_storage_dav_pass">Password</string>
<string name="settings_network_error">Unable to reach server: </string> <string name="settings_network_error">Unable to reach server: </string>
<string name="settings_webdav_error_denied">Wrong WebDAV user or password</string> <string name="settings_webdav_error_denied">Wrong WebDAV user or password</string>
<string name="settings_webdav_error_server_offline">WebDAV server is currently unavailable</string>
<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 WebDAV server</string> <string name="settings_webdav_creation_ok">Successfully connected with WebDAV server</string>
<string name="settings_json_error">There\'s a save file on the server, but is corrupted or unreadable. Please delete it </string> <string name="settings_json_error">There\'s a save file on the server, but 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="trim_logbook_dialog_title">Your logbook is pretty big!</string> <string name="trim_logbook_dialog_title">Your logbook is pretty big!</string>
<string name="trim_logbook_dialog_message_local">Your logbook file is growing a lot. We suggest trimming the oldest events to avoid crashes.</string> <string name="trim_logbook_dialog_message_local">Your logbook file is growing a lot. We suggest trimming the oldest events to avoid crashes.</string>
@ -102,11 +104,15 @@
<string name="measurement_unit_temperature_base_metric" translatable="false">°C</string> <string name="measurement_unit_temperature_base_metric" translatable="false">°C</string>
<string name="dialog_event_detail_title">Event detail</string> <string name="dialog_event_detail_title">Event detail</string>
<string name="dialog_event_detail_save_button">Save</string>
<string name="dialog_event_detail_delete_button">Delete</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>
<string name="dialog_add_logbook_message">Write a name to identify this logbook. This name will appear on top of the screen and, if you use WebDAV, will be in the save file name as well.</string> <string name="dialog_add_logbook_message">Write a name to identify this logbook. This name will appear on top of the screen and, if you use WebDAV, will be in the save file name as well.</string>
<string name="dialog_add_logbook_message_intro">Welcome! To use this app you need to create at least one logbook. You would probably want to call it with your child\'s name.</string>
<string name="default_logbook_name">👶 My first logbook</string> <string name="default_logbook_name">👶 My first logbook</string>
<string name="logbook_created">New logbook created: </string>
</resources> </resources>

View File

@ -0,0 +1,3 @@
Multiple children support
Fixed interface in devices with big font size