add export/import of my list

fixes #39
This commit is contained in:
Jannik 2021-05-26 19:46:46 +02:00
parent 68d462eeee
commit 7ce67f57cd
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
5 changed files with 99 additions and 9 deletions

View File

@ -10,8 +10,8 @@ android {
applicationId "org.mosad.teapod" applicationId "org.mosad.teapod"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 30 targetSdkVersion 30
versionCode 4100 //00.04.100 versionCode 4180 //00.04.100
versionName "0.4.1" versionName "0.4.2-alpha1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resValue "string", "build_time", buildTime() resValue "string", "build_time", buildTime()

View File

@ -1,5 +1,6 @@
package org.mosad.teapod.ui.activity.main.fragments package org.mosad.teapod.ui.activity.main.fragments
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
@ -7,6 +8,7 @@ import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
@ -14,20 +16,24 @@ import com.afollestad.materialdialogs.list.listItemsSingleChoice
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.mosad.teapod.BuildConfig import org.mosad.teapod.BuildConfig
import org.mosad.teapod.ui.activity.main.MainActivity
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.databinding.FragmentAccountBinding import org.mosad.teapod.databinding.FragmentAccountBinding
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.preferences.EncryptedPreferences import org.mosad.teapod.preferences.EncryptedPreferences
import org.mosad.teapod.preferences.Preferences import org.mosad.teapod.preferences.Preferences
import org.mosad.teapod.ui.activity.main.MainActivity
import org.mosad.teapod.ui.components.LoginDialog import org.mosad.teapod.ui.components.LoginDialog
import org.mosad.teapod.util.DataTypes.Theme import org.mosad.teapod.util.DataTypes.Theme
import org.mosad.teapod.util.StorageController
import org.mosad.teapod.util.showFragment import org.mosad.teapod.util.showFragment
class AccountFragment : Fragment() { class AccountFragment : Fragment() {
private lateinit var binding: FragmentAccountBinding private lateinit var binding: FragmentAccountBinding
private val exportFileCode = 1111
private val importFileCode = 1122
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentAccountBinding.inflate(inflater, container, false) binding = FragmentAccountBinding.inflate(inflater, container, false)
return binding.root return binding.root
@ -60,6 +66,30 @@ class AccountFragment : Fragment() {
initActions() initActions()
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// return if the result was not ok
if (resultCode != Activity.RESULT_OK) {
Log.e(javaClass.name, "Error while computing result. Result code is: $resultCode")
return
}
when(requestCode) {
exportFileCode -> data?.data?.also { uri ->
StorageController.exportMyList(requireContext(), uri)
}
importFileCode -> data?.data?.also { uri ->
val success = StorageController.importMyList(requireContext(), uri)
if (success == 0) {
Toast.makeText(
context, getString(R.string.import_data_success),
Toast.LENGTH_SHORT
).show()
}
}
}
}
private fun initActions() { private fun initActions() {
binding.linearAccountLogin.setOnClickListener { binding.linearAccountLogin.setOnClickListener {
showLoginDialog(true) showLoginDialog(true)
@ -86,11 +116,20 @@ class AccountFragment : Fragment() {
} }
binding.linearExportData.setOnClickListener { binding.linearExportData.setOnClickListener {
println("TODO") val i = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/json"
putExtra(Intent.EXTRA_TITLE, "my-list.json")
}
startActivityForResult(i, exportFileCode)
} }
binding.linearImportData.setOnClickListener { binding.linearImportData.setOnClickListener {
println("TODO") val i = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
}
startActivityForResult(i, importFileCode)
} }
} }
@ -120,7 +159,7 @@ class AccountFragment : Fragment() {
when(index) { when(index) {
0 -> Preferences.saveTheme(context, Theme.LIGHT) 0 -> Preferences.saveTheme(context, Theme.LIGHT)
1 -> Preferences.saveTheme(context, Theme.DARK) 1 -> Preferences.saveTheme(context, Theme.DARK)
else -> Preferences.saveTheme(context, Theme.LIGHT) else -> Preferences.saveTheme(context, Theme.DARK)
} }
(activity as MainActivity).restart() (activity as MainActivity).restart()

View File

@ -1,12 +1,18 @@
package org.mosad.teapod.util package org.mosad.teapod.util
import android.content.Context import android.content.Context
import android.net.Uri
import android.util.Log import android.util.Log
import android.widget.Toast
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.JsonParser import com.google.gson.JsonParser
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.mosad.teapod.R
import java.io.File import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.lang.Exception import java.lang.Exception
import java.net.URI
/** /**
* This controller contains the logic for permanently saved data. * This controller contains the logic for permanently saved data.
@ -19,6 +25,10 @@ object StorageController {
val myList = ArrayList<Int>() // a list of saved mediaIds val myList = ArrayList<Int>() // a list of saved mediaIds
fun load(context: Context) { fun load(context: Context) {
loadMyList(context)
}
fun loadMyList(context: Context) {
val file = File(context.filesDir, fileNameMyList) val file = File(context.filesDir, fileNameMyList)
if (!file.exists()) runBlocking { saveMyList(context).join() } if (!file.exists()) runBlocking { saveMyList(context).join() }
@ -30,7 +40,6 @@ object StorageController {
myList.clear() myList.clear()
Log.e(javaClass.name, "Parsing of My-List failed.") Log.e(javaClass.name, "Parsing of My-List failed.")
} }
} }
fun saveMyList(context: Context): Job { fun saveMyList(context: Context): Job {
@ -41,4 +50,44 @@ object StorageController {
} }
} }
fun exportMyList(context: Context, uri: Uri) {
try {
context.contentResolver.openFileDescriptor(uri, "w")?.use {
FileWriter(it.fileDescriptor).use { writer ->
writer.write(Gson().toJson(myList.distinct()))
}
}
} catch (ex: Exception) {
Log.e(javaClass.name, "Exporting my list failed.", ex)
}
}
/**
* import my list from a (previously exported) json file
* @param context the current context
* @param uri the uri of the selected file
* @return 0 if import was successfull, else 1
*/
fun importMyList(context: Context, uri: Uri): Int {
try {
val text = context.contentResolver.openFileDescriptor(uri, "r")?.use {
FileReader(it.fileDescriptor).use { reader ->
reader.readText()
}
}
myList.clear()
myList.addAll(JsonParser.parseString(text).asJsonArray.map { it.asInt }.distinct())
// after the list has been imported also save it
saveMyList(context)
} catch (ex: Exception) {
myList.clear()
Log.e(javaClass.name, "Importing my list failed.", ex)
return 1
}
return 0
}
} }

View File

@ -51,6 +51,7 @@
<string name="export_data_desc">Speichere "meine Liste" in eine Datei</string> <string name="export_data_desc">Speichere "meine Liste" in eine Datei</string>
<string name="import_data">Daten importieren</string> <string name="import_data">Daten importieren</string>
<string name="import_data_desc">Lade "meine Liste" aus einer Datei</string> <string name="import_data_desc">Lade "meine Liste" aus einer Datei</string>
<string name="import_data_success">"meine Liste" erfolgreich importiert</string>
<!-- about fragment --> <!-- about fragment -->
<string name="version">Version</string> <string name="version">Version</string>

View File

@ -59,9 +59,10 @@
<string name="theme_dark">Dark</string> <string name="theme_dark">Dark</string>
<string name="dev_settings">Developer Settings</string> <string name="dev_settings">Developer Settings</string>
<string name="export_data">export data</string> <string name="export_data">export data</string>
<string name="export_data_desc">export my list to a file</string> <string name="export_data_desc">export "my list" to a file</string>
<string name="import_data">import data</string> <string name="import_data">import data</string>
<string name="import_data_desc">import my list from a file</string> <string name="import_data_desc">import "my list" from a file</string>
<string name="import_data_success">imported "my list" successfully</string>
<!-- about fragment --> <!-- about fragment -->