From 55c74c7565937e6274644f209fb066e2deb86d9a Mon Sep 17 00:00:00 2001 From: kunfei Date: Sun, 9 Feb 2020 09:37:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/legado/app/help/storage/Backup.kt | 4 - .../legado/app/help/storage/ImportOldData.kt | 149 ++++++++++++++++++ .../io/legado/app/help/storage/Restore.kt | 81 ---------- .../app/ui/config/BackupConfigFragment.kt | 132 +--------------- .../legado/app/ui/config/BackupRestoreUi.kt | 32 ++++ .../ui/replacerule/ReplaceRuleViewModel.kt | 6 +- 6 files changed, 186 insertions(+), 218 deletions(-) create mode 100644 app/src/main/java/io/legado/app/help/storage/ImportOldData.kt diff --git a/app/src/main/java/io/legado/app/help/storage/Backup.kt b/app/src/main/java/io/legado/app/help/storage/Backup.kt index 82485c363..6a02fb696 100644 --- a/app/src/main/java/io/legado/app/help/storage/Backup.kt +++ b/app/src/main/java/io/legado/app/help/storage/Backup.kt @@ -19,10 +19,6 @@ object Backup { val backupPath = App.INSTANCE.filesDir.absolutePath + File.separator + "backup" - val defaultPath by lazy { - FileUtils.getSdCardPath() + File.separator + "YueDu" - } - val legadoPath by lazy { FileUtils.getSdCardPath() + File.separator + "YueDu3.0" } diff --git a/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt b/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt new file mode 100644 index 000000000..7329705e9 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt @@ -0,0 +1,149 @@ +package io.legado.app.help.storage + +import android.content.Context +import android.net.Uri +import androidx.documentfile.provider.DocumentFile +import io.legado.app.App +import io.legado.app.data.entities.BookSource +import io.legado.app.data.entities.ReplaceRule +import io.legado.app.help.coroutine.Coroutine +import io.legado.app.utils.DocumentUtils +import io.legado.app.utils.FileUtils +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.jetbrains.anko.toast +import java.io.File + +object ImportOldData { + val yueDuPath by lazy { + FileUtils.getSdCardPath() + File.separator + "YueDu" + } + + fun import(context: Context) { + GlobalScope.launch(Dispatchers.IO) { + try {// 导入书架 + val shelfFile = + FileUtils.createFileIfNotExist(yueDuPath + File.separator + "myBookShelf.json") + val json = shelfFile.readText() + val importCount = importOldBookshelf(json) + withContext(Dispatchers.Main) { + context.toast("成功导入书籍${importCount}") + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + context.toast("导入书籍失败\n${e.localizedMessage}") + } + } + + try {// Book source + val sourceFile = + FileUtils.createFileIfNotExist(yueDuPath + File.separator + "myBookSource.json") + val json = sourceFile.readText() + val importCount = importOldSource(json) + withContext(Dispatchers.Main) { + context.toast("成功导入书源${importCount}") + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + context.toast("导入源失败\n${e.localizedMessage}") + } + } + + try {// Replace rules + val ruleFile = + FileUtils.createFileIfNotExist(yueDuPath + File.separator + "myBookReplaceRule.json") + val json = ruleFile.readText() + val importCount = importOldReplaceRule(json) + withContext(Dispatchers.Main) { + context.toast("成功导入替换规则${importCount}") + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + context.toast("导入替换规则失败\n${e.localizedMessage}") + } + } + } + } + + fun importUri(uri: Uri) { + Coroutine.async { + DocumentFile.fromTreeUri(App.INSTANCE, uri)?.listFiles()?.forEach { + when (it.name) { + "myBookShelf.json" -> + try { + DocumentUtils.readText(App.INSTANCE, it.uri)?.let { json -> + val importCount = importOldBookshelf(json) + withContext(Dispatchers.Main) { + App.INSTANCE.toast("成功导入书籍${importCount}") + } + } + } catch (e: java.lang.Exception) { + withContext(Dispatchers.Main) { + App.INSTANCE.toast("导入书籍失败\n${e.localizedMessage}") + } + } + "myBookSource.json" -> + try { + DocumentUtils.readText(App.INSTANCE, it.uri)?.let { json -> + val importCount = importOldSource(json) + withContext(Dispatchers.Main) { + App.INSTANCE.toast("成功导入书源${importCount}") + } + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + App.INSTANCE.toast("导入源失败\n${e.localizedMessage}") + } + } + "myBookReplaceRule.json" -> + try { + DocumentUtils.readText(App.INSTANCE, it.uri)?.let { json -> + val importCount = importOldReplaceRule(json) + withContext(Dispatchers.Main) { + App.INSTANCE.toast("成功导入替换规则${importCount}") + } + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + App.INSTANCE.toast("导入替换规则失败\n${e.localizedMessage}") + } + } + } + } + } + } + + fun importOldBookshelf(json: String): Int { + val books = OldBook.toNewBook(json) + App.db.bookDao().insert(*books.toTypedArray()) + return books.size + } + + fun importOldSource(json: String): Int { + val bookSources = mutableListOf() + val items: List> = Restore.jsonPath.parse(json).read("$") + for (item in items) { + val jsonItem = Restore.jsonPath.parse(item) + OldRule.jsonToBookSource(jsonItem.jsonString())?.let { + bookSources.add(it) + } + } + App.db.bookSourceDao().insert(*bookSources.toTypedArray()) + return bookSources.size + } + + fun importOldReplaceRule(json: String): Int { + val replaceRules = mutableListOf() + val items: List> = Restore.jsonPath.parse(json).read("$") + for (item in items) { + val jsonItem = Restore.jsonPath.parse(item) + OldRule.jsonToReplaceRule(jsonItem.jsonString())?.let { + replaceRules.add(it) + } + } + App.db.replaceRuleDao().insert(*replaceRules.toTypedArray()) + return replaceRules.size + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/storage/Restore.kt b/app/src/main/java/io/legado/app/help/storage/Restore.kt index edc0c1478..b7fa2a68a 100644 --- a/app/src/main/java/io/legado/app/help/storage/Restore.kt +++ b/app/src/main/java/io/legado/app/help/storage/Restore.kt @@ -13,12 +13,8 @@ import io.legado.app.data.entities.* import io.legado.app.help.ReadBookConfig import io.legado.app.utils.* import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.Dispatchers.Main -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.jetbrains.anko.defaultSharedPreferences -import org.jetbrains.anko.toast import java.io.File object Restore { @@ -109,81 +105,4 @@ object Restore { return null } - fun importYueDuData(context: Context) { - GlobalScope.launch(IO) { - try {// 导入书架 - val shelfFile = - FileUtils.createFileIfNotExist(Backup.defaultPath + File.separator + "myBookShelf.json") - val json = shelfFile.readText() - val importCount = importOldBookshelf(json) - withContext(Main) { - context.toast("成功导入书籍${importCount}") - } - } catch (e: Exception) { - withContext(Main) { - context.toast("导入书籍失败\n${e.localizedMessage}") - } - } - - try {// Book source - val sourceFile = - FileUtils.createFileIfNotExist(Backup.defaultPath + File.separator + "myBookSource.json") - val json = sourceFile.readText() - val importCount = importOldSource(json) - withContext(Main) { - context.toast("成功导入书源${importCount}") - } - } catch (e: Exception) { - withContext(Main) { - context.toast("导入源失败\n${e.localizedMessage}") - } - } - - try {// Replace rules - val ruleFile = - FileUtils.createFileIfNotExist(Backup.defaultPath + File.separator + "myBookReplaceRule.json") - val json = ruleFile.readText() - val importCount = importOldReplaceRule(json) - withContext(Main) { - context.toast("成功导入替换规则${importCount}") - } - } catch (e: Exception) { - withContext(Main) { - context.toast("导入替换规则失败\n${e.localizedMessage}") - } - } - } - } - - fun importOldBookshelf(json: String): Int { - val books = OldBook.toNewBook(json) - App.db.bookDao().insert(*books.toTypedArray()) - return books.size - } - - fun importOldSource(json: String): Int { - val bookSources = mutableListOf() - val items: List> = jsonPath.parse(json).read("$") - for (item in items) { - val jsonItem = jsonPath.parse(item) - OldRule.jsonToBookSource(jsonItem.jsonString())?.let { - bookSources.add(it) - } - } - App.db.bookSourceDao().insert(*bookSources.toTypedArray()) - return bookSources.size - } - - fun importOldReplaceRule(json: String): Int { - val replaceRules = mutableListOf() - val items: List> = jsonPath.parse(json).read("$") - for (item in items) { - val jsonItem = jsonPath.parse(item) - OldRule.jsonToReplaceRule(jsonItem.jsonString())?.let { - replaceRules.add(it) - } - } - App.db.replaceRuleDao().insert(*replaceRules.toTypedArray()) - return replaceRules.size - } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/config/BackupConfigFragment.kt b/app/src/main/java/io/legado/app/ui/config/BackupConfigFragment.kt index d7a9c54d2..9df96e3f2 100644 --- a/app/src/main/java/io/legado/app/ui/config/BackupConfigFragment.kt +++ b/app/src/main/java/io/legado/app/ui/config/BackupConfigFragment.kt @@ -1,51 +1,26 @@ package io.legado.app.ui.config -import android.app.Activity.RESULT_OK import android.content.Intent import android.content.SharedPreferences -import android.net.Uri -import android.os.Build import android.os.Bundle import android.text.InputType import android.view.View -import androidx.documentfile.provider.DocumentFile import androidx.preference.EditTextPreference import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import io.legado.app.R import io.legado.app.constant.PreferKey -import io.legado.app.help.IntentHelp -import io.legado.app.help.permission.Permissions -import io.legado.app.help.permission.PermissionsCompat -import io.legado.app.help.storage.Restore -import io.legado.app.lib.dialogs.alert -import io.legado.app.lib.dialogs.noButton -import io.legado.app.lib.dialogs.yesButton import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.accentColor import io.legado.app.ui.filechooser.FileChooserDialog -import io.legado.app.utils.DocumentUtils -import io.legado.app.utils.LogUtils -import io.legado.app.utils.applyTint import io.legado.app.utils.getPrefString -import kotlinx.coroutines.* -import kotlinx.coroutines.Dispatchers.IO -import org.jetbrains.anko.toast -import kotlin.coroutines.CoroutineContext class BackupConfigFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener, - FileChooserDialog.CallBack, - CoroutineScope { - private lateinit var job: Job - private val oldDataRequestCode = 11 - - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main + FileChooserDialog.CallBack { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - job = Job() addPreferencesFromResource(R.xml.pref_config_backup) findPreference(PreferKey.webDavUrl)?.let { it.setOnBindEditTextListener { editText -> @@ -80,7 +55,6 @@ class BackupConfigFragment : PreferenceFragmentCompat(), override fun onDestroy() { super.onDestroy() preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this) - job.cancel() } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { @@ -132,107 +106,11 @@ class BackupConfigFragment : PreferenceFragmentCompat(), PreferKey.backupPath -> BackupRestoreUi.selectBackupFolder(this) "web_dav_backup" -> BackupRestoreUi.backup(this) "web_dav_restore" -> BackupRestoreUi.restore(this) - "import_old" -> importOldData() + "import_old" -> BackupRestoreUi.importOldData(this) } return super.onPreferenceTreeClick(preference) } - private fun importOldData() { - try { - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - startActivityForResult(intent, oldDataRequestCode) - } catch (e: Exception) { - needInstallApps { - alert(title = "导入") { - message = "是否导入旧版本数据" - yesButton { - PermissionsCompat.Builder(this@BackupConfigFragment) - .addPermissions(*Permissions.Group.STORAGE) - .rationale(R.string.tip_perm_request_storage) - .onGranted { - Restore.importYueDuData(requireContext()) - } - .request() - } - noButton { - } - }.show().applyTint() - } - } - } - - private fun importOldData(uri: Uri) { - launch(IO) { - DocumentFile.fromTreeUri(requireContext(), uri)?.listFiles()?.forEach { - when (it.name) { - "myBookShelf.json" -> - try { - DocumentUtils.readText(requireContext(), it.uri)?.let { json -> - val importCount = Restore.importOldBookshelf(json) - withContext(Dispatchers.Main) { - requireContext().toast("成功导入书籍${importCount}") - } - } - } catch (e: java.lang.Exception) { - withContext(Dispatchers.Main) { - requireContext().toast("导入书籍失败\n${e.localizedMessage}") - } - } - "myBookSource.json" -> - try { - DocumentUtils.readText(requireContext(), it.uri)?.let { json -> - val importCount = Restore.importOldSource(json) - withContext(Dispatchers.Main) { - requireContext().toast("成功导入书源${importCount}") - } - } - } catch (e: Exception) { - withContext(Dispatchers.Main) { - requireContext().toast("导入源失败\n${e.localizedMessage}") - } - } - "myBookReplaceRule.json" -> - try { - DocumentUtils.readText(requireContext(), it.uri)?.let { json -> - val importCount = Restore.importOldReplaceRule(json) - withContext(Dispatchers.Main) { - requireContext().toast("成功导入替换规则${importCount}") - } - } - } catch (e: Exception) { - withContext(Dispatchers.Main) { - requireContext().toast("导入替换规则失败\n${e.localizedMessage}") - } - } - } - } - } - } - - private fun needInstallApps(callback: () -> Unit) { - - fun canRequestPackageInstalls(): Boolean { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { - return requireContext().packageManager.canRequestPackageInstalls() - } - return true - } - if (!canRequestPackageInstalls()) { - alert(title = "开启权限提示") { - message = "需要打开「安装外部来源应用」权限才能导入旧版数据,请去设置中开启" - yesButton { - IntentHelp.toInstallUnknown(requireContext()) - } - noButton { - } - }.show().applyTint() - } else { - LogUtils.d("xxx", "import old") - callback() - } - } - override fun onFilePicked(requestCode: Int, currentPath: String) { BackupRestoreUi.onFilePicked(requestCode, currentPath) } @@ -240,11 +118,5 @@ class BackupConfigFragment : PreferenceFragmentCompat(), override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) BackupRestoreUi.onActivityResult(requestCode, resultCode, data) - when (requestCode) { - oldDataRequestCode -> - if (resultCode == RESULT_OK) data?.data?.let { uri -> - importOldData(uri) - } - } } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt b/app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt index a15f4ea33..5fde57fb7 100644 --- a/app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt +++ b/app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt @@ -13,10 +13,14 @@ import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.permission.Permissions import io.legado.app.help.permission.PermissionsCompat import io.legado.app.help.storage.Backup +import io.legado.app.help.storage.ImportOldData import io.legado.app.help.storage.Restore import io.legado.app.help.storage.WebDavHelp import io.legado.app.lib.dialogs.alert +import io.legado.app.lib.dialogs.noButton +import io.legado.app.lib.dialogs.yesButton import io.legado.app.ui.filechooser.FileChooserDialog +import io.legado.app.utils.applyTint import io.legado.app.utils.getPrefString import io.legado.app.utils.isContentPath import io.legado.app.utils.toast @@ -27,6 +31,7 @@ object BackupRestoreUi { private const val backupSelectRequestCode = 22 private const val restoreSelectRequestCode = 33 + private const val oldDataRequestCode = 11 fun backup(fragment: Fragment) { val backupPath = AppConfig.backupPath @@ -163,6 +168,29 @@ object BackupRestoreUi { }.show() } + fun importOldData(fragment: Fragment) { + try { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + fragment.startActivityForResult(intent, oldDataRequestCode) + } catch (e: Exception) { + fragment.alert(title = "导入") { + message = "是否导入旧版本数据" + yesButton { + PermissionsCompat.Builder(fragment) + .addPermissions(*Permissions.Group.STORAGE) + .rationale(R.string.tip_perm_request_storage) + .onGranted { + ImportOldData.import(fragment.requireContext()) + } + .request() + } + noButton { + } + }.show().applyTint() + } + } + fun onFilePicked(requestCode: Int, currentPath: String) { when (requestCode) { backupSelectRequestCode -> { @@ -214,6 +242,10 @@ object BackupRestoreUi { } } } + oldDataRequestCode -> + if (resultCode == RESULT_OK) data?.data?.let { uri -> + ImportOldData.importUri(uri) + } } } diff --git a/app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleViewModel.kt b/app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleViewModel.kt index 9d1f2f1a0..42217ec18 100644 --- a/app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleViewModel.kt @@ -8,7 +8,7 @@ import io.legado.app.base.BaseViewModel import io.legado.app.data.entities.ReplaceRule import io.legado.app.help.http.HttpHelper import io.legado.app.help.storage.Backup -import io.legado.app.help.storage.Restore +import io.legado.app.help.storage.ImportOldData import io.legado.app.utils.FileUtils import io.legado.app.utils.GSON import io.legado.app.utils.isAbsUrl @@ -22,10 +22,10 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application execute { if (text.isAbsUrl()) { HttpHelper.simpleGet(text)?.let { - Restore.importOldReplaceRule(it) + ImportOldData.importOldReplaceRule(it) } } else { - Restore.importOldReplaceRule(text) + ImportOldData.importOldReplaceRule(text) } }.onError { showMsg(it.localizedMessage ?: "ERROR")