mirror of
https://github.com/gedoor/legado.git
synced 2024-09-03 09:55:00 +08:00
优化
This commit is contained in:
parent
7c2a5b28e7
commit
55c74c7565
@ -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"
|
||||
}
|
||||
|
149
app/src/main/java/io/legado/app/help/storage/ImportOldData.kt
Normal file
149
app/src/main/java/io/legado/app/help/storage/ImportOldData.kt
Normal file
@ -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<BookSource>()
|
||||
val items: List<Map<String, Any>> = 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<ReplaceRule>()
|
||||
val items: List<Map<String, Any>> = 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
|
||||
}
|
||||
}
|
@ -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<BookSource>()
|
||||
val items: List<Map<String, Any>> = 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<ReplaceRule>()
|
||||
val items: List<Map<String, Any>> = 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
|
||||
}
|
||||
}
|
@ -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<EditTextPreference>(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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user