diff --git a/app/src/main/java/it/danieleverducci/lunatracker/MainActivity.kt b/app/src/main/java/it/danieleverducci/lunatracker/MainActivity.kt
index 4c03fe9..4474daa 100644
--- a/app/src/main/java/it/danieleverducci/lunatracker/MainActivity.kt
+++ b/app/src/main/java/it/danieleverducci/lunatracker/MainActivity.kt
@@ -14,10 +14,12 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.thegrizzlylabs.sardineandroid.impl.SardineException
+import it.danieleverducci.lunatracker.SettingsActivity
import it.danieleverducci.lunatracker.adapters.LunaEventRecyclerAdapter
import it.danieleverducci.lunatracker.entities.Logbook
import it.danieleverducci.lunatracker.entities.LunaEvent
import it.danieleverducci.lunatracker.entities.LunaEventType
+import it.danieleverducci.lunatracker.repository.FileLogbookRepository
import it.danieleverducci.lunatracker.repository.LocalSettingsRepository
import it.danieleverducci.lunatracker.repository.LogbookLoadedListener
import it.danieleverducci.lunatracker.repository.LogbookRepository
@@ -42,7 +44,7 @@ class MainActivity : AppCompatActivity() {
loadLogbook()
handler.postDelayed(updateListRunnable, 1000*60)
}
- lateinit var logbookRepo: LogbookRepository
+ var logbookRepo: LogbookRepository? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -52,11 +54,6 @@ class MainActivity : AppCompatActivity() {
if (webDavCredentials == null) {
TODO("Not supported ATM (TODO: apply settings)")
}
- logbookRepo = WebDAVLogbookRepository( // TODO: support also FileLogbookRepository
- webDavCredentials[0],
- webDavCredentials[1],
- webDavCredentials[2]
- )
handler = Handler(mainLooper)
adapter = LunaEventRecyclerAdapter(this)
@@ -114,7 +111,6 @@ class MainActivity : AppCompatActivity() {
fun showSettings() {
val i = Intent(this, SettingsActivity::class.java)
startActivity(i)
-
}
fun showLogbook() {
@@ -127,6 +123,21 @@ class MainActivity : AppCompatActivity() {
override fun onStart() {
super.onStart()
+ val settingsRepository = LocalSettingsRepository(this)
+ if (settingsRepository.loadDataRepository() == LocalSettingsRepository.DATA_REPO.WEBDAV) {
+ val webDavCredentials = settingsRepository.loadWebdavCredentials()
+ if (webDavCredentials == null) {
+ throw IllegalStateException("Corrupted local settings: repo is webdav, but no webdav login data saved")
+ }
+ logbookRepo = WebDAVLogbookRepository(
+ webDavCredentials[0],
+ webDavCredentials[1],
+ webDavCredentials[2]
+ )
+ } else {
+ logbookRepo = FileLogbookRepository()
+ }
+
// Update list dates
adapter.notifyDataSetChanged()
@@ -190,7 +201,7 @@ class MainActivity : AppCompatActivity() {
// Load data
progressIndicator.visibility = View.VISIBLE
- logbookRepo.loadLogbook(this, object: LogbookLoadedListener{
+ logbookRepo?.loadLogbook(this, object: LogbookLoadedListener{
override fun onLogbookLoaded(lb: Logbook) {
runOnUiThread({
progressIndicator.visibility = View.INVISIBLE
@@ -201,16 +212,37 @@ class MainActivity : AppCompatActivity() {
}
override fun onIOError(error: IOException) {
- onRepoError(error) // TODO: Meaningful message
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ Toast.makeText(this@MainActivity, getString(R.string.settings_network_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ })
}
override fun onWebDAVError(error: SardineException) {
- onRepoError(error) // TODO: Meaningful message
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ if(error.toString().contains("401")) {
+ Toast.makeText(this@MainActivity, getString(R.string.settings_webdav_error_denied), Toast.LENGTH_SHORT).show()
+ } else {
+ Toast.makeText(this@MainActivity, getString(R.string.settings_webdav_error_generic) + error.toString(), Toast.LENGTH_SHORT).show()
+ }
+ })
}
override fun onJSONError(error: JSONException) {
- onRepoError(error) // TODO: Meaningful message
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ Toast.makeText(this@MainActivity, getString(R.string.settings_json_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ })
}
+
+ override fun onError(error: Exception) {
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ Toast.makeText(this@MainActivity, getString(R.string.settings_generic_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ })
+ }
+
})
}
@@ -233,7 +265,7 @@ class MainActivity : AppCompatActivity() {
progressIndicator.visibility = View.VISIBLE
logbook.logs.add(0, event)
- logbookRepo.saveLogbook(this, logbook, object: LogbookSavedListener{
+ logbookRepo?.saveLogbook(this, logbook, object: LogbookSavedListener{
override fun onLogbookSaved() {
Log.d(TAG, "Logbook saved")
runOnUiThread({
@@ -244,18 +276,54 @@ class MainActivity : AppCompatActivity() {
})
}
- override fun onError(error: String) {
- Log.e(TAG, "ERROR: Logbook was NOT saved!")
+ override fun onIOError(error: IOException) {
runOnUiThread({
progressIndicator.visibility = View.INVISIBLE
-
- Toast.makeText(this@MainActivity, R.string.toast_event_add_error, Toast.LENGTH_SHORT).show()
- adapter.items.remove(event)
- adapter.notifyDataSetChanged()
- savingEvent = false
+ Toast.makeText(this@MainActivity, getString(R.string.settings_network_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ onAddError(event, error.toString())
})
}
+ override fun onWebDAVError(error: SardineException) {
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ if(error.toString().contains("401")) {
+ Toast.makeText(this@MainActivity, getString(R.string.settings_webdav_error_denied), Toast.LENGTH_SHORT).show()
+ onAddError(event, error.toString())
+ } else {
+ Toast.makeText(this@MainActivity, getString(R.string.settings_webdav_error_generic) + error.toString(), Toast.LENGTH_SHORT).show()
+ onAddError(event, error.toString())
+ }
+ })
+ }
+
+ override fun onJSONError(error: JSONException) {
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ Toast.makeText(this@MainActivity, getString(R.string.settings_json_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ onAddError(event, error.toString())
+ })
+ }
+
+ override fun onError(error: Exception) {
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ Toast.makeText(this@MainActivity, getString(R.string.settings_generic_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ onAddError(event, error.toString())
+ })
+ }
+ })
+ }
+
+ private fun onAddError(event: LunaEvent, error: String) {
+ Log.e(TAG, "Logbook was NOT saved!")
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+
+ Toast.makeText(this@MainActivity, R.string.toast_event_add_error, Toast.LENGTH_SHORT).show()
+ adapter.items.remove(event)
+ adapter.notifyDataSetChanged()
+ savingEvent = false
})
}
diff --git a/app/src/main/java/it/danieleverducci/lunatracker/SettingsActivity.kt b/app/src/main/java/it/danieleverducci/lunatracker/SettingsActivity.kt
index 5c8fb3e..239bc4e 100644
--- a/app/src/main/java/it/danieleverducci/lunatracker/SettingsActivity.kt
+++ b/app/src/main/java/it/danieleverducci/lunatracker/SettingsActivity.kt
@@ -1,8 +1,6 @@
package it.danieleverducci.lunatracker
import android.os.Bundle
-import android.os.PersistableBundle
-import android.util.Log
import android.view.View
import android.widget.RadioButton
import android.widget.TextView
@@ -10,15 +8,12 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.thegrizzlylabs.sardineandroid.impl.SardineException
-import it.danieleverducci.lunatracker.entities.Logbook
-import it.danieleverducci.lunatracker.repository.FileLogbookRepository
import it.danieleverducci.lunatracker.repository.LocalSettingsRepository
-import it.danieleverducci.lunatracker.repository.LogbookLoadedListener
import it.danieleverducci.lunatracker.repository.WebDAVLogbookRepository
import okio.IOException
import org.json.JSONException
-class SettingsActivity : AppCompatActivity() {
+open class SettingsActivity : AppCompatActivity() {
protected lateinit var settingsRepository: LocalSettingsRepository
protected lateinit var radioDataLocal: RadioButton
protected lateinit var radioDataWebDAV: RadioButton
@@ -71,75 +66,53 @@ class SettingsActivity : AppCompatActivity() {
}
// Try to connect to WebDAV and check if the save file already exists
- val logbookRepo = WebDAVLogbookRepository(
+ val webDAVLogbookRepo = WebDAVLogbookRepository(
textViewWebDAVUrl.text.toString(),
textViewWebDAVUser.text.toString(),
textViewWebDAVPass.text.toString()
)
progressIndicator.visibility = View.VISIBLE
- logbookRepo.loadLogbook(this, object: LogbookLoadedListener {
- override fun onLogbookLoaded(logbook: Logbook) {
- progressIndicator.visibility = View.INVISIBLE
- // Save file does exist. Settings valid. Save.
- saveSettings()
+ webDAVLogbookRepo.createLogbook(this, object: WebDAVLogbookRepository.LogbookCreatedListener{
+ override fun onLogbookCreated() {
+ 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) {
- // Unable to reach network
runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
Toast.makeText(this@SettingsActivity, getString(R.string.settings_network_error) + error.toString(), Toast.LENGTH_SHORT).show()
})
}
override fun onWebDAVError(error: SardineException) {
- // Save file does not exist, upload the local one
runOnUiThread({
progressIndicator.visibility = View.INVISIBLE
- if (error.toString().contains("401")) {
+ if(error.toString().contains("401")) {
Toast.makeText(this@SettingsActivity, getString(R.string.settings_webdav_error_denied), Toast.LENGTH_SHORT).show()
- } else if (error.toString().contains("404")) {
- // Connection successful, but no existing save. Upload the local one.
- val fileLogbookRepo = FileLogbookRepository()
- fileLogbookRepo.loadLogbook(this@SettingsActivity, object: LogbookLoadedListener {
- override fun onLogbookLoaded(logbook: Logbook) {
- TODO("Not yet implemented")
- }
-
- override fun onIOError(error: IOException) {
- TODO("Not yet implemented")
- }
-
- override fun onWebDAVError(error: SardineException) {
- TODO("Not yet implemented")
- }
-
- override fun onJSONError(error: JSONException) {
- TODO("Not yet implemented")
- }
-
- override fun onError(error: Exception) {
- TODO("Not yet implemented")
- }
-
- })
} else {
Toast.makeText(this@SettingsActivity, getString(R.string.settings_webdav_error_generic) + error.toString(), Toast.LENGTH_SHORT).show()
}
})
-
-
}
override fun onJSONError(error: JSONException) {
- progressIndicator.visibility = View.INVISIBLE
- // Save file exists, but is corrupted
- Toast.makeText(this@SettingsActivity, getString(R.string.settings_json_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ Toast.makeText(this@SettingsActivity, getString(R.string.settings_json_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ })
}
override fun onError(error: Exception) {
- progressIndicator.visibility = View.INVISIBLE
- Toast.makeText(this@SettingsActivity, getString(R.string.settings_generic_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ runOnUiThread({
+ progressIndicator.visibility = View.INVISIBLE
+ Toast.makeText(this@SettingsActivity, getString(R.string.settings_generic_error) + error.toString(), Toast.LENGTH_SHORT).show()
+ })
}
+
})
}
diff --git a/app/src/main/java/it/danieleverducci/lunatracker/repository/FileLogbookRepository.kt b/app/src/main/java/it/danieleverducci/lunatracker/repository/FileLogbookRepository.kt
index 169fd53..87b3444 100644
--- a/app/src/main/java/it/danieleverducci/lunatracker/repository/FileLogbookRepository.kt
+++ b/app/src/main/java/it/danieleverducci/lunatracker/repository/FileLogbookRepository.kt
@@ -15,21 +15,25 @@ class FileLogbookRepository: LogbookRepository {
}
override fun loadLogbook(context: Context, listener: LogbookLoadedListener) {
- val logbook = Logbook()
- val file = File(context.getFilesDir(), "data.json")
try {
- val json = FileInputStream(file).bufferedReader().use { it.readText() }
- val ja = JSONArray(json)
- for (i in 0 until ja.length()) {
- val jo = ja.getJSONObject(i)
- val evt = LunaEvent.fromJson(jo)
- logbook.logs.add(evt)
- }
+ listener.onLogbookLoaded(loadLogbook(context))
} catch (e: FileNotFoundException) {
Log.d(TAG, "No logbook file found")
listener.onIOError(e)
}
- listener.onLogbookLoaded(logbook)
+ }
+
+ fun loadLogbook(context: Context): Logbook {
+ val logbook = Logbook()
+ val file = File(context.getFilesDir(), "data.json")
+ val json = FileInputStream(file).bufferedReader().use { it.readText() }
+ val ja = JSONArray(json)
+ for (i in 0 until ja.length()) {
+ val jo = ja.getJSONObject(i)
+ val evt = LunaEvent.fromJson(jo)
+ logbook.logs.add(evt)
+ }
+ return logbook
}
override fun saveLogbook(
diff --git a/app/src/main/java/it/danieleverducci/lunatracker/repository/LocalSettingsRepository.kt b/app/src/main/java/it/danieleverducci/lunatracker/repository/LocalSettingsRepository.kt
index 98125cf..b48608c 100644
--- a/app/src/main/java/it/danieleverducci/lunatracker/repository/LocalSettingsRepository.kt
+++ b/app/src/main/java/it/danieleverducci/lunatracker/repository/LocalSettingsRepository.kt
@@ -8,7 +8,7 @@ class LocalSettingsRepository(val context: Context) {
companion object {
val SHARED_PREFS_FILE_NAME = "lunasettings"
val SHARED_PREFS_BB_CONTENT = "bbcontent"
- val SHARED_PREFS_DATA_REPO = "webdav_url"
+ 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"
diff --git a/app/src/main/java/it/danieleverducci/lunatracker/repository/LogbookRepository.kt b/app/src/main/java/it/danieleverducci/lunatracker/repository/LogbookRepository.kt
index b5a65bc..316909e 100644
--- a/app/src/main/java/it/danieleverducci/lunatracker/repository/LogbookRepository.kt
+++ b/app/src/main/java/it/danieleverducci/lunatracker/repository/LogbookRepository.kt
@@ -21,5 +21,8 @@ interface LogbookLoadedListener {
interface LogbookSavedListener {
fun onLogbookSaved()
- fun onError(error: String)
+ fun onIOError(error: IOException)
+ fun onWebDAVError(error: SardineException)
+ fun onJSONError(error: JSONException)
+ fun onError(error: Exception)
}
\ No newline at end of file
diff --git a/app/src/main/java/it/danieleverducci/lunatracker/repository/WebDAVLogbookRepository.kt b/app/src/main/java/it/danieleverducci/lunatracker/repository/WebDAVLogbookRepository.kt
index d70be06..5d2aa9a 100644
--- a/app/src/main/java/it/danieleverducci/lunatracker/repository/WebDAVLogbookRepository.kt
+++ b/app/src/main/java/it/danieleverducci/lunatracker/repository/WebDAVLogbookRepository.kt
@@ -10,6 +10,7 @@ import kotlinx.coroutines.Runnable
import org.json.JSONArray
import org.json.JSONException
import java.io.BufferedReader
+import java.io.FileNotFoundException
import java.io.IOException
import java.net.SocketTimeoutException
import kotlin.io.bufferedReader
@@ -31,16 +32,7 @@ class WebDAVLogbookRepository(val webDavURL: String, val username: String, val p
override fun loadLogbook(context: Context, listener: LogbookLoadedListener) {
Thread(Runnable {
try {
- val inputStream = sardine.get("$webDavURL/$FILE_NAME")
- val json = inputStream.bufferedReader().use(BufferedReader::readText)
- inputStream.close()
- val ja = JSONArray(json)
- val logbook = Logbook()
- for (i in 0 until ja.length()) {
- val jo = ja.getJSONObject(i)
- val evt = LunaEvent.fromJson(jo)
- logbook.logs.add(evt)
- }
+ val logbook = loadLogbook(context)
listener.onLogbookLoaded(logbook)
} catch (e: SardineException) {
Log.e(TAG, e.toString())
@@ -60,31 +52,115 @@ class WebDAVLogbookRepository(val webDavURL: String, val username: String, val p
}).start()
}
+ private fun loadLogbook(context: Context): Logbook {
+ val inputStream = sardine.get("$webDavURL/$FILE_NAME")
+ val json = inputStream.bufferedReader().use(BufferedReader::readText)
+ inputStream.close()
+ val ja = JSONArray(json)
+ val logbook = Logbook()
+ for (i in 0 until ja.length()) {
+ val jo = ja.getJSONObject(i)
+ val evt = LunaEvent.fromJson(jo)
+ logbook.logs.add(evt)
+ }
+ return logbook
+ }
+
override fun saveLogbook(context: Context, logbook: Logbook, listener: LogbookSavedListener) {
Thread(Runnable {
- // Lock logbook on WebDAV to avoid concurrent changes
- //sardine.lock(getUrl())
- // Reload logbook from WebDAV
- // Merge logbooks (based on time)
- // Write logbook
- // Unlock logbook on WebDAV
- //sardine.unlock(getUrl())
-
- val ja = JSONArray()
- for (l in logbook.logs) {
- ja.put(l.toJson())
- }
try {
- sardine.put(getUrl(), ja.toString().toByteArray())
+ saveLogbook(context, logbook)
listener.onLogbookSaved()
} catch (e: SardineException) {
- listener.onError(e.toString())
+ 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: JSONException) {
+ Log.e(TAG, e.toString())
+ listener.onJSONError(e)
+ } catch (e: Exception) {
+ listener.onError(e)
}
}).start()
}
+ private fun saveLogbook(context: Context, logbook: Logbook) {
+ // Lock logbook on WebDAV to avoid concurrent changes
+ //sardine.lock(getUrl())
+ // Reload logbook from WebDAV
+ // Merge logbooks (based on time)
+ // Write logbook
+ // Unlock logbook on WebDAV
+ //sardine.unlock(getUrl())
+
+ val ja = JSONArray()
+ for (l in logbook.logs) {
+ ja.put(l.toJson())
+ }
+ sardine.put(getUrl(), ja.toString().toByteArray())
+ }
+
+ /**
+ * 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).
+ */
+ fun createLogbook(context: Context, listener: LogbookCreatedListener) {
+ Thread(Runnable {
+ try {
+ loadLogbook(context)
+ listener.onLogbookCreated()
+ } catch (e: SardineException) {
+ if (e.toString().contains("404")) {
+ // Connection successful, but no existing save. Upload the local one.
+ try {
+ val flr = FileLogbookRepository()
+ val logbook = flr.loadLogbook(context)
+ saveLogbook(context, logbook)
+ Log.d(TAG, "Local logbook file found, uploaded")
+ listener.onLogbookCreated()
+ } catch (e: FileNotFoundException) {
+ Log.d(TAG, "No local logbook file found, uploading empty file")
+ saveLogbook(context, Logbook())
+ listener.onLogbookCreated()
+ } catch (e: SardineException) {
+ Log.e(TAG, "Unable to upload logbook: $e")
+ listener.onWebDAVError(e)
+ }
+ } else {
+ 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: JSONException) {
+ Log.e(TAG, e.toString())
+ listener.onJSONError(e)
+ } catch (e: Exception) {
+ listener.onError(e)
+ }
+ }).start()
+ }
+
private fun getUrl(): String {
return "$webDavURL/$FILE_NAME"
}
+
+
+ interface LogbookCreatedListener {
+ fun onLogbookCreated()
+ fun onIOError(error: okio.IOException)
+ fun onWebDAVError(error: SardineException)
+ fun onJSONError(error: JSONException)
+ fun onError(error: Exception)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7069cf4..8122f76 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -54,8 +54,10 @@
Username
Password
Impossibile raggiungere il server:
- Nome utente o password sbagliati
+ Nome utente o password WebDAV sbagliati
Si è verificato un errore tentando di accedere al server WebDAV:
+ Impossibile creare un file di salvataggio sul server WebDAV:
+ Connessione al server WebDAV avvenuta con successo
Sul server esiste un salvataggio, ma è corrotto o illeggibile. Cancellare il file
Si è verificato un errore:
\ No newline at end of file